4854faa027
Implémente mqtt_manager.h/.cpp : connexion sans authentification si MQTT_USER vide, filtre deadband par sonde, retain=true, jamais de valeur d'erreur publiée. Intégration dans main.cpp (mqtt_init/update). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
2.6 KiB
C++
75 lines
2.6 KiB
C++
#include "mqtt_manager.h"
|
||
#include "config.h"
|
||
#include <WiFi.h>
|
||
#include <PubSubClient.h>
|
||
|
||
static WiFiClient _wifiClient;
|
||
static PubSubClient _mqtt(_wifiClient);
|
||
static uint32_t _dernierRetryMs = 0;
|
||
|
||
// Tente une connexion MQTT (bloquant le temps de la poignée de main TCP)
|
||
static bool _connecter() {
|
||
Serial.printf("[MQTT] Connexion → %s:%d\n", MQTT_BROKER, MQTT_PORT);
|
||
bool ok;
|
||
if (strlen(MQTT_USER) > 0) {
|
||
ok = _mqtt.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASS_STR);
|
||
} else {
|
||
ok = _mqtt.connect(MQTT_CLIENT_ID);
|
||
}
|
||
if (ok) {
|
||
Serial.println("[MQTT] Connecté");
|
||
netStatus.mqttConnecte = true;
|
||
} else {
|
||
Serial.printf("[MQTT] Échec, état=%d\n", _mqtt.state());
|
||
netStatus.mqttConnecte = false;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
void mqtt_init() {
|
||
_mqtt.setServer(MQTT_BROKER, MQTT_PORT);
|
||
}
|
||
|
||
void mqtt_update() {
|
||
// Pas de WiFi STA = pas de MQTT
|
||
if (!netStatus.wifiConnecte || netStatus.modeAP) return;
|
||
|
||
// Reconnexion non-bloquante : on ne retente que toutes les MQTT_RETRY_MS
|
||
if (!_mqtt.connected()) {
|
||
netStatus.mqttConnecte = false;
|
||
if (millis() - _dernierRetryMs > MQTT_RETRY_MS) {
|
||
_dernierRetryMs = millis();
|
||
_connecter();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Traitement du keepalive et des messages entrants
|
||
_mqtt.loop();
|
||
|
||
// Publication par sonde avec filtre deadband
|
||
for (uint8_t i = 0; i < NB_SONDES; i++) {
|
||
// Ne jamais publier une valeur d'erreur (−127 °C, 85 °C, NAN)
|
||
if (sondesEtat[i].erreur) continue;
|
||
|
||
float delta = fabsf(sondesEtat[i].tempActuelle - sondesEtat[i].dernierPublie);
|
||
uint32_t ecart = millis() - sondesEtat[i].dernierPubliMs;
|
||
bool deadbandOk = delta >= sondesConfig[i].deadband;
|
||
bool intervalOk = ecart >= sondesConfig[i].intervalleMs;
|
||
|
||
// Publication si variation hors deadband OU intervalle max écoulé
|
||
// Note : au premier cycle, dernierPubliMs == 0 → ecart très grand → publication immédiate
|
||
if (deadbandOk || intervalOk) {
|
||
char payload[8];
|
||
snprintf(payload, sizeof(payload), "%.1f", sondesEtat[i].tempActuelle);
|
||
// retain=true : le broker mémorise la dernière valeur pour les nouveaux abonnés
|
||
bool ok = _mqtt.publish(sondesConfig[i].topic, payload, true);
|
||
if (ok) {
|
||
sondesEtat[i].dernierPublie = sondesEtat[i].tempActuelle;
|
||
sondesEtat[i].dernierPubliMs = millis();
|
||
Serial.printf("[MQTT] %s → %s °C\n", sondesConfig[i].topic, payload);
|
||
}
|
||
}
|
||
}
|
||
}
|