|
|
#include <MqttSettingsService.h>
/**
* Retains a copy of the cstr provided in the pointer provided using dynamic allocation. * * Frees the pointer before allocation and leaves it as nullptr if cstr == nullptr. */ static char* retainCstr(const char* cstr, char** ptr) { // free up previously retained value if exists
free(*ptr); *ptr = nullptr;
// dynamically allocate and copy cstr (if non null)
if (cstr != nullptr) { *ptr = (char*)malloc(strlen(cstr) + 1); strcpy(*ptr, cstr); }
// return reference to pointer for convenience
return *ptr; }
MqttSettingsService::MqttSettingsService(AsyncWebServer* server, FS* fs, SecurityManager* securityManager) : _httpEndpoint(MqttSettings::read, MqttSettings::update, this, server, MQTT_SETTINGS_SERVICE_PATH, securityManager), _fsPersistence(MqttSettings::read, MqttSettings::update, this, fs, MQTT_SETTINGS_FILE), _retainedHost(nullptr), _retainedClientId(nullptr), _retainedUsername(nullptr), _retainedPassword(nullptr), _reconfigureMqtt(false), _disconnectedAt(0), _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED), _mqttClient() { #ifdef ESP32
WiFi.onEvent( std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP); #elif defined(ESP8266)
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected( std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1)); _onStationModeGotIPHandler = WiFi.onStationModeGotIP(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1)); #endif
_mqttClient.onConnect(std::bind(&MqttSettingsService::onMqttConnect, this, std::placeholders::_1)); _mqttClient.onDisconnect(std::bind(&MqttSettingsService::onMqttDisconnect, this, std::placeholders::_1)); addUpdateHandler([&](const String& originId) { onConfigUpdated(); }, false); }
MqttSettingsService::~MqttSettingsService() { }
void MqttSettingsService::begin() { _fsPersistence.readFromFS(); }
void MqttSettingsService::loop() { if (_reconfigureMqtt || (_disconnectedAt && (unsigned long)(millis() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) { // reconfigure MQTT client
configureMqtt();
// clear the reconnection flags
_reconfigureMqtt = false; _disconnectedAt = 0; } }
bool MqttSettingsService::isEnabled() { return _state.enabled; }
bool MqttSettingsService::isConnected() { return _mqttClient.connected(); }
const char* MqttSettingsService::getClientId() { return _mqttClient.getClientId(); }
AsyncMqttClientDisconnectReason MqttSettingsService::getDisconnectReason() { return _disconnectReason; }
AsyncMqttClient* MqttSettingsService::getMqttClient() { return &_mqttClient; }
void MqttSettingsService::onMqttConnect(bool sessionPresent) { Serial.print(F("Connected to MQTT, ")); if (sessionPresent) { Serial.println(F("with persistent session")); } else { Serial.println(F("without persistent session")); } }
void MqttSettingsService::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.print(F("Disconnected from MQTT reason: ")); Serial.println((uint8_t)reason); _disconnectReason = reason; _disconnectedAt = millis(); }
void MqttSettingsService::onConfigUpdated() { _reconfigureMqtt = true; _disconnectedAt = 0; }
#ifdef ESP32
void MqttSettingsService::onStationModeGotIP(WiFiEvent_t event, WiFiEventInfo_t info) { if (_state.enabled) { Serial.println(F("WiFi connection dropped, starting MQTT client.")); onConfigUpdated(); } }
void MqttSettingsService::onStationModeDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) { if (_state.enabled) { Serial.println(F("WiFi connection dropped, stopping MQTT client.")); onConfigUpdated(); } } #elif defined(ESP8266)
void MqttSettingsService::onStationModeGotIP(const WiFiEventStationModeGotIP& event) { if (_state.enabled) { Serial.println(F("WiFi connection dropped, starting MQTT client.")); onConfigUpdated(); } }
void MqttSettingsService::onStationModeDisconnected(const WiFiEventStationModeDisconnected& event) { if (_state.enabled) { Serial.println(F("WiFi connection dropped, stopping MQTT client.")); onConfigUpdated(); } } #endif
void MqttSettingsService::configureMqtt() { // disconnect if currently connected
_mqttClient.disconnect();
// only connect if WiFi is connected and MQTT is enabled
if (_state.enabled && WiFi.isConnected()) { Serial.println(F("Connecting to MQTT...")); _mqttClient.setServer(retainCstr(_state.host.c_str(), &_retainedHost), _state.port); if (_state.username.length() > 0) { _mqttClient.setCredentials( retainCstr(_state.username.c_str(), &_retainedUsername), retainCstr(_state.password.length() > 0 ? _state.password.c_str() : nullptr, &_retainedPassword)); } else { _mqttClient.setCredentials(retainCstr(nullptr, &_retainedUsername), retainCstr(nullptr, &_retainedPassword)); } _mqttClient.setClientId(retainCstr(_state.clientId.c_str(), &_retainedClientId)); _mqttClient.setKeepAlive(_state.keepAlive); _mqttClient.setCleanSession(_state.cleanSession); _mqttClient.setMaxTopicLength(_state.maxTopicLength); _mqttClient.connect(); } }
|