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/library.properties b/library.properties index 9c0b81d3..04fd42ad 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_ConnectionHandler -version=1.1.1 +version=1.1.2 author=Ubi de Feo, Cristian Maglie, Andrea Catozzi, Alexander Entinger et al. maintainer=Arduino sentence=Arduino Library for network connection management (WiFi, GSM, NB, [Ethernet], Notecard) 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..44dbd72e 100644 --- a/src/ConnectionHandlerInterface.cpp +++ b/src/ConnectionHandlerInterface.cpp @@ -27,10 +27,11 @@ ConnectionHandler::ConnectionHandler(bool const keep_alive, NetworkAdapter interface) : _keep_alive{keep_alive} +, _check_internet_availability{false} , _interface{interface} , _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..e76f1036 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -31,6 +31,8 @@ #include "ConnectionHandlerDefinitions.h" #include "connectionHandlerModels/settings.h" +#include + /****************************************************************************** TYPEDEFS ******************************************************************************/ @@ -101,8 +103,18 @@ class ConnectionHandler { return false; } + virtual void getSetting(models::NetworkSetting& s) { + memcpy(&s, &_settings, sizeof(s)); + return; + } + 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 +132,7 @@ class ConnectionHandler { models::NetworkSetting _settings; + TimeoutTable _timeoutTable; private: unsigned long _lastConnectionTickTime; diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index 6e730381..48f2f7e8 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -41,6 +41,7 @@ EthernetConnectionHandler::EthernetConnectionHandler( bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::ETHERNET} { + _settings.type = NetworkAdapter::ETHERNET; memset(_settings.eth.ip.dword, 0, sizeof(_settings.eth.ip.dword)); memset(_settings.eth.dns.dword, 0, sizeof(_settings.eth.dns.dword)); memset(_settings.eth.gateway.dword, 0, sizeof(_settings.eth.gateway.dword)); @@ -54,6 +55,7 @@ EthernetConnectionHandler::EthernetConnectionHandler( unsigned long const timeout, unsigned long const responseTimeout, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::ETHERNET} { + _settings.type = NetworkAdapter::ETHERNET; fromIPAddress(ip, _settings.eth.ip); fromIPAddress(dns, _settings.eth.dns); fromIPAddress(gateway, _settings.eth.gateway); @@ -117,7 +119,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/GenericConnectionHandler.cpp b/src/GenericConnectionHandler.cpp index ce6c198c..14b76fc5 100644 --- a/src/GenericConnectionHandler.cpp +++ b/src/GenericConnectionHandler.cpp @@ -46,6 +46,14 @@ bool GenericConnectionHandler::updateSetting(const models::NetworkSetting& s) { } } +void GenericConnectionHandler::getSetting(models::NetworkSetting& s) { + if(_ch != nullptr) { + _ch->getSetting(s); + } else { + s.type = NetworkAdapter::NONE; + } +} + NetworkConnectionState GenericConnectionHandler::updateConnectionState() { return _ch != nullptr ? _ch->updateConnectionState() : NetworkConnectionState::INIT; } diff --git a/src/GenericConnectionHandler.h b/src/GenericConnectionHandler.h index e1b315e4..5468e438 100644 --- a/src/GenericConnectionHandler.h +++ b/src/GenericConnectionHandler.h @@ -49,6 +49,7 @@ class GenericConnectionHandler : public ConnectionHandler #endif bool updateSetting(const models::NetworkSetting& s) override; + void getSetting(models::NetworkSetting& s) override; void connect() override; void disconnect() override; 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 diff --git a/src/connectionHandlerModels/settings_default.h b/src/connectionHandlerModels/settings_default.h index dc9a4efd..186cebff 100644 --- a/src/connectionHandlerModels/settings_default.h +++ b/src/connectionHandlerModels/settings_default.h @@ -23,7 +23,7 @@ namespace models { inline NetworkSetting settingsDefault(NetworkAdapter type) { #endif - NetworkSetting res = {type}; + NetworkSetting res = {type, {}}; switch(type) { #if defined(BOARD_HAS_ETHERNET)