Files
kc868-a2_solar/README.md
T
gilles df350c10f5 Ajout README.md — documentation complète du projet
Couvre : matériel, brochage, architecture, API REST, bibliothèques,
commandes build/flash, configuration runtime, registres Modbus,
et section TODO (MQTT, version firmware, audit code mort, PSK WireGuard…)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 19:29:55 +02:00

11 KiB
Raw Blame History

KC868-A2 — Contrôleur Solaire ESP32

Système embarqué autonome de supervision et de pilotage d'une installation solaire.
Fonctionne sans internet, sans cloud, sans application mobile — tout passe par une interface web hébergée sur l'ESP32.


Matériel

Composant Référence
Contrôleur Kincony KC868-A2 (ESP32-WROOM-32)
Régulateur solaire Epever Tracer 4210N (MPPT 40A)
Communication RS485 Modbus RTU
Interface RJ45 8P8C côté Epever

Brochage RS485

Epever RJ45 (vue de face, languette bas)   KC868-A2
  Pin 3 / 4  → RS485-B (D-)              → B
  Pin 5 / 6  → RS485-A (D+)              → A+
  Pin 7 / 8  → GND                       → GND (optionnel)
  Pin 1 / 2  → +7.5V  ⚠ NE PAS CONNECTER

Paramètres Modbus : esclave 1, 115200 bps, 8N1, RTU, half-duplex.

GPIO ESP32

Signal Pin Note
Relais 1 GPIO 15
Relais 2 GPIO 2 Pin de strapping boot — reste HIGH au démarrage
RS485 TX GPIO 32
RS485 RX GPIO 35 Input only
Entrée DI1 GPIO 36 Input only
Entrée DI2 GPIO 39 Input only

Fonctionnalités

Acquisition de données (Modbus RTU)

  • Tension / courant / puissance panneau solaire (PV)
  • Tension / courant / puissance sortie de charge (load)
  • Tension, SOC (%), température et statut batterie
  • Énergie générée/consommée (jour et total, kWh)
  • Détection jour/nuit et horloge interne de l'Epever
  • Fréquence de lecture configurable (mode jour / mode nuit)

Commande

  • 2 relais commandés manuellement ou automatiquement
  • 2 entrées numériques (DI1, DI2) — contacts secs
  • État des relais sauvegardé en NVS (survit aux coupures)

Moteur de règles

Règles JSON stockées dans LittleFS. Chaque règle combine :

  • Déclencheurs : ensoleillement (jour/nuit), état DI1/DI2
  • Conditions : seuil batterie min/max, seuil PV min/max
  • Action : relais ON/OFF avec délai optionnel et hystérésis

Interface web (mobile-first)

Accessible sur http://192.168.4.1 (AP) ou http://pv.local (mDNS) :

Onglet Contenu
Dashboard Relais, entrées, PV, batterie, load, énergie
Règles Liste, ajout, activation/désactivation, suppression
Config Relais manuels, noms, sleep, OTA, WiFi, WireGuard VPN
Historique Graphes 4h (1 min) et 30h (5 min) exportables CSV
Config EPEVER Lecture/écriture des 18 registres holding du régulateur
Debug Journal série en mémoire

Réseau

  • Mode AP permanent : kc868-a2 / soleil12192.168.4.1
  • Mode STA optionnel : connexion à un réseau WiFi existant (scan + NVS)
  • Portail captif : iOS/Android/Windows ouvrent l'UI automatiquement
  • mDNS : pv.local configurable depuis l'interface

VPN WireGuard (optionnel, désactivé par défaut)

Tunnel chiffré vers un serveur WireGuard distant.
Configuration complète depuis l'onglet Config — clés, endpoint, IP locale, keepalive.
Actif uniquement quand la STA WiFi est connectée ; l'accès local via AP reste toujours disponible.

Deep sleep

Mode économie d'énergie configurable : l'ESP32 se rendort entre les cycles de mesure la nuit (PV < seuil), se réveille périodiquement et évalue les règles.

OTA

Mise à jour firmware et filesystem via http://192.168.4.1/update (ElegantOTA).


Architecture logicielle

src/
├── main.cpp            — Init + boucle principale (non bloquante)
├── modbus_epever.cpp   — Lecture RS485 Modbus RTU (FC02/03/04/16), CRC manuel
├── epever_config.cpp   — Lecture/écriture des 18 registres holding de configuration
├── webserver.cpp       — Serveur HTTP async + 30+ routes REST
├── wifi_ap.cpp         — WiFi AP+STA, mDNS, portail captif, reconnexion auto
├── wireguard_vpn.cpp   — Tunnel WireGuard (optionnel)
├── rules.cpp           — Moteur de règles JSON
├── historique.cpp      — Historique RAM (hires 4h) + LittleFS (lores 30h)
├── sleep.cpp           — Deep sleep + restauration état relais
├── buttons.cpp         — Entrées numériques DI1/DI2 avec anti-rebond
├── ota.cpp             — ElegantOTA async
└── debug_log.cpp       — Journal en mémoire (ring buffer)

include/                — Headers correspondants + config.h + state.h

data/                   — Assets web (LittleFS)
├── index.html          — SPA 6 onglets
├── app.js              — Logique JS (~1100 lignes)
└── style.css           — Thème sombre mobile-first

Principe fondamental : aucun delay() ni boucle bloquante.
Tout le timing passe par millis(). Les lectures RS485 ont un timeout court ; en cas d'erreur, le dernier état valide est conservé.

API REST (sélection)

Méthode Endpoint Description
GET /api/state État système complet (JSON)
POST /api/relay/1/on Relais 1 ON
POST /api/relay/1/toggle Toggle + sauvegarde NVS
GET /api/rules Liste des règles
POST /api/rules Ajout de règle (JSON)
GET /api/epever/config Lecture config EPEVER depuis le régulateur
POST /api/epever/config Écriture config EPEVER
GET /api/wifi/status Statut AP + STA
GET /api/wifi/scan Scan réseaux disponibles
POST /api/wifi/sta Connexion à un réseau WiFi
GET /api/mdns Hostname mDNS courant
POST /api/mdns Modification hostname mDNS
GET /api/wireguard Config et statut WireGuard
POST /api/wireguard Sauvegarde config WireGuard
GET /api/history/hires Historique 4h (1 min/point)
GET /api/history/csv Export CSV (30h)
GET /api/sleep Config deep sleep
POST /api/modbus Intervalles de lecture Modbus

Bibliothèques utilisées

Bibliothèque Version Rôle
ArduinoJson ^7.0 Sérialisation JSON
AsyncTCP git TCP non bloquant
ESPAsyncWebServer git Serveur HTTP async
ElegantOTA ^3.1 OTA via navigateur
modbus-esp8266 ^4.1 Modbus RTU (utilisé pour les fonctions bas niveau)
WireGuard-ESP32-Arduino git VPN WireGuard (kc868_a2 uniquement)

Intégrées dans le framework ESP32 Arduino : WiFi, DNSServer, ESPmDNS, Preferences (NVS), LittleFS.


Outils

  • PlatformIO — build, flash, monitor
  • Framework : Arduino pour ESP32 (espressif32)
  • Filesystem : LittleFS

Build et flash

Prérequis

  • PlatformIO Core ou PlatformIO IDE (VS Code)
  • Câble USB pour le premier flash, WiFi pour les suivants (OTA)

Commandes

pio run                            # Compiler
pio run -e kc868_a2 --target upload       # Flasher par USB
pio run -e kc868_a2 --target uploadfs     # Flasher le filesystem (LittleFS)
pio run --target monitor           # Moniteur série 115200 bps
pio run -e qemu                    # Build émulateur (sans WireGuard ni WiFi)

OTA (après premier flash)

Ouvrir http://192.168.4.1/update (ou http://pv.local/update) :

  1. Sélectionner Firmware → uploader .pio/build/kc868_a2/firmware.bin
  2. Sélectionner Filesystem → uploader .pio/build/kc868_a2/littlefs.bin

Configuration

WiFi AP (compile-time)

Dans include/config.h :

#define WIFI_SSID     "kc868-a2"
#define WIFI_PASSWORD "soleil12"

WiFi STA (runtime)

Onglet Config → section Connexion WiFi → scanner, choisir le réseau, saisir le mot de passe.

Connexion WiFi STA + nom mDNS (runtime)

Onglet Config → section Connexion WiFi.

VPN WireGuard (runtime)

Onglet Config → section VPN WireGuard :

  • Coller la clé privée de l'interface ESP32
  • Coller la clé publique du serveur
  • Renseigner l'endpoint (mon.domaine.org) et le port (51820)
  • IP locale WireGuard (ex. 10.8.0.16)
  • Keepalive recommandé : 25 s pour maintenir le NAT actif
  • Activer et sauvegarder

Sécurité : les clés sont stockées dans la NVS flash de l'ESP32. Ne jamais committer le fichier .conf WireGuard dans git (il est dans .gitignore).

Deep sleep

Onglet Config → Mode économie d'énergie : activer, régler l'intervalle de réveil et le seuil PV.


Registres Modbus lus

Registre Données Format
0x3100 Tension PV U16 × 0.01 V
0x3101 Courant PV U16 × 0.01 A
0x3104 Tension batterie U16 × 0.01 V
0x3105 Courant batterie S16 × 0.01 A
0x3106 Tension load U16 × 0.01 V
0x3107 Courant load U16 × 0.01 A
0x310C Température batterie S16 × 0.01 °C
0x311A SOC batterie U16 %
0x3201 Statut batterie bitfield
0x3302 Énergie générée jour U32 × 0.01 kWh
0x3304 Énergie générée total U32 × 0.01 kWh
0x3306 Énergie consommée jour U32 × 0.01 kWh
0x3308 Énergie consommée total U32 × 0.01 kWh
0x200C État jour/nuit bitfield
0x9013 Horloge RTC 3 × U16

TODO

Fonctionnalités

  • Publication MQTT — envoi périodique de l'état système vers un broker MQTT (Home Assistant, Mosquitto…). Topics suggérés : solar/state, solar/relay/1, etc.
  • Version firmware dans l'UI — afficher le numéro de version (défini dans config.h) sur le dashboard et dans l'en-tête de l'API /api/state
  • Améliorations interface web — graphes plein écran, export PDF, notifications push navigateur (PWA), mode nuit/jour automatique de l'UI
  • Support PSK WireGuard — la bibliothèque WireGuard-ESP32-Arduino n'expose pas encore la preshared key dans son API Arduino ; patcher la lib ou utiliser un fork qui le supporte
  • Alertes — notification (email, webhook, MQTT) quand la batterie est basse, le RS485 déconnecté, ou un relais en défaut
  • Gestion multi-règles avancée — priorité entre règles, règles avec plage horaire

Code / qualité

  • Audit code mort — vérifier si modbus-esp8266 est encore utile (le code Modbus utilise du Serial2 raw + CRC manuel depuis la correction du RS485 ; les fonctions de la lib pourraient être inutilisées)
  • backup/ — le dossier est un instantané manuel ; le supprimer du repo une fois que l'historique git remplit ce rôle
  • Secrets compile-timeWIFI_PASSWORD et OTA_PASSWORD dans config.h en clair ; les déplacer dans un fichier secrets.h exclu du repo
  • Tests unitaires — couvrir le moteur de règles et le décodage Modbus avec des tests PlatformIO (dossier test/)
  • Emulateur QEMU — vérifier que le build qemu et les scripts Python du dossier emulator/ sont encore synchronisés avec l'état actuel du firmware

Licence

Usage personnel — aucune licence définie.