From 137b99b291779749fe6a2a3c11b1975d595ee672 Mon Sep 17 00:00:00 2001 From: iranl Date: Tue, 9 Jul 2024 13:17:31 +0200 Subject: [PATCH] Fixes/Enhancement for MQTT and WiFi reconnect + network timout + MQTT retain (#419) * Retain * Reconnect --- lib/WiFiManager/WiFiManager.h | 5 ++-- src/NukiNetwork.cpp | 42 ++++++++++++++++++------------- src/NukiNetwork.h | 13 +++++----- src/NukiNetworkLock.cpp | 30 +++++++++++----------- src/NukiNetworkLock.h | 16 ++++++------ src/NukiNetworkOpener.cpp | 18 ++++++------- src/NukiNetworkOpener.h | 14 +++++------ src/networkDevices/WifiDevice.cpp | 18 ++++++++++++- 8 files changed, 90 insertions(+), 66 deletions(-) diff --git a/lib/WiFiManager/WiFiManager.h b/lib/WiFiManager/WiFiManager.h index 98f40d4..4e8d580 100644 --- a/lib/WiFiManager/WiFiManager.h +++ b/lib/WiFiManager/WiFiManager.h @@ -629,7 +629,7 @@ public: boolean _preloadwifiscan = false; // preload wifiscan if true unsigned int _scancachetime = 30000; // ms cache time for preload scans boolean _asyncScan = false; // perform wifi network scan async - + bool wifiConnectDefault(); protected: boolean _autoforcerescan = false; // automatically force rescan if scan networks is 0, ignoring cache @@ -659,7 +659,6 @@ protected: uint8_t connectWifi(String ssid, String pass, bool connect = true); bool setSTAConfig(); - bool wifiConnectDefault(); bool wifiConnectNew(String ssid, String pass,bool connect = true); uint8_t waitForConnectResult(); @@ -669,6 +668,7 @@ protected: // webserver handlers public: void handleNotFound(); + bool WiFi_scanNetworks(bool force,bool async); protected: void HTTPSend(const String &content); void handleRoot(); @@ -710,7 +710,6 @@ protected: String WiFi_SSID(bool persistent = true) const; String WiFi_psk(bool persistent = true) const; bool WiFi_scanNetworks(); - bool WiFi_scanNetworks(bool force,bool async); bool WiFi_scanNetworks(unsigned int cachetime,bool async); bool WiFi_scanNetworks(unsigned int cachetime); void WiFi_scanComplete(int networksFound); diff --git a/src/NukiNetwork.cpp b/src/NukiNetwork.cpp index e62c0e0..9dcd886 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -321,18 +321,18 @@ void NukiNetwork::initialize() if(rebGpio) { buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); - publishString(_lockPath.c_str(), gpioPath, "input"); + publishString(_lockPath.c_str(), gpioPath, "input", false); buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); - publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str()); + publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str(), false); } break; case PinRole::GeneralOutput: if(rebGpio) { buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role}); - publishString(_lockPath.c_str(), gpioPath, "output"); + publishString(_lockPath.c_str(), gpioPath, "output", false); buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); - publishString(_lockPath.c_str(), gpioPath, "0"); + publishString(_lockPath.c_str(), gpioPath, "0", false); } buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state}); subscribe(_lockPath.c_str(), gpioPath); @@ -360,8 +360,11 @@ bool NukiNetwork::update() if(!_device->isConnected()) { - _device->mqttDisconnect(true); - + if(_firstDisconnected) { + _firstDisconnected = false; + _device->mqttDisconnect(true); + } + if(_restartOnDisconnect && millis() > 60000) { restartEsp(RestartReason::RestartOnDisconnectWatchdog); @@ -394,17 +397,11 @@ bool NukiNetwork::update() _logIp = false; Log->print(F("IP: ")); Log->println(_device->localIP()); + _firstDisconnected = true; } if(!_device->mqttConnected() && _device->isConnected()) { - if(_networkTimeout > 0 && (ts - _lastConnectedTs > _networkTimeout * 1000) && ts > 60000) - { - Log->println("Network timeout has been reached, restarting ..."); - delay(200); - restartEsp(RestartReason::NetworkTimeoutWatchdog); - } - bool success = reconnect(); if(!success) { @@ -413,8 +410,19 @@ bool NukiNetwork::update() delay(2000); } - if(!_device->mqttConnected() || !_device->isConnected()) return false; - + if(!_device->mqttConnected() || !_device->isConnected()) + { + if(_networkTimeout > 0 && (ts - _lastConnectedTs > _networkTimeout * 1000) && ts > 60000) + { + Log->println("Network timeout has been reached, restarting ..."); + delay(200); + restartEsp(RestartReason::NetworkTimeoutWatchdog); + } + + delay(2000); + return false; + } + _lastConnectedTs = ts; if(_presenceDetection != nullptr && (_lastPresenceTs == 0 || (ts - _lastPresenceTs) > 3000)) @@ -504,7 +512,7 @@ bool NukiNetwork::update() uint8_t pinState = digitalRead(pin) == HIGH ? 1 : 0; char gpioPath[250]; buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pin)).c_str(), mqtt_topic_gpio_state}); - publishInt(_lockPath.c_str(), gpioPath, pinState); + publishInt(_lockPath.c_str(), gpioPath, pinState, false); Log->print(F("GPIO ")); Log->print(pin); @@ -774,7 +782,7 @@ bool NukiNetwork::encryptionSupported() return _device->supportsEncryption(); } -void NukiNetwork::publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision, bool retain) +void NukiNetwork::publishFloat(const char* prefix, const char* topic, const float value, bool retain, const uint8_t precision) { char str[30]; dtostrf(value, 0, precision, str); diff --git a/src/NukiNetwork.h b/src/NukiNetwork.h index a17ca33..d43c78f 100644 --- a/src/NukiNetwork.h +++ b/src/NukiNetwork.h @@ -56,12 +56,12 @@ public: void subscribe(const char* prefix, const char* path); void initTopic(const char* prefix, const char* path, const char* value); - void publishFloat(const char* prefix, const char* topic, const float value, const uint8_t precision = 2, bool retain = false); - void publishInt(const char* prefix, const char* topic, const int value, bool retain = false); - void publishUInt(const char* prefix, const char* topic, const unsigned int value, bool retain = false); - void publishULong(const char* prefix, const char* topic, const unsigned long value, bool retain = false); - void publishBool(const char* prefix, const char* topic, const bool value, bool retain = false); - bool publishString(const char* prefix, const char* topic, const char* value, bool retain = false); + void publishFloat(const char* prefix, const char* topic, const float value, bool retain, const uint8_t precision = 2); + void publishInt(const char* prefix, const char* topic, const int value, bool retain); + void publishUInt(const char* prefix, const char* topic, const unsigned int value, bool retain); + void publishULong(const char* prefix, const char* topic, const unsigned long value, bool retain); + void publishBool(const char* prefix, const char* topic, const bool value, bool retain); + bool publishString(const char* prefix, const char* topic, const char* value, bool retain); void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const char *softwareVersion, const char *hardwareVersion, const char* availabilityTopic, const bool& hasKeypad, char* lockAction, char* unlockAction, char* openAction); void publishHASSConfigAdditionalLockEntities(char* deviceType, const char* baseTopic, char* name, char* uidString); @@ -155,6 +155,7 @@ private: int _mqttConnectionState = 0; bool _connectReplyReceived = false; + bool _firstDisconnected = true; unsigned long _nextReconnect = 0; char _mqttBrokerAddr[101] = {0}; diff --git a/src/NukiNetworkLock.cpp b/src/NukiNetworkLock.cpp index 8f8b84c..1ff2d7a 100644 --- a/src/NukiNetworkLock.cpp +++ b/src/NukiNetworkLock.cpp @@ -64,17 +64,17 @@ void NukiNetworkLock::initialize() _network->initTopic(_mqttPath, mqtt_topic_config_action, "--"); _network->subscribe(_mqttPath, mqtt_topic_config_action); + _network->subscribe(_mqttPath, mqtt_topic_reset); + _network->initTopic(_mqttPath, mqtt_topic_reset, "0"); + if(_preferences->getBool(preference_update_from_mqtt, false)) { - _network->subscribe(_mqttPath, mqtt_topic_reset); - _network->initTopic(_mqttPath, mqtt_topic_reset, "0"); + #if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0)) + _network->subscribe(_mqttPath, mqtt_topic_update); + _network->initTopic(_mqttPath, mqtt_topic_update, "0"); + #endif } - #if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0)) - _network->subscribe(_mqttPath, mqtt_topic_update); - _network->initTopic(_mqttPath, mqtt_topic_update, "0"); - #endif - _network->subscribe(_mqttPath, mqtt_topic_webserver_action); _network->initTopic(_mqttPath, mqtt_topic_webserver_action, "--"); _network->initTopic(_mqttPath, mqtt_topic_webserver_state, (_preferences->getBool(preference_webserver_enabled, true) ? "1" : "0")); @@ -263,16 +263,16 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const switch(lockActionResult) { case LockActionResult::Success: - publishString(mqtt_topic_lock_action, "ack"); + publishString(mqtt_topic_lock_action, "ack", false); break; case LockActionResult::UnknownAction: - publishString(mqtt_topic_lock_action, "unknown_action"); + publishString(mqtt_topic_lock_action, "unknown_action", false); break; case LockActionResult::AccessDenied: - publishString(mqtt_topic_lock_action, "denied"); + publishString(mqtt_topic_lock_action, "denied", false); break; case LockActionResult::Failed: - publishString(mqtt_topic_lock_action, "error"); + publishString(mqtt_topic_lock_action, "error", false); break; } } @@ -677,7 +677,7 @@ void NukiNetworkLock::publishAuthorizationInfo(const std::listpublishInt(_offMqttPath, mqtt_topic_official_lock_action, value, false); } -void NukiNetworkLock::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain) +void NukiNetworkLock::publishFloat(const char *topic, const float value, bool retain, const uint8_t precision) { - _network->publishFloat(_mqttPath, topic, value, precision, retain); + _network->publishFloat(_mqttPath, topic, value, retain, precision); } void NukiNetworkLock::publishInt(const char *topic, const int value, bool retain) diff --git a/src/NukiNetworkLock.h b/src/NukiNetworkLock.h index 0944094..9624025 100644 --- a/src/NukiNetworkLock.h +++ b/src/NukiNetworkLock.h @@ -53,14 +53,14 @@ public: void setTimeControlCommandReceivedCallback(void (*timeControlCommandReceivedReceivedCallback)(const char* value)); void onMqttDataReceived(const char* topic, byte* payload, const unsigned int length) override; - void publishFloat(const char* topic, const float value, const uint8_t precision = 2, bool retain = false); - void publishInt(const char* topic, const int value, bool retain = false); - void publishUInt(const char* topic, const unsigned int value, bool retain = false); - void publishULong(const char* topic, const unsigned long value, bool retain = false); - void publishBool(const char* topic, const bool value, bool retain = false); - bool publishString(const char* topic, const String& value, bool retain = false); - bool publishString(const char* topic, const std::string& value, bool retain = false); - bool publishString(const char* topic, const char* value, bool retain = false); + void publishFloat(const char* topic, const float value, bool retain, const uint8_t precision = 2); + void publishInt(const char* topic, const int value, bool retain); + void publishUInt(const char* topic, const unsigned int value, bool retain); + void publishULong(const char* topic, const unsigned long value, bool retain); + void publishBool(const char* topic, const bool value, bool retain); + bool publishString(const char* topic, const String& value, bool retain); + bool publishString(const char* topic, const std::string& value, bool retain); + bool publishString(const char* topic, const char* value, bool retain); bool reconnected(); uint8_t queryCommands(); diff --git a/src/NukiNetworkOpener.cpp b/src/NukiNetworkOpener.cpp index ffa0d1e..62f4b76 100644 --- a/src/NukiNetworkOpener.cpp +++ b/src/NukiNetworkOpener.cpp @@ -161,16 +161,16 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con switch(lockActionResult) { case LockActionResult::Success: - publishString(mqtt_topic_lock_action, "ack"); + publishString(mqtt_topic_lock_action, "ack", false); break; case LockActionResult::UnknownAction: - publishString(mqtt_topic_lock_action, "unknown_action"); + publishString(mqtt_topic_lock_action, "unknown_action", false); break; case LockActionResult::AccessDenied: - publishString(mqtt_topic_lock_action, "denied"); + publishString(mqtt_topic_lock_action, "denied", false); break; case LockActionResult::Failed: - publishString(mqtt_topic_lock_action, "error"); + publishString(mqtt_topic_lock_action, "error", false); break; } } @@ -302,10 +302,10 @@ void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& key if(keyTurnerState.nukiState == NukiOpener::State::ContinuousMode) { - publishString(mqtt_topic_lock_continuous_mode, "on"); + publishString(mqtt_topic_lock_continuous_mode, "on", true); json["continuous_mode"] = 1; } else { - publishString(mqtt_topic_lock_continuous_mode, "off"); + publishString(mqtt_topic_lock_continuous_mode, "off", true); json["continuous_mode"] = 0; } @@ -1159,7 +1159,7 @@ void NukiNetworkOpener::publishTimeControlCommandResult(const char* result) void NukiNetworkOpener::publishStatusUpdated(const bool statusUpdated) { - publishBool(mqtt_topic_lock_status_updated, statusUpdated); + publishBool(mqtt_topic_lock_status_updated, statusUpdated, true); } void NukiNetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *)) @@ -1188,9 +1188,9 @@ void NukiNetworkOpener::setTimeControlCommandReceivedCallback(void (*timeControl _timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback; } -void NukiNetworkOpener::publishFloat(const char *topic, const float value, const uint8_t precision, bool retain) +void NukiNetworkOpener::publishFloat(const char *topic, const float value, bool retain, const uint8_t precision) { - _network->publishFloat(_mqttPath, topic, value, precision, retain); + _network->publishFloat(_mqttPath, topic, value, retain, precision); } void NukiNetworkOpener::publishInt(const char *topic, const int value, bool retain) diff --git a/src/NukiNetworkOpener.h b/src/NukiNetworkOpener.h index 1c13ed3..98b79cc 100644 --- a/src/NukiNetworkOpener.h +++ b/src/NukiNetworkOpener.h @@ -55,13 +55,13 @@ public: private: bool comparePrefixedPath(const char* fullPath, const char* subPath); - void publishFloat(const char* topic, const float value, const uint8_t precision = 2, bool retain = false); - void publishInt(const char* topic, const int value, bool retain = false); - void publishUInt(const char* topic, const unsigned int value, bool retain = false); - void publishBool(const char* topic, const bool value, bool retain = false); - void publishString(const char* topic, const String& value, bool retain = false); - void publishString(const char* topic, const std::string& value, bool retain = false); - void publishString(const char* topic, const char* value, bool retain = false); + void publishFloat(const char* topic, const float value, bool retain, const uint8_t precision = 2); + void publishInt(const char* topic, const int value, bool retain); + void publishUInt(const char* topic, const unsigned int value, bool retain); + void publishBool(const char* topic, const bool value, bool retain); + void publishString(const char* topic, const String& value, bool retain); + void publishString(const char* topic, const std::string& value, bool retain); + void publishString(const char* topic, const char* value, bool retain); void publishKeypadEntry(const String topic, NukiLock::KeypadEntry entry); void buildMqttPath(const char* path, char* outPath); diff --git a/src/networkDevices/WifiDevice.cpp b/src/networkDevices/WifiDevice.cpp index fa0f479..39b50f1 100644 --- a/src/networkDevices/WifiDevice.cpp +++ b/src/networkDevices/WifiDevice.cpp @@ -146,7 +146,23 @@ ReconnectStatus WifiDevice::reconnect() if(!isConnected() && !_isReconnecting) { _isReconnecting = true; - _wm.autoConnect(); + WiFi.disconnect(); + delay(1000); + if(!_preferences->getBool(preference_find_best_rssi, false)) WiFi.reconnect(); + else + { + if(WiFi.getMode() & WIFI_STA){ + WiFi.mode(WIFI_OFF); + int timeout = millis()+1200; + while(WiFi.getMode()!= WIFI_OFF && millis()