From 8ca9bf563371fd3f4d986dd55619ef19e015eb00 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 9 Aug 2021 15:23:08 -0400 Subject: [PATCH 1/8] rewrite keepalive for wifi --- src/Wippersnapper.cpp | 18 +++++++++++------- src/Wippersnapper.h | 3 ++- src/network_interfaces/Wippersnapper_ESP32.h | 17 +++++++++++++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index b6eae63d8..7eb4b60fd 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -774,10 +774,6 @@ void Wippersnapper::connect() { statusLEDBlink(WS_LED_STATUS_CONNECTED); statusLEDDeinit(); -/* // Disable connectivity watchdog timer - Watchdog.disable(); - // Enable default WDT for application loop - Watchdog.enable(WS_WDT_TIMEOUT); */ // Attempt to process initial sync packets from broker WS._mqtt->processPackets(500); @@ -965,7 +961,8 @@ ws_status_t Wippersnapper::run() { uint32_t curTime = millis(); // Handle network connection - checkNetworkConnection(); + keepAliveWiFi(); + // Handle MQTT connection checkMQTTConnection(curTime); @@ -978,9 +975,7 @@ ws_status_t Wippersnapper::run() { // Process analog inputs WS._analogIO->processAnalogInputs(); - WS_DEBUG_PRINTLN("resetting wdt"); feedWDT(); - return status(); } @@ -1022,6 +1017,15 @@ ws_status_t Wippersnapper::status() { return _status; } + +void Wippersnapper::keepAliveWiFi() { + if (networkStatus() == WS_NET_CONNECTED) { + return; // return immediately if WL_CONNECTED + } + // Otherwise, try to reconnect + _connect(); +} + /**************************************************************************/ /*! @brief Returns the board definition status diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 796a0bb05..c1b7ad3eb 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -47,7 +47,7 @@ #include "Adafruit_SleepyDog.h" // Uncomment for staging builds -// define USE_STAGING +#define USE_STAGING #ifdef USE_STAGING #define IO_MQTT_SERVER "io.adafruit.us" @@ -192,6 +192,7 @@ class Wippersnapper { virtual void setupMQTTClient(const char *clientID); virtual ws_status_t networkStatus(); + void keepAliveWiFi(); ws_status_t status(); ws_status_t mqttStatus(); ws_board_status_t getBoardStatus(); diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index 1bdf7876a..0e26d6b73 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -209,12 +209,21 @@ 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 < 30000) { + // do nothing, busy loop during the timeout + } + // timeout expired and connected + if (WiFi.status() == WL_CONNECTED) { + _mqtt_client->setCACert(_aio_root_ca); + return; + } + // timeout expired and not connected + if (WiFi.status() != WL_CONNECTED) { + delay(30000); // delay 30 seconds } - _mqtt_client->setCACert(_aio_root_ca); } /**************************************************************************/ From 0fed496b2143b5694a6f109ca697e3d03d8ab8c5 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 9 Aug 2021 16:18:27 -0400 Subject: [PATCH 2/8] handling networking, tested against allowlist --- src/Wippersnapper.cpp | 30 +++++++++++++++++--- src/Wippersnapper.h | 3 +- src/network_interfaces/Wippersnapper_ESP32.h | 7 +---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 7eb4b60fd..f3b31e6fd 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -957,25 +957,30 @@ 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 - keepAliveWiFi(); + //keepAliveWiFi(); + handleNetworking(); // Handle MQTT connection checkMQTTConnection(curTime); // 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(); } @@ -1017,13 +1022,30 @@ ws_status_t Wippersnapper::status() { return _status; } +void Wippersnapper::handleNetworking() { + // check if WiFi network connection is alive + while(keepAliveWiFi() != WS_NET_CONNECTED) { + WS_DEBUG_PRINT("Network Status: "); + WS_DEBUG_PRINTLN(networkStatus()); + delay(20000); + feedWDT(); + }; + // TODO: + // Check if MQTT connection is alive +} + -void Wippersnapper::keepAliveWiFi() { +ws_status_t Wippersnapper::keepAliveWiFi() { + WS_DEBUG_PRINTLN("keepAliveWiFi()"); if (networkStatus() == WS_NET_CONNECTED) { - return; // return immediately if WL_CONNECTED + return WS_NET_CONNECTED; // return immediately if WL_CONNECTED } // Otherwise, try to reconnect + // TODO: add color LEDS to match main loop + WS_DEBUG_PRINTLN("Attempting to reconnect..."); + feedWDT(); _connect(); + return networkStatus(); } /**************************************************************************/ diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index c1b7ad3eb..88092a66b 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -192,7 +192,8 @@ class Wippersnapper { virtual void setupMQTTClient(const char *clientID); virtual ws_status_t networkStatus(); - void keepAliveWiFi(); + ws_status_t keepAliveWiFi(); + void handleNetworking(); ws_status_t status(); ws_status_t mqttStatus(); ws_board_status_t getBoardStatus(); diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index 0e26d6b73..a2a520c4f 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -211,7 +211,7 @@ class Wippersnapper_ESP32 : public Wippersnapper { // wait for connection to be established long startRetry = millis(); - while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 30000) { + while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 10000) { // do nothing, busy loop during the timeout } // timeout expired and connected @@ -219,11 +219,6 @@ class Wippersnapper_ESP32 : public Wippersnapper { _mqtt_client->setCACert(_aio_root_ca); return; } - // timeout expired and not connected - if (WiFi.status() != WL_CONNECTED) { - delay(30000); // delay 30 seconds - } - } /**************************************************************************/ From 05190390554cb41b05548b2ea74dc34590c31db8 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 9 Aug 2021 16:46:28 -0400 Subject: [PATCH 3/8] remove old handling code, replace with new, use LEDs in new code --- src/Wippersnapper.cpp | 92 +++++++++++-------------------------------- src/Wippersnapper.h | 8 ++-- 2 files changed, 26 insertions(+), 74 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index f3b31e6fd..c12ae23a6 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -861,51 +861,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. @@ -962,12 +917,9 @@ ws_status_t Wippersnapper::run() { // WS_DEBUG_PRINTLN("exec::run()"); uint32_t curTime = millis(); - // Handle network connection - //keepAliveWiFi(); + // Handle networking handleNetworking(); - - // Handle MQTT connection - checkMQTTConnection(curTime); + feedWDT(); // Process all incoming packets from Wippersnapper MQTT Broker WS._mqtt->processPackets(10); @@ -1023,27 +975,38 @@ ws_status_t Wippersnapper::status() { } void Wippersnapper::handleNetworking() { - // check if WiFi network connection is alive + 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(); }; - // TODO: - // Check if MQTT connection is alive + // 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) { return WS_NET_CONNECTED; // return immediately if WL_CONNECTED } // Otherwise, try to reconnect - // TODO: add color LEDS to match main loop WS_DEBUG_PRINTLN("Attempting to reconnect..."); feedWDT(); + setStatusLEDColor(LED_NET_CONNECT); _connect(); return networkStatus(); } @@ -1063,19 +1026,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)) { @@ -1085,7 +1036,7 @@ 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(); @@ -1095,10 +1046,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; diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 88092a66b..1ae4d888b 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -193,7 +193,6 @@ class Wippersnapper { virtual ws_status_t networkStatus(); ws_status_t keepAliveWiFi(); - void handleNetworking(); ws_status_t status(); ws_status_t mqttStatus(); ws_board_status_t getBoardStatus(); @@ -208,10 +207,11 @@ class Wippersnapper { // run() loop // ws_status_t run(); - ws_status_t checkNetworkConnection(); - ws_status_t checkMQTTConnection(uint32_t timeStart); - void ping(); void feedWDT(); + // Networking + void handleNetworking(); + void ping(); + // MQTT topic callbacks // // Decodes a signal message From 4eac499b04e32c3ac25f2847889f013ea87d3b54 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 9 Aug 2021 16:50:12 -0400 Subject: [PATCH 4/8] clang --- src/Wippersnapper.cpp | 16 ++++++++-------- src/Wippersnapper.h | 6 ++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index c12ae23a6..3bb15ffde 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -686,7 +686,8 @@ void Wippersnapper::subscribeWSTopics() { /**************************************************************************/ void Wippersnapper::connect() { WS_DEBUG_PRINTLN("connect()"); - // Enable WDT w/60 second timeout for all connection-related tasks (may take longer than expected) + // Enable WDT w/60 second timeout for all connection-related tasks (may take + // longer than expected) if (Watchdog.enable(60000) == 0) { WS_DEBUG_PRINTLN("ERROR: WDT initialization failure!"); setStatusLEDColor(LED_ERROR); @@ -774,7 +775,6 @@ void Wippersnapper::connect() { statusLEDBlink(WS_LED_STATUS_CONNECTED); statusLEDDeinit(); - // Attempt to process initial sync packets from broker WS._mqtt->processPackets(500); } @@ -977,7 +977,7 @@ ws_status_t Wippersnapper::status() { void Wippersnapper::handleNetworking() { bool mqttDisconnected = false; // Handle WiFi connection, BLOCKING - while(keepAliveWiFi() != WS_NET_CONNECTED) { + while (keepAliveWiFi() != WS_NET_CONNECTED) { setStatusLEDColor(LED_ERROR); WS_DEBUG_PRINT("Network Status: "); WS_DEBUG_PRINTLN(networkStatus()); @@ -1001,6 +1001,8 @@ void Wippersnapper::handleNetworking() { 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 @@ -1036,7 +1038,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 by WipperSnapper Application"); + WS_DEBUG_PRINTLN( + "Can not blink, status-LED in use by WipperSnapper Application"); } else { statusLEDBlink(WS_LED_STATUS_KAT); statusLEDDeinit(); @@ -1074,12 +1077,9 @@ ws_status_t Wippersnapper::mqttStatus() { return WS_DISCONNECTED; } - /********************************************************/ /*! @brief Feeds the WDT to prevent hardware reset. */ /*******************************************************/ -void Wippersnapper::feedWDT() { - Watchdog.reset(); -} \ No newline at end of file +void Wippersnapper::feedWDT() { Watchdog.reset(); } \ No newline at end of file diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 1ae4d888b..a5f32726f 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -39,12 +39,12 @@ // External libraries #include "Adafruit_MQTT.h" // MQTT Client -#include "Arduino.h" // Wiring +#include "Adafruit_SleepyDog.h" +#include "Arduino.h" // Wiring #include #include #include #include -#include "Adafruit_SleepyDog.h" // Uncomment for staging builds #define USE_STAGING @@ -136,7 +136,6 @@ typedef enum { WS_BOARD_DEF_UNSPECIFIED } ws_board_status_t; - #define WS_WDT_TIMEOUT 10000 ///< WDT timeout /* MQTT Configuration */ #define WS_KEEPALIVE_INTERVAL 4 ///< Session keepalive interval time, in seconds @@ -212,7 +211,6 @@ class Wippersnapper { void handleNetworking(); void ping(); - // MQTT topic callbacks // // Decodes a signal message bool decodeSignalMsg( From 8bc74e35963769c50258e63c2ad0ea175ce4a91c Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 10 Aug 2021 16:11:33 -0400 Subject: [PATCH 5/8] move header --- src/Wippersnapper.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index d2517c9a2..5468f18ad 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -212,13 +212,14 @@ class Wippersnapper { ws_status_t run(); ws_status_t checkNetworkConnection(); ws_status_t checkMQTTConnection(uint32_t timeStart); - void ping(); - void enableWDT(int timeoutMS = 0); - void feedWDT(); // Networking void handleNetworking(); void ping(); + // WDT + void enableWDT(int timeoutMS = 0); + void feedWDT(); + // MQTT topic callbacks // // Decodes a signal message bool decodeSignalMsg( From a5fbe4ad384db3e02038caea0c182be44f27f49d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 10 Aug 2021 16:14:49 -0400 Subject: [PATCH 6/8] remove circular import --- src/Wippersnapper.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 5468f18ad..21b237450 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -39,7 +39,6 @@ // External libraries #include "Adafruit_MQTT.h" // MQTT Client -#include "Adafruit_SleepyDog.h" #include "Arduino.h" // Wiring #include #include From 7938d5d5299b5e63b4bc961e881ebadbf81e04ff Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 11 Aug 2021 13:54:44 -0400 Subject: [PATCH 7/8] bump PR --- README.md | 2 ++ 1 file changed, 2 insertions(+) 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 From 443b7c2521b941cc48405fd156288bb634282a10 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 11 Aug 2021 14:00:17 -0400 Subject: [PATCH 8/8] clang --- src/Wippersnapper.h | 2 +- src/network_interfaces/Wippersnapper_ESP32.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 21b237450..a2ef7d1a9 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -39,7 +39,7 @@ // External libraries #include "Adafruit_MQTT.h" // MQTT Client -#include "Arduino.h" // Wiring +#include "Arduino.h" // Wiring #include #include #include diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index a2a520c4f..73d961fc5 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -212,7 +212,7 @@ class Wippersnapper_ESP32 : public Wippersnapper { // wait for connection to be established long startRetry = millis(); while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 10000) { - // do nothing, busy loop during the timeout + // do nothing, busy loop during the timeout } // timeout expired and connected if (WiFi.status() == WL_CONNECTED) {