Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(wifi): do not trust platform auto reconnect routines #32

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions AquaMQTT/include/config/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -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
Expand Down
32 changes: 32 additions & 0 deletions AquaMQTT/include/handler/Wifi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef AQUAMQTT_WIFI_H
#define AQUAMQTT_WIFI_H

#include <WiFi.h>

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
71 changes: 71 additions & 0 deletions AquaMQTT/src/handler/Wifi.cpp
Original file line number Diff line number Diff line change
@@ -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
28 changes: 8 additions & 20 deletions AquaMQTT/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <Arduino.h>
#include <WiFi.h>
#include <esp_task_wdt.h>

#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"
Expand All @@ -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();

Expand All @@ -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();
Expand Down
Loading