From 39b8d3f43fe054fbfb6cacbc84a1ac7111b14785 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 15 Apr 2025 22:26:17 +0200 Subject: [PATCH] Implement Wifi reconnect watchdog Sometimes the ESP does not trigger the ARDUINO_EVENT_WIFI_STA_DISCONNECTED when a disconnect occours. In this case, no further reconnect attempt is done. To take care of this behavior, the wifi hardware is reset when no connect occours within 60 seconds.. --- include/NetworkSettings.h | 4 +++- src/NetworkSettings.cpp | 30 ++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/include/NetworkSettings.h b/include/NetworkSettings.h index 0594f5ee..04f9c005 100644 --- a/include/NetworkSettings.h +++ b/include/NetworkSettings.h @@ -65,17 +65,19 @@ private: void setupMode(); void NetworkEvent(const WiFiEvent_t event, WiFiEventInfo_t info); void disableAdminMode(); + bool wifiConfigured() const; Task _loopTask; static constexpr byte DNS_PORT = 53; bool _adminEnabled = true; - bool _forceDisconnection = false; + bool _performConnection = true; uint32_t _adminTimeoutCounter = 0; uint32_t _adminTimeoutCounterMax = 0; uint32_t _connectTimeoutTimer = 0; uint32_t _connectRedoTimer = 0; + uint32_t _lastReconnectAttempt = 0; uint32_t _lastTimerCall = 0; IPAddress _apIp; IPAddress _apNetmask; diff --git a/src/NetworkSettings.cpp b/src/NetworkSettings.cpp index a3eb6ee9..6e50ad20 100644 --- a/src/NetworkSettings.cpp +++ b/src/NetworkSettings.cpp @@ -101,6 +101,7 @@ void NetworkSettingsClass::NetworkEvent(const WiFiEvent_t event, WiFiEventInfo_t MessageOutput.printf("WiFi disconnected: %" PRIu8 "\r\n", info.wifi_sta_disconnected.reason); if (_networkMode == network_mode::WiFi) { MessageOutput.printf("Try reconnecting\r\n"); + _lastReconnectAttempt = millis(); WiFi.disconnect(true, false); WiFi.begin(); raiseEvent(network_event::NETWORK_DISCONNECTED); @@ -213,6 +214,12 @@ void NetworkSettingsClass::disableAdminMode() setupMode(); } +bool NetworkSettingsClass::wifiConfigured() const +{ + // Check if SSID is empty + return strcmp(Configuration.get().WiFi.Ssid, ""); +} + String NetworkSettingsClass::getApName() const { return String(ACCESS_POINT_NAME + String(Utils::getChipId())); @@ -244,6 +251,18 @@ void NetworkSettingsClass::loop() MessageOutput.printf("Admin AP remaining seconds: %" PRIu32 " / %" PRIu32 "\r\n", _adminTimeoutCounter, _adminTimeoutCounterMax); } } + if (_performConnection && !isConnected() && wifiConfigured() && millis() - _lastReconnectAttempt > 60000) { + MessageOutput.printf("Wifi reconnect watchdog triggered... Resetting Wifi hardware\r\n"); + WiFi.disconnect(true, false); + WiFi.mode(WIFI_MODE_NULL); + if (_adminEnabled) { + // Call enableAdminMode to reset all the timeout values. + // Otherwise the search for AP gets disabled immediatly after wifi reset. + enableAdminMode(); + } + applyConfig(); + _lastReconnectAttempt = millis(); // Just in case if the reconnect method gets not triggered + } _connectTimeoutTimer++; _connectRedoTimer++; _lastTimerCall = millis(); @@ -265,18 +284,18 @@ void NetworkSettingsClass::loop() _connectTimeoutTimer = 0; _connectRedoTimer = 0; } else { - if (_connectTimeoutTimer > WIFI_RECONNECT_TIMEOUT && !_forceDisconnection) { + if (_connectTimeoutTimer > WIFI_RECONNECT_TIMEOUT && _performConnection) { MessageOutput.printf("Disabling search for AP...\r\n"); WiFi.mode(WIFI_AP); _connectRedoTimer = 0; - _forceDisconnection = true; + _performConnection = false; } - if (_connectRedoTimer > WIFI_RECONNECT_REDO_TIMEOUT && _forceDisconnection) { + if (_connectRedoTimer > WIFI_RECONNECT_REDO_TIMEOUT && !_performConnection) { MessageOutput.printf("Enable search for AP...\r\n"); WiFi.mode(WIFI_AP_STA); applyConfig(); _connectTimeoutTimer = 0; - _forceDisconnection = false; + _performConnection = true; } } } @@ -293,8 +312,7 @@ void NetworkSettingsClass::applyConfig() const auto& config = Configuration.get().WiFi; - // Check if SSID is empty - if (!strcmp(config.Ssid, "")) { + if (!wifiConfigured()) { return; }