Files
esp_jardin/plan_corrections.md
T
2026-05-24 13:05:18 +02:00

212 lines
6.8 KiB
Markdown

# Plan de corrections — esp_jardin
Toutes les améliorations identifiées lors de la revue de code, classées par priorité.
---
## ✅ Déjà corrigé dans cette session
| Correction | Fichier | Description |
|---|---|---|
| Race condition historique | `sensors.cpp` | Utilise `tempLues[i]` au lieu de `sondesEtat[i]` dans le buffer historique |
| MQTT timeout bloquant | `mqtt_manager.cpp` | `_wifiClient.setTimeout(2000)` — limite le blocage à 2s max |
| LWT (Last Will Testament) | `mqtt_manager.cpp` | Le broker publie `offline` automatiquement si l'ESP disparaît |
| Heartbeat MQTT | `mqtt_manager.cpp` | Publication `online` toutes les 60s sur `maison/jardin/status` |
| Erreurs sonde MQTT | `mqtt_manager.cpp` | Publication `1`/`0` sur `maison/jardin/ext/erreur` au changement d'état |
---
## Corrections restantes
### Tâche 1 — DS18B20 : lecture par adresse ROM (priorité haute)
**Problème :** `getTempCByIndex(i)` retourne les capteurs dans l'ordre d'énumération OneWire, qui peut changer si une sonde est débranchée ou remplacée. Cela peut inverser T°C Ext ↔ T°C Sol sans avertissement.
**Fichiers :** `include/config.h`, `include/sensors.h`, `src/sensors.cpp`
**Changements :**
`include/sensors.h` — ajouter la déclaration :
```cpp
extern DeviceAddress sondesAddr[NB_SONDES];
```
`src/sensors.cpp` — dans `sensors_init()`, scanner et mémoriser les adresses :
```cpp
DeviceAddress sondesAddr[NB_SONDES] = {};
void sensors_init() {
_sensors.begin();
_sensors.setWaitForConversion(false);
uint8_t nb = _sensors.getDeviceCount();
Serial.printf("[SONDES] %u capteur(s) détecté(s) sur GPIO %d\n", nb, ONE_WIRE_BUS);
for (uint8_t i = 0; i < NB_SONDES; i++) {
if (_sensors.getAddress(sondesAddr[i], i)) {
Serial.printf("[SONDE %u] Adresse: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
i, sondesAddr[i][0], sondesAddr[i][1], sondesAddr[i][2], sondesAddr[i][3],
sondesAddr[i][4], sondesAddr[i][5], sondesAddr[i][6], sondesAddr[i][7]);
} else {
Serial.printf("[SONDE %u] Adresse introuvable\n", i);
}
}
}
```
Dans la boucle de lecture, remplacer :
```cpp
// Avant
float t = _sensors.getTempCByIndex(i);
// Après
float t = _sensors.getTempC(sondesAddr[i]);
```
> **Note :** Les adresses ROM doivent être fixées au premier branchement. Si tu changes l'ordre physique des sondes, il faut reprogrammer la correspondance dans `main.cpp` ou les sauvegarder en NVS.
---
### Tâche 2 — DS18B20 : résolution 11-bit (priorité faible)
**Problème :** La résolution par défaut est 12 bits (précision 0,0625°C, conversion 750ms). Pour une station jardin, 11 bits suffisent largement (précision 0,125°C, conversion 375ms).
**Fichiers :** `include/config.h`, `src/sensors.cpp`
`config.h` — modifier la constante :
```cpp
// Avant
static const uint32_t CONVERSION_MS = 750;
// Après (déplacer dans config.h)
#define CONVERSION_MS 375 // 11-bit : 375ms au lieu de 750ms
```
`sensors.cpp` — ajouter dans `sensors_init()` après `_sensors.begin()` :
```cpp
_sensors.setResolution(11); // 0.125°C, 375ms — suffisant pour jardin
```
---
### Tâche 3 — WiFi : RSSI lu trop souvent (priorité faible)
**Problème :** `WiFi.RSSI()` est appelé à chaque itération de `loop()` (plusieurs milliers de fois par seconde), alors que la valeur change sur une échelle de secondes.
**Fichier :** `src/network.cpp`
Remplacer dans `network_update()` :
```cpp
// Avant
} else {
netStatus.rssi = WiFi.RSSI();
}
// Après
} else {
static uint32_t _dernierRssiMs = 0;
if (millis() - _dernierRssiMs >= 10000) {
netStatus.rssi = WiFi.RSSI();
_dernierRssiMs = millis();
}
}
```
---
### Tâche 4 — WiFi : persistent(false) (priorité faible)
**Problème :** Sans `WiFi.persistent(false)`, le SDK ESP32 sauvegarde aussi les credentials en NVS automatiquement, en doublon de notre propre gestion NVS.
**Fichier :** `src/network.cpp`
Ajouter dans `_demarrerSTA()` avant `WiFi.begin()` :
```cpp
WiFi.persistent(false); // on gère la persistance nous-mêmes via Preferences
WiFi.begin(_ssidActif, _passActif);
```
---
### Tâche 5 — Web server : delay() dans callback async (priorité faible)
**Problème :** `delay(500)` dans le handler `/api/wifi/connect` bloque la tâche AsyncTCP (Core 0) pendant 500ms avant le redémarrage.
**Fichiers :** `include/web_server.h`, `src/web_server.cpp`, `src/main.cpp`
`web_server.h` — ajouter la déclaration :
```cpp
void web_server_update(); // à appeler dans loop()
```
`web_server.cpp` — remplacer le delay par un flag :
```cpp
static bool _redemarrerDemande = false;
// Dans le handler POST /api/wifi/connect, remplacer :
// delay(500);
// ESP.restart();
// Par :
req->send(200, "application/json", "{\"ok\":true}");
_redemarrerDemande = true;
// Ajouter la fonction :
void web_server_update() {
if (_redemarrerDemande) {
delay(300); // dans loop() : delay() est toléré
ESP.restart();
}
}
```
`main.cpp` — ajouter dans `loop()` :
```cpp
void loop() {
network_update();
web_server_update(); // ajouter
bool nouvelleMesure = sensors_update();
...
}
```
---
### Tâche 6 — Historique : timestamps absolus via NTP (priorité optionnelle)
**Problème :** Les timestamps sont basés sur `millis()` (ms depuis le démarrage). Après un reboot, ils repartent à 0. L'interface web ne peut pas afficher des heures réelles (ex: "23h15").
**Fichier :** `src/sensors.cpp`, `src/network.cpp`
`network.cpp` — synchroniser l'heure NTP après connexion WiFi :
```cpp
#include <time.h>
// Dans _configurerMDNS() ou après la connexion WiFi :
configTime(3600, 3600, "pool.ntp.org"); // UTC+1, +1h été (à adapter)
Serial.println("[NTP] Synchronisation heure...");
```
`sensors.cpp` — utiliser `time(nullptr)` comme timestamp :
```cpp
// Avant
historique[histIdx].timestamp = maintenant; // millis()
// Après
historique[histIdx].timestamp = (uint32_t)time(nullptr); // Unix timestamp
```
`config.h` — adapter le type si nécessaire (uint32_t Unix timestamp est valide jusqu'en 2106).
> **Note :** Les graphiques de l'interface web devront adapter l'axe X pour des Unix timestamps plutôt que des ms depuis le boot.
---
## Ordre d'exécution recommandé
| Priorité | Tâche | Risque si ignoré |
|---|---|---|
| 🔴 Haute | Tâche 1 — DS18B20 adresses ROM | Fausses lectures MQTT si sonde déconnectée |
| 🟡 Moyenne | Tâche 2 — Résolution 11-bit | Aucun, juste optimisation |
| 🟡 Moyenne | Tâche 3 — RSSI throttle | Aucun, CPU légèrement gaspillé |
| 🟢 Faible | Tâche 4 — WiFi persistent(false) | Doublon NVS, usure Flash négligeable |
| 🟢 Faible | Tâche 5 — delay() async | 500ms de blocage une seule fois (reboot) |
| ⚪ Optionnel | Tâche 6 — NTP timestamps | Graphiques sans heure réelle |