Files
esp_jardin/src/mqtt_manager.cpp
T
gilles 4854faa027 feat: module MQTT — PubSubClient, deadband, reconnexion non-bloquante
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>
2026-05-23 16:45:01 +02:00

75 lines
2.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}
}
}
}