diff --git a/AquaMQTT/include/config/Configuration.h b/AquaMQTT/include/config/Configuration.h index 61a4a01..0c872e6 100644 --- a/AquaMQTT/include/config/Configuration.h +++ b/AquaMQTT/include/config/Configuration.h @@ -44,7 +44,6 @@ constexpr EOperationMode OPERATION_MODE = EOperationMode::MITM; */ constexpr bool OVERRIDE_TIME_AND_DATE_IN_MITM = true; - /** * Choose to publish raw messages represented as hex-string on debug mqtt topics */ @@ -53,19 +52,20 @@ constexpr bool DEBUG_RAW_SERIAL_MESSAGES = false; /** * Change the time interval where all known attributes are re-published to the MQTT broker. */ -constexpr uint32_t MQTT_FULL_UPDATE_MS = 1000*60*30; +constexpr uint32_t MQTT_FULL_UPDATE_MS = 1000 * 60 * 30; /** * Change the fixed time interval where the attributes published to the stats topic are updated. */ -constexpr uint16_t MQTT_STATS_UPDATE_MS = 5000; +constexpr uint16_t MQTT_STATS_UPDATE_MS = 5000; /** * Self explanatory internal settings: most probably you don't want to change them. */ -constexpr uint8_t WATCHDOG_TIMEOUT_S = 60; -constexpr uint8_t MQTT_MAX_TOPIC_SIZE = 80; -constexpr uint8_t MQTT_MAX_PAYLOAD_SIZE = 255; +constexpr uint8_t WATCHDOG_TIMEOUT_S = 60; +constexpr uint16_t WIFI_RECONNECT_CYCLE_S = 10; +constexpr uint8_t MQTT_MAX_TOPIC_SIZE = 80; +constexpr uint8_t MQTT_MAX_PAYLOAD_SIZE = 255; /** * Pin assignments for AquaMQTT Board Rev 1.0 diff --git a/AquaMQTT/include/handler/Wifi.h b/AquaMQTT/include/handler/Wifi.h new file mode 100644 index 0000000..43e12de --- /dev/null +++ b/AquaMQTT/include/handler/Wifi.h @@ -0,0 +1,32 @@ +#ifndef AQUAMQTT_WIFI_H +#define AQUAMQTT_WIFI_H + +#include + +namespace aquamqtt +{ +class WifiHandler +{ +public: + WifiHandler(); + + virtual ~WifiHandler() = default; + + void setup(); + + void loop(); + +private: + static void wifiCallback(WiFiEvent_t event); + + unsigned long mLastCheck; + + static bool mConnectedToWifiWithValidIpAddress; + +}; + +} // namespace aquamqtt + + + +#endif // AQUAMQTT_WIFI_H diff --git a/AquaMQTT/src/handler/Wifi.cpp b/AquaMQTT/src/handler/Wifi.cpp new file mode 100644 index 0000000..6b5a499 --- /dev/null +++ b/AquaMQTT/src/handler/Wifi.cpp @@ -0,0 +1,71 @@ +#include "handler/Wifi.h" + +#include "config/Configuration.h" + +namespace aquamqtt +{ + +bool WifiHandler::mConnectedToWifiWithValidIpAddress = false; + +WifiHandler::WifiHandler() : mLastCheck(0) +{ +} + +void WifiHandler::setup() +{ + WiFiClass::mode(WIFI_STA); + + // we don't trust the auto reconnect routine, as it seems there are edge cases where it does not work + WiFi.setAutoReconnect(false); + + // we trust the wifi callbacks to determine if we are properly connected or disconnected + WiFi.onEvent(wifiCallback); + + // begin a single wifi session + WiFi.begin(aquamqtt::config::ssid, aquamqtt::config::psk); + + // perform the next wifi check in config::WIFI_RECONNECT_CYCLE_S + mLastCheck = millis(); +} + +void WifiHandler::loop() +{ + if ((millis() - mLastCheck) >= (config::WIFI_RECONNECT_CYCLE_S * 1000)) + { + mLastCheck = millis(); + + // we don't trust WiFi.isConnected() or WiFi.status() == WL_CONNECTED, since it is suspected to be unreliable + if (!mConnectedToWifiWithValidIpAddress) + { + Serial.println("[wifi] attempting reconnect"); + WiFi.disconnect(); + WiFi.reconnect(); + } + } +} + +void WifiHandler::wifiCallback(WiFiEvent_t event) +{ + Serial.print("[wifi] event: "); + Serial.println(WiFi.eventName(event)); + + switch (event) + { + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + // if we lost connection or ip address, we wil enforce a reconnect within the next cycle + mConnectedToWifiWithValidIpAddress = false; + break; + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + // if we got connection and therefore a valid ip address we have a valid connection + Serial.print("[wifi] ip address: "); + Serial.println(WiFi.localIP().toString().c_str()); + mConnectedToWifiWithValidIpAddress = true; + break; + default: + break; + } +} + +} // namespace aquamqtt \ No newline at end of file diff --git a/AquaMQTT/src/main.cpp b/AquaMQTT/src/main.cpp index 5fd0dec..7f97597 100644 --- a/AquaMQTT/src/main.cpp +++ b/AquaMQTT/src/main.cpp @@ -1,10 +1,10 @@ #include -#include #include #include "config/Configuration.h" #include "handler/OTA.h" #include "handler/RTC.h" +#include "handler/Wifi.h" #include "task/ControllerTask.h" #include "task/HMITask.h" #include "task/ListenerTask.h" @@ -19,28 +19,18 @@ ListenerTask listenerTask; MQTTTask mqttTask; OTAHandler otaHandler; RTCHandler rtcHandler; +WifiHandler wifiHandler; + -void wifiCallback(WiFiEvent_t event) -{ - switch (event) - { - case WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED: - Serial.println(F("ARDUINO_EVENT_WIFI_STA_CONNECTED")); - break; - case WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - Serial.println(F("ARDUINO_EVENT_WIFI_STA_DISCONNECTED")); - WiFi.setAutoReconnect(true); - break; - default: - break; - } -} void loop() { // watchdog esp_task_wdt_reset(); + // handle wifi events + wifiHandler.loop(); + // handle over-the-air module in main thread otaHandler.loop(); @@ -58,10 +48,8 @@ void setup() esp_task_wdt_init(WATCHDOG_TIMEOUT_S, true); esp_task_wdt_add(nullptr); - // connect to Wi-Fi - WiFiClass::mode(WIFI_STA); - WiFi.onEvent(wifiCallback); - WiFi.begin(aquamqtt::config::ssid, aquamqtt::config::psk); + // setup wifi + wifiHandler.setup(); // setup rtc module rtcHandler.setup();