Initial commit — KC868-A2 contrôleur solaire ESP32

Fonctionnalités :
- Lecture RS485 Modbus Epever Tracer 4210N (115200 bps, FC03/FC04/FC16)
- Moteur de règles JSON (LittleFS) — commande automatique des relais
- Interface web mobile-first (dashboard, règles, config, historique, EPEVER, debug)
- WiFi AP+STA simultanés avec reconnexion automatique et portail captif
- mDNS configurable (pv.local par défaut)
- Configuration registres EPEVER depuis l'UI (18 registres holding)
- Historique basse/haute résolution avec graphes canvas
- VPN WireGuard optionnel (désactivé par défaut, config via UI)
- OTA firmware + filesystem via ElegantOTA
- Deep sleep / économie d'énergie

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 19:25:01 +02:00
commit a8f0d6ccba
88 changed files with 13162 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
# Émulateur QEMU ESP32 — KC868-A2
Émulation du firmware sur QEMU ESP32 (fork Espressif, GPL).
Interface de débogage 3 volets : GPIO / terminal série / webserver ESP32.
## Architecture
```
Docker
├── qemu-system-xtensa (ESP32 firmware + WiFi + réseau)
│ UART0 → stdout (logs Serial.print → terminal)
│ UART2 → TCP:1235 (Modbus RTU ← stub Python)
│ NIC → slirp (hostfwd port 10080 → ESP32:80)
├── modbus_stub.py (émulateur Modbus RTU slave Epever)
│ Se connecte à TCP:1235, répond aux FC04 avec données simulées
└── server.py (interface web débogage, port 8888)
/ → UI 3 volets
/serial → SSE flux UART0
/api/* → proxy vers webserver ESP32 (port 10080)
```
## Prérequis
- Docker + Docker Compose
- Firmware compilé avec PlatformIO : `pio run`
## Lancement
### Option 1 — Serveur de simulation (recommandé)
Sert les vrais fichiers `data/` + simule tous les `/api/*` en mémoire.
L'état des relais, règles et config sleep sont modifiables via l'interface.
L'historique s'alimente toutes les 5 secondes (= 5 min en temps réel).
```bash
# Sans Docker (Python 3 requis) :
cd emulator && python3 sim.py
# Avec Docker :
cd emulator && docker compose up sim
```
Accès : **http://localhost:8087**
---
### Option 2 — Émulateur QEMU (boot séquence + terminal série)
Exécute le vrai binaire compilé. Montre le boot ESP32 et les logs Serial.
Le firmware crashe au démarrage de WiFi (hardware non émulé) — normal.
```bash
# 1. Compiler le firmware
pio run && pio run -t buildfs
# 2. Copier les binaires
cp .pio/build/kc868_a2/*.bin emulator/firmware/
# 3. Démarrer
cd emulator && docker compose up --build emulator
```
Accès :
- **Interface de débogage** : http://localhost:8888
- **WebServer ESP32** : http://localhost:10080 (si WiFi démarre)
## Mise à jour de la version QEMU
Si le téléchargement échoue, vérifier la dernière version disponible sur :
https://github.com/espressif/qemu/releases
Modifier `QEMU_TAG` et `QEMU_ARCHIVE` dans le `Dockerfile`.
## Correctif registres WiFi (LoadStorePIFAddrError)
Le QEMU Espressif standard n'émule pas les registres matériels WiFi modem
(`0x60033C00`). Sans correctif, le firmware crash en boucle avec
`LoadStorePIFAddrError` dès l'initialisation WiFi.
**Solution** : le `Dockerfile` utilise un build multi-étapes :
1. **`rom-extractor`** — télécharge le binaire pré-compilé, extrait les ROM blobs ESP32 (fichiers binaires propriétaires)
2. **`qemu-builder`** — clone le source Espressif QEMU, applique `wifi_stub_patch.py`, compile uniquement la cible xtensa
3. **Image finale** — ROM blobs de l'étape 1 + binaire patché de l'étape 2
`wifi_stub_patch.py` injecte un appel `create_unimplemented_device()` dans
`hw/xtensa/esp32.c` qui mappe silencieusement la plage `0x60033C000x60043BFF`
(64 Ko, WiFi MAC + baseband) : toutes les lectures retournent 0, les écritures
sont ignorées, plus de fault CPU.
> **Note** : le build initial prend 1530 min (compilation QEMU). Docker met
> les layers en cache — les rebuilds suivants sont instantanés.
## Limites connues
| Fonctionnalité | État |
|---|---|
| WiFi AP mode (softAP) | Registres stubés (pas de WiFi réel) — le firmware démarre |
| Webserver ESP32 (port 80) | Accessible via hostfwd → port 10080 si WiFi s'initialise |
| Modbus RS485 | Émulé par `modbus_stub.py` (données sinusoïdales) |
| GPIO physiques (DI1/DI2) | Non émulés — toujours à 0 |
| Deep sleep | Non supporté dans QEMU |
| OTA | Non testé |
## Modbus simulé
Le stub `modbus_stub.py` répond aux lectures FC04 des registres Epever Tracer 4210N :
| Registre | Valeur simulée |
|---|---|
| 0x3100 PV tension | ~18.72 V (variation sinusoïdale) |
| 0x3101 PV courant | ~4.20 A |
| 0x3104 Batterie | ~13.45 V |
| 0x310E Load | 26.80 W |
| 0x311A SOC | 75 % |
| 0x3200 Statut | Float charge |
| 0x200C Jour/Nuit | Jour |
## Arrêt
```bash
docker compose down
```
Pour quitter la console QEMU (dans le terminal) : `Ctrl+A` puis `X`.