# 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.