212 lines
6.8 KiB
Markdown
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 |
|