From 163bb80680977c7694fc67e758e35bf31dbbbebe Mon Sep 17 00:00:00 2001 From: coolneng Date: Tue, 16 Dec 2025 16:38:21 +0100 Subject: [PATCH] Replace the MQTT client with a robust async option --- include/wlan.h | 33 ++++++++++++++++----- platformio.ini | 2 +- src/main.cpp | 25 ++++++++-------- src/wlan.cpp | 80 ++++++++++++++++++++++++++------------------------ 4 files changed, 81 insertions(+), 59 deletions(-) diff --git a/include/wlan.h b/include/wlan.h index e797786..cfb553e 100644 --- a/include/wlan.h +++ b/include/wlan.h @@ -2,14 +2,33 @@ #define WLAN_H #include "config.h" -#include +#include +#include +#include + +static AsyncMqttClient mqtt_client; +static Ticker mqtt_connection_timer, wlan_connection_timer; +static WiFiEventHandler connection_handler, disconnection_handler; +extern Config *config; + +void initialize_wlan(); + +void initialize_mqtt(); + +void connect_wlan(); + +void connect_mqtt(); + +void on_wlan_connection(const WiFiEventStationModeGotIP &event); + +void on_wlan_disconnection(const WiFiEventStationModeDisconnected &event); + +void on_mqtt_connection(bool session); + +void on_mqtt_disconnection(AsyncMqttClientDisconnectReason reason); -void initial_connection(const char *ssid, const char *psk, - const char *hostname); -void connect_wlan(Config *config); -void connect_mqtt(PubSubClient &client, Config *config); -void disconnect_mqtt(PubSubClient &client, const char *topic); size_t construct_json(float *data, char *buffer, int buffer_size); -void mqtt_transfer(PubSubClient &client, Config *config, float *data); + +void mqtt_transfer(float *data); #endif /* WLAN_H */ diff --git a/platformio.ini b/platformio.ini index 12e5591..e828ba4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,6 +16,6 @@ framework = arduino monitor_filters = esp8266_exception_decoder lib_deps = sensirion/Sensirion I2C SCD4x@^1.1.0 - knolleary/PubSubClient@^2.8 + marvinroger/AsyncMqttClient@^0.9.0 bblanchon/ArduinoJson@^7.4.1 diff --git a/src/main.cpp b/src/main.cpp index ea2dcb9..a4c6af7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,18 @@ -#include "config.h" #include "sensor.h" #include "wlan.h" #include -#include -#include -#include -WiFiClient wifi_client; -PubSubClient mqtt_client(wifi_client); SensirionI2cScd4x sensor; int error_code; char error_msg[64]; + const char *config_file_path = "/config.json"; Config *config; +float data[3]; +unsigned long previous_millis = 0; + void setup() { Serial.begin(9600); config = (Config *)malloc(sizeof(Config)); @@ -22,15 +20,18 @@ void setup() { if (!load_config_file(config_file_path, config)) Serial.println("ERROR: The config file could not be loaded"); - connect_wlan(config); - connect_mqtt(mqtt_client, config); + initialize_wlan(); + initialize_mqtt(); + connect_wlan(); initialize_sensor(sensor, error_code, error_msg); } void loop() { - float data[3]; + unsigned long current_millis = millis(); - read_values(sensor, data, error_code, error_msg); - mqtt_transfer(mqtt_client, config, data); - delay(config->sleep_time); + if (current_millis - previous_millis >= config->sleep_time) { + previous_millis = current_millis; + read_values(sensor, data, error_code, error_msg); + mqtt_transfer(data); + } } diff --git a/src/wlan.cpp b/src/wlan.cpp index 4a7eaed..a8afcc6 100644 --- a/src/wlan.cpp +++ b/src/wlan.cpp @@ -1,50 +1,50 @@ #include "wlan.h" -#include -void initial_connection(const char *ssid, const char *psk, - const char *hostname) { - WiFi.hostname(hostname); - WiFi.begin(ssid, psk); - WiFi.persistent(true); - WiFi.setAutoConnect(true); - WiFi.setAutoReconnect(true); +void initialize_wlan() { + connection_handler = WiFi.onStationModeGotIP(on_wlan_connection); + disconnection_handler = + WiFi.onStationModeDisconnected(on_wlan_disconnection); } -void connect_wlan(Config *config) { - if (WiFi.SSID() != config->ssid) - initial_connection(config->ssid, config->psk, config->device_id); - while (WiFi.status() != WL_CONNECTED) { - delay(1000); - Serial.print("."); - } - Serial.println(""); +void initialize_mqtt() { + mqtt_client.onConnect(on_mqtt_connection); + mqtt_client.onDisconnect(on_mqtt_disconnection); + mqtt_client.setServer(config->mqtt_host, config->mqtt_port); + mqtt_client.setCredentials(config->mqtt_user, config->mqtt_password); + Serial.println("MQTT initialization complete"); +} + +void connect_wlan() { WiFi.begin(config->ssid, config->psk); } + +void connect_mqtt() { + Serial.println("Connecting to MQTT"); + mqtt_client.connect(); +} + +void on_wlan_connection(const WiFiEventStationModeGotIP &event) { Serial.println("WiFi connected"); + connect_mqtt(); } -void connect_mqtt(PubSubClient &client, Config *config) { - bool connection; - client.setServer(config->mqtt_host, config->mqtt_port); +void on_wlan_disconnection(const WiFiEventStationModeDisconnected &event) { + Serial.println("WiFi disconnected"); + mqtt_connection_timer.detach(); + wlan_connection_timer.once(2, connect_wlan); +} - while (!client.connected()) { - connection = client.connect(config->device_id, config->mqtt_user, - config->mqtt_password); - if (connection) { - Serial.println("MQTT connected"); - client.subscribe(config->topic); - } else { - Serial.println("MQTT failed to connect"); - Serial.println(client.state()); - delay(5000); - } +void on_mqtt_connection(bool session) { + Serial.println("MQTT connected"); + mqtt_client.subscribe(config->topic, 2); +}; + +void on_mqtt_disconnection(AsyncMqttClientDisconnectReason reason) { + Serial.println("MQTT disconnected"); + + if (WiFi.isConnected()) { + mqtt_connection_timer.once(2, connect_mqtt); } } -void disconnect_mqtt(PubSubClient &client, const char *topic) { - Serial.println("Disconnecting MQTT"); - client.unsubscribe(topic); - client.disconnect(); -} - size_t construct_json(float *data, char *buffer, int buffer_size) { JsonDocument json; json["co2_concentration"] = data[0]; @@ -54,9 +54,11 @@ size_t construct_json(float *data, char *buffer, int buffer_size) { return payload_size; } -void mqtt_transfer(PubSubClient &client, Config *config, float *data) { +void mqtt_transfer(float *data) { char buffer[100]; size_t payload_size = construct_json(data, buffer, 100); - client.publish(config->topic, buffer, payload_size); - Serial.println("Data transferred successfully"); + uint16_t response = + mqtt_client.publish(config->topic, 2, true, buffer, payload_size); + if (response) + Serial.println("Data transferred successfully"); }