# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Autonomous solar controller running on a **Kincony KC868-A2 (ESP32)** board. It reads data from an **Epever Tracer 4210N** solar regulator via RS485 Modbus, controls 2 relays using a programmable rule engine, and hosts a mobile-first web interface over a WiFi access point. No internet connection required.

> **Note:** `platformio.ini` currently targets `espressif8266/esp_wroom_02` but the hardware is an **ESP32** (espressif32). This will need to be corrected before flashing.

## Build Commands

```bash
pio run                        # Compile
pio run --target upload        # Compile and flash
pio run --target monitor       # Open serial monitor
pio run --target uploadfs      # Upload /data filesystem (LittleFS)
pio run --target clean         # Clean build artifacts
```

The full project specification is at `../vscode/esp-32-epever/consigne.md` (outside the PlatformIO project root).

## Architecture

System flow:
```
Epever 4210N (RS485 Modbus) → ESP32 → Rule Engine → Relays 1/2
                                   ↓
                              Web UI (WiFi AP 192.168.4.1)
                                   ↓
                              Smartphone
```

### Module structure (target)

| File | Responsibility |
|------|----------------|
| `src/main.cpp` | Init, main loop dispatcher |
| `src/wifi.cpp` | WiFi AP setup (`SSID: KC868_SOLAR`) |
| `src/webserver.cpp` | HTTP server, REST endpoints |
| `src/ota.cpp` | OTA firmware update (`/update`) |
| `src/modbus.cpp` | Non-blocking RS485 Modbus reads from Epever |
| `src/relais.cpp` | Relay GPIO control |
| `src/rules.cpp` | JSON rule engine (LittleFS) |
| `src/buttons.cpp` | DI1/DI2 dry-contact inputs |
| `src/sleep.cpp` | Deep sleep / power management |
| `data/` | LittleFS web assets (index.html, style.css, app.js, rules.json) |

### System state

```cpp
struct SystemState {
    float battery;        // Battery voltage (V) — register 0x3104
    float pv;             // Panel voltage (V) — register 0x3100
    bool sun;             // Day/night — register 0x200C
    bool relay1, relay2;
    bool di1, di2;        // DI1=auto/manual toggle, DI2=manual relay
    bool rs485_ok;
    unsigned long last_update;
};
```

### Rule engine (JSON in LittleFS)

```json
[{ "enabled": true, "sun": true, "battery": 13.0, "relay": 1, "state": true, "delay": 0 }]
```

Conditions: sunlight, battery threshold, relay state, DI state.
Actions: relay ON/OFF with optional delay.

## Critical Design Constraints

**No blocking code anywhere.** RS485 errors must never stall the web server, relays, buttons, or rule engine.

```cpp
// FORBIDDEN
while (!response) { }
delay(x);

// REQUIRED
millis()  // for all timing
```

RS485 reads must have short timeouts, limited retries, and fall back to the last valid cached value on error.

## Hardware Reference

**RS485 wiring:**
```
Epever RS485 A (D+) → KC868-A2 A1/RXI
Epever RS485 B (D-) → KC868-A2 B1/TXO
Epever GND          → KC868-A2 GND
```
⚠️ Never connect the RJ45 Epever power supply rail.

**Modbus parameters:** baud=9600, slave address=1, RTU mode, half-duplex.

**Key Modbus registers:**

| Data | Register |
|------|----------|
| PV voltage | 0x3100 |
| PV current | 0x3101 |
| Battery voltage | 0x3104 |
| Day/night state | 0x200C |

## Power Modes

| Mode | WiFi | Web | Epever | Rules | Consumption |
|------|------|-----|--------|-------|-------------|
| Day | ON | ON | Active | Active | 1.8–4 W |
| Night | OFF | OFF | Periodic wake | Suspended | 0.1–0.6 W |

Deep sleep = ESP32 reboot on wake-up. UART unavailable during sleep. Relays retain state.

## Development Phases

1. WiFi + Web UI + OTA
2. Relay control
3. Button handling (DI1/DI2)
4. RS485 Modbus reads
5. Rule engine
6. Sleep / power optimization

GPIO assignments must be validated against the KC868-A2 schematic images in `../vscode/esp-32-epever/photo/` before use.
