diff --git a/examples/ConnectionHandlerTimeoutTable/ConnectionHandlerTimeoutTable.ino b/examples/ConnectionHandlerTimeoutTable/ConnectionHandlerTimeoutTable.ino new file mode 100644 index 00000000..ab629053 --- /dev/null +++ b/examples/ConnectionHandlerTimeoutTable/ConnectionHandlerTimeoutTable.ino @@ -0,0 +1,83 @@ +/* SECRET_ fields are in `arduino_secrets.h` (included below) + * + * This example is a lightly modified version of ConnectionHandlerDemo to showcase + * the possibility of changing the timeout values for the different states a connectionhandler have + */ + +#include + +#include "arduino_secrets.h" + +#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \ + defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT)) + #error "Please check Arduino Connection Handler supported boards list: https://github.com/arduino-libraries/Arduino_ConnectionHandler/blob/master/README.md" +#endif + +#if defined(BOARD_HAS_ETHERNET) +EthernetConnectionHandler conMan(SECRET_IP, SECRET_DNS, SECRET_GATEWAY, SECRET_NETMASK); +#elif defined(BOARD_HAS_WIFI) +WiFiConnectionHandler conMan(SECRET_WIFI_SSID, SECRET_WIFI_PASS); +#elif defined(BOARD_HAS_GSM) +GSMConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS); +#elif defined(BOARD_HAS_NB) +NBConnectionHandler conMan(SECRET_PIN); +#elif defined(BOARD_HAS_LORA) +LoRaConnectionHandler conMan(SECRET_APP_EUI, SECRET_APP_KEY); +#elif defined(BOARD_HAS_CATM1_NBIOT) +CatM1ConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS); +#elif defined(BOARD_HAS_CELLULAR) +CellularConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS); +#endif + +bool attemptConnect = false; +uint32_t lastConnToggleMs = 0; + +void setup() { + /* Initialize serial debug port and wait up to 5 seconds for port to open */ + Serial.begin(9600); + for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { } + +#ifndef __AVR__ + /* Set the debug message level: + * - DBG_ERROR: Only show error messages + * - DBG_WARNING: Show warning and error messages + * - DBG_INFO: Show info, warning, and error messages + * - DBG_DEBUG: Show debug, info, warning, and error messages + * - DBG_VERBOSE: Show all messages + */ + setDebugMessageLevel(DBG_INFO); +#endif + + /* Add callbacks to the ConnectionHandler object to get notified of network + * connection events. */ + conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect); + conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect); + conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError); + + /* By using updateTimeoutInterval I can change the timeout value for a specific + * state of the connection handler + */ + conMan.updateTimeoutInterval(NetworkConnectionState::INIT, 8000); + conMan.updateTimeoutInterval(NetworkConnectionState::CONNECTING, 1000); + conMan.updateTimeoutInterval(NetworkConnectionState::CONNECTED, 20000); + conMan.updateTimeoutInterval(NetworkConnectionState::DISCONNECTING, 200); + conMan.updateTimeoutInterval(NetworkConnectionState::DISCONNECTED, 2000); + conMan.updateTimeoutInterval(NetworkConnectionState::CLOSED, 2000); + conMan.updateTimeoutInterval(NetworkConnectionState::ERROR, 2000); +} + +void loop() { + conMan.check(); +} + +void onNetworkConnect() { + Serial.println(">>>> CONNECTED to network"); +} + +void onNetworkDisconnect() { + Serial.println(">>>> DISCONNECTED from network"); +} + +void onNetworkError() { + Serial.println(">>>> ERROR"); +} diff --git a/examples/ConnectionHandlerTimeoutTable/arduino_secrets.h b/examples/ConnectionHandlerTimeoutTable/arduino_secrets.h new file mode 100644 index 00000000..cecefa42 --- /dev/null +++ b/examples/ConnectionHandlerTimeoutTable/arduino_secrets.h @@ -0,0 +1,19 @@ +// Required for WiFiConnectionHandler +const char SECRET_WIFI_SSID[] = "SSID"; +const char SECRET_WIFI_PASS[] = "PASSWORD"; + +// Required for GSMConnectionHandler +const char SECRET_APN[] = "MOBILE PROVIDER APN ADDRESS"; +const char SECRET_PIN[] = "0000"; // Required for NBConnectionHandler +const char SECRET_GSM_USER[] = "GSM USERNAME"; +const char SECRET_GSM_PASS[] = "GSM PASSWORD"; + +// Required for LoRaConnectionHandler +const char SECRET_APP_EUI[] = "APP_EUI"; +const char SECRET_APP_KEY[] = "APP_KEY"; + +// Required for EthernetConnectionHandler (without DHCP mode) +const char SECRET_IP[] = "IP ADDRESS"; +const char SECRET_DNS[] = "DNS ADDRESS"; +const char SECRET_GATEWAY[] = "GATEWAY ADDRESS"; +const char SECRET_NETMASK[] = "NETWORK MASK"; diff --git a/src/CatM1ConnectionHandler.cpp b/src/CatM1ConnectionHandler.cpp index c8bd7fcd..ef9edb62 100644 --- a/src/CatM1ConnectionHandler.cpp +++ b/src/CatM1ConnectionHandler.cpp @@ -107,7 +107,7 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() if (ping_result < 0) { Debug.print(DBG_ERROR, F("Internet check failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), 2 * CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::CONNECTING; } else diff --git a/src/CellularConnectionHandler.cpp b/src/CellularConnectionHandler.cpp index c6a90774..62cb93b2 100644 --- a/src/CellularConnectionHandler.cpp +++ b/src/CellularConnectionHandler.cpp @@ -83,7 +83,7 @@ NetworkConnectionState CellularConnectionHandler::update_handleConnecting() if(getTime() == 0){ Debug.print(DBG_ERROR, F("Internet check failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::CONNECTING; } diff --git a/src/ConnectionHandlerDefinitions.h b/src/ConnectionHandlerDefinitions.h index 4cefc5de..3479d83f 100644 --- a/src/ConnectionHandlerDefinitions.h +++ b/src/ConnectionHandlerDefinitions.h @@ -185,21 +185,35 @@ enum class NetworkAdapter { NOTECARD }; +union TimeoutTable { + struct { + // Note: order of the following values must be preserved + // and match against NetworkConnectionState values + uint32_t init; + uint32_t connecting; + uint32_t connected; + uint32_t disconnecting; + uint32_t disconnected; + uint32_t closed; + uint32_t error; + } timeout; + uint32_t intervals[sizeof(timeout) / sizeof(uint32_t)]; +}; + /****************************************************************************** CONSTANTS ******************************************************************************/ -static unsigned int const CHECK_INTERVAL_TABLE[] = -{ +constexpr TimeoutTable DefaultTimeoutTable { #if defined(BOARD_HAS_NOTECARD) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) - /* INIT */ 4000, + 4000, // init #else - /* INIT */ 500, -#endif - /* CONNECTING */ 500, - /* CONNECTED */ 10000, - /* DISCONNECTING */ 100, - /* DISCONNECTED */ 1000, - /* CLOSED */ 1000, - /* ERROR */ 1000 + 500, // init +#endif + 500, // connecting + 10000, // connected + 100, // disconnecting + 1000, // disconnected + 1000, // closed + 1000, // error }; diff --git a/src/ConnectionHandlerInterface.cpp b/src/ConnectionHandlerInterface.cpp index 237b465d..fe52664d 100644 --- a/src/ConnectionHandlerInterface.cpp +++ b/src/ConnectionHandlerInterface.cpp @@ -31,6 +31,7 @@ ConnectionHandler::ConnectionHandler(bool const keep_alive, NetworkAdapter inter , _lastConnectionTickTime{millis()} , _check_internet_availability{false} , _current_net_connection_state{NetworkConnectionState::INIT} +, _timeoutTable(DefaultTimeoutTable) { } @@ -42,7 +43,8 @@ ConnectionHandler::ConnectionHandler(bool const keep_alive, NetworkAdapter inter NetworkConnectionState ConnectionHandler::check() { unsigned long const now = millis(); - unsigned int const connectionTickTimeInterval = CHECK_INTERVAL_TABLE[static_cast(_current_net_connection_state)]; + unsigned int const connectionTickTimeInterval = + _timeoutTable.intervals[static_cast(_current_net_connection_state)]; if((now - _lastConnectionTickTime) > connectionTickTimeInterval) { diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index 6af40d47..88c413c6 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -31,6 +31,8 @@ #include "ConnectionHandlerDefinitions.h" #include "connectionHandlerModels/settings.h" +#include + /****************************************************************************** TYPEDEFS ******************************************************************************/ @@ -103,6 +105,11 @@ class ConnectionHandler { virtual void setKeepAlive(bool keep_alive=true) { this->_keep_alive = keep_alive; } + inline void updateTimeoutTable(const TimeoutTable& t) { _timeoutTable = t; } + inline void updateTimeoutTable(TimeoutTable&& t) { _timeoutTable = std::move(t); } + inline void updateTimeoutInterval(NetworkConnectionState state, uint32_t interval) { + _timeoutTable.intervals[static_cast(state)] = interval; + } protected: virtual NetworkConnectionState updateConnectionState(); @@ -120,6 +127,7 @@ class ConnectionHandler { models::NetworkSetting _settings; + TimeoutTable _timeoutTable; private: unsigned long _lastConnectionTickTime; diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index 6e730381..ee3de244 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -117,7 +117,7 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() if (ping_result < 0) { Debug.print(DBG_ERROR, F("Internet check failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::CONNECTING; } else diff --git a/src/GSMConnectionHandler.cpp b/src/GSMConnectionHandler.cpp index 64b04d0e..edce9cd7 100644 --- a/src/GSMConnectionHandler.cpp +++ b/src/GSMConnectionHandler.cpp @@ -117,7 +117,7 @@ NetworkConnectionState GSMConnectionHandler::update_handleConnecting() if (ping_result < 0) { Debug.print(DBG_ERROR, F("PING failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::CONNECTING; } else diff --git a/src/LoRaConnectionHandler.cpp b/src/LoRaConnectionHandler.cpp index bc753fd2..1ed9168a 100644 --- a/src/LoRaConnectionHandler.cpp +++ b/src/LoRaConnectionHandler.cpp @@ -126,7 +126,7 @@ NetworkConnectionState LoRaConnectionHandler::update_handleConnecting() if (network_status != true) { Debug.print(DBG_ERROR, F("Connection to the network failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::INIT; } else diff --git a/src/NotecardConnectionHandler.cpp b/src/NotecardConnectionHandler.cpp index 466c74df..8b3d5b6e 100644 --- a/src/NotecardConnectionHandler.cpp +++ b/src/NotecardConnectionHandler.cpp @@ -518,7 +518,7 @@ NetworkConnectionState NotecardConnectionHandler::update_handleConnecting() if (!conn_status.connected_to_notehub) { if ((::millis() - _conn_start_ms) > NOTEHUB_CONN_TIMEOUT_MS) { Debug.print(DBG_ERROR, F("Timeout exceeded, connection to the network failed.")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); result = NetworkConnectionState::INIT; } else { // Continue awaiting the connection to Notehub diff --git a/src/WiFiConnectionHandler.cpp b/src/WiFiConnectionHandler.cpp index 37d3ff66..8db1b2c6 100644 --- a/src/WiFiConnectionHandler.cpp +++ b/src/WiFiConnectionHandler.cpp @@ -114,7 +114,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleInit() { #if !defined(__AVR__) Debug.print(DBG_ERROR, F("Connection to \"%s\" failed"), _settings.wifi.ssid); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::INIT)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.init); #endif return NetworkConnectionState::INIT; } @@ -146,7 +146,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() if (ping_result < 0) { Debug.print(DBG_ERROR, F("Internet check failed")); - Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), _timeoutTable.timeout.connecting); return NetworkConnectionState::CONNECTING; } #endif