diff --git a/README.md b/README.md index 5f8d988b4..15279beb0 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ WipperSnapper currently supports the following hardware. Don't see your board? D ESP32-S2 * Adafruit FunHouse +* Adafruit MagTag 2.9" +* Adafruit Metro ESP32-S2 SAMD51 * Adafruit Metro M4 AirLift Lite diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 6d3a039f0..9e43c1ec6 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -856,51 +856,6 @@ void Wippersnapper::set_ssid_pass() { WS_DEBUG_PRINTLN("ERROR: Please define a network interface!"); } -/**************************************************************************/ -/*! - @brief Checks and handles network interface connection. - @returns Network status as ws_status_t. -*/ -/**************************************************************************/ -ws_status_t Wippersnapper::checkNetworkConnection() { - if (status() < WS_NET_CONNECTED) { - WS_DEBUG_PRINTLN("WiFi connection failed out, reconnecting..."); - unsigned long startRetry = millis(); - connect(); - while (status() < WS_CONNECTED) { // return an error on timeout - if (millis() - startRetry > 60000) { - return status(); - } - delay(500); - } - } - return status(); -} - -/**************************************************************************/ -/*! - @brief Handles MQTT connection. - @param timeStart - The time which this function was called, in milliseconds. - @returns Network status, as ws_status_t. -*/ -/**************************************************************************/ -ws_status_t Wippersnapper::checkMQTTConnection(uint32_t timeStart) { - // Return quickly - if (mqttStatus() == WS_CONNECTED) { - return status(); - } - - // loop until we have a connection - // mqttStatus() will try to reconnect before returning - while (mqttStatus() != WS_CONNECTED && millis() - timeStart < 60000) { - } - if (mqttStatus() != WS_CONNECTED) { - WS_DEBUG_PRINTLN("ERROR: Disconnected from MQTT!"); - } - return status(); -} - /**************************************************************************/ /*! @brief Pings MQTT broker. @@ -952,23 +907,25 @@ bool Wippersnapper::encodePinEvent( */ /**************************************************************************/ ws_status_t Wippersnapper::run() { + // this should be a state machine, dept. on the network... + // WS_DEBUG_PRINTLN("exec::run()"); uint32_t curTime = millis(); - // Handle network connection - checkNetworkConnection(); - // Handle MQTT connection - checkMQTTConnection(curTime); + // Handle networking + handleNetworking(); + feedWDT(); // Process all incoming packets from Wippersnapper MQTT Broker WS._mqtt->processPackets(10); + feedWDT(); // Process digital inputs, digitalGPIO module WS._digitalGPIO->processDigitalInputs(); + feedWDT(); // Process analog inputs WS._analogIO->processAnalogInputs(); - feedWDT(); return status(); @@ -1012,6 +969,45 @@ ws_status_t Wippersnapper::status() { return _status; } +void Wippersnapper::handleNetworking() { + bool mqttDisconnected = false; + // Handle WiFi connection, BLOCKING + while (keepAliveWiFi() != WS_NET_CONNECTED) { + setStatusLEDColor(LED_ERROR); + WS_DEBUG_PRINT("Network Status: "); + WS_DEBUG_PRINTLN(networkStatus()); + delay(20000); + feedWDT(); + }; + // Handle MQTT connection, BLOCKING + while (mqttStatus() != WS_CONNECTED) { + setStatusLEDColor(LED_ERROR); + WS_DEBUG_PRINT("MQTT Error: "); + WS_DEBUG_PRINTLN(WS._mqtt->connectErrorString(_status)); + mqttDisconnected = true; + delay(20000); + feedWDT(); + } + // Perform re-registration if we disconnect from MQTT broker as well + if (mqttDisconnected) + registerBoard(10); +} + +ws_status_t Wippersnapper::keepAliveWiFi() { + WS_DEBUG_PRINTLN("keepAliveWiFi()"); + if (networkStatus() == WS_NET_CONNECTED) { + if (usingStatusNeoPixel) + statusLEDDeinit(); + return WS_NET_CONNECTED; // return immediately if WL_CONNECTED + } + // Otherwise, try to reconnect + WS_DEBUG_PRINTLN("Attempting to reconnect..."); + feedWDT(); + setStatusLEDColor(LED_NET_CONNECT); + _connect(); + return networkStatus(); +} + /**************************************************************************/ /*! @brief Returns the board definition status @@ -1027,19 +1023,7 @@ ws_board_status_t Wippersnapper::getBoardStatus() { return WS._boardStatus; } */ /**************************************************************************/ ws_status_t Wippersnapper::mqttStatus() { - // if the connection failed, - // return so we don't hammer IO - if (_status == WS_CONNECT_FAILED) { - WS_DEBUG_PRINT("mqttStatus() failed to connect"); -#ifdef USE_TINYUSB - WS._fileSystem->writeErrorToBootOut( - "ERROR: Failed to connect to WipperSnapper, retrying..."); -#endif - WS_DEBUG_PRINTLN(WS._mqtt->connectErrorString(_status)); - setStatusLEDColor(LED_ERROR); - return _status; - } - + // First, handle the case where we're connected if (WS._mqtt->connected()) { // ping within keepalive to keep connection open if (millis() > (_prv_ping + WS_KEEPALIVE_INTERVAL_MS)) { @@ -1049,7 +1033,8 @@ ws_status_t Wippersnapper::mqttStatus() { // blink status LED every STATUS_LED_KAT_BLINK_TIME millis if (millis() > (_prvKATBlink + STATUS_LED_KAT_BLINK_TIME)) { if (!statusLEDInit()) { - WS_DEBUG_PRINTLN("Can not blink, status-LED in use"); + WS_DEBUG_PRINTLN( + "Can not blink, status-LED in use by WipperSnapper Application"); } else { statusLEDBlink(WS_LED_STATUS_KAT); statusLEDDeinit(); @@ -1059,10 +1044,11 @@ ws_status_t Wippersnapper::mqttStatus() { return WS_CONNECTED; } - // prevent fast reconnect attempts, except for the first time through + // Next, handle the case where we are not connected and attempt to reconnect if (_last_mqtt_connect == 0 || millis() - _last_mqtt_connect > WS_KEEPALIVE_INTERVAL_MS) { _last_mqtt_connect = millis(); + setStatusLEDColor(LED_IO_CONNECT); switch (WS._mqtt->connect(WS._username, WS._key)) { case 0: return WS_CONNECTED; @@ -1115,4 +1101,4 @@ void Wippersnapper::enableWDT(int timeoutMS) { } } #endif -} \ No newline at end of file +} diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index d96e54825..a2ef7d1a9 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -194,6 +194,7 @@ class Wippersnapper { virtual void setupMQTTClient(const char *clientID); virtual ws_status_t networkStatus(); + ws_status_t keepAliveWiFi(); ws_status_t status(); ws_status_t mqttStatus(); ws_board_status_t getBoardStatus(); @@ -210,7 +211,11 @@ class Wippersnapper { ws_status_t run(); ws_status_t checkNetworkConnection(); ws_status_t checkMQTTConnection(uint32_t timeStart); + // Networking + void handleNetworking(); void ping(); + + // WDT void enableWDT(int timeoutMS = 0); void feedWDT(); diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index 1bdf7876a..73d961fc5 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -209,12 +209,16 @@ class Wippersnapper_ESP32 : public Wippersnapper { _status = WS_NET_DISCONNECTED; } - // wait until connection is established - while (WiFi.status() != WL_CONNECTED) { - delay(100); + // wait for connection to be established + long startRetry = millis(); + while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 10000) { + // do nothing, busy loop during the timeout + } + // timeout expired and connected + if (WiFi.status() == WL_CONNECTED) { + _mqtt_client->setCACert(_aio_root_ca); + return; } - - _mqtt_client->setCACert(_aio_root_ca); } /**************************************************************************/