From d4778bcb0bcb25f336bcddc99b99bfc718b705a1 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 4 Jun 2024 16:01:19 +0200 Subject: [PATCH 01/17] defining interface settings in a struct --- src/connectionHandlerModels/settings.h | 128 +++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/connectionHandlerModels/settings.h diff --git a/src/connectionHandlerModels/settings.h b/src/connectionHandlerModels/settings.h new file mode 100644 index 00000000..b47960c4 --- /dev/null +++ b/src/connectionHandlerModels/settings.h @@ -0,0 +1,128 @@ +/* + This file is part of the Arduino_ConnectionHandler library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#include "ConnectionHandlerDefinitions.h" +#include +#include + +namespace models { + constexpr size_t WifiSsidLength = 33; // Max length of wifi ssid is 32 + \0 + constexpr size_t WifiPwdLength = 64; // Max length of wifi password is 63 + \0 + + constexpr size_t CellularPinLength = 9; + constexpr size_t CellularApnLength = 101; // Max length of apn is 100 + \0 + constexpr size_t CellularLoginLength = 65; + constexpr size_t CellularPassLength = 65; + + constexpr size_t LoraAppeuiLength = 17; // appeui is 8 octets * 2 (hex format) + \0 + constexpr size_t LoraAppkeyLength = 33; // appeui is 16 octets * 2 (hex format) + \0 + constexpr size_t LoraChannelMaskLength = 13; + + #if defined(BOARD_HAS_WIFI) + struct WiFiSetting { + char ssid[WifiSsidLength]; + char pwd[WifiPwdLength]; + }; + #endif //defined(BOARD_HAS_WIFI) + + #if defined(BOARD_HAS_ETHERNET) + // this struct represents an ip address in its simplest form. + // FIXME this should be available from ArduinoCore-api IPAddress + struct ip_addr { + IPType type; + union { + uint8_t bytes[16]; + uint32_t dword[4]; + }; + }; + + struct EthernetSetting { + ip_addr ip; + ip_addr dns; + ip_addr gateway; + ip_addr netmask; + unsigned long timeout; + unsigned long response_timeout; + }; + #endif // BOARD_HAS_ETHERNET + + #if defined(BOARD_HAS_NB) || defined(BOARD_HAS_GSM) ||defined(BOARD_HAS_CELLULAR) + struct CellularSetting { + char pin[CellularPinLength]; + char apn[CellularApnLength]; + char login[CellularLoginLength]; + char pass[CellularPassLength]; + }; + #endif // defined(BOARD_HAS_NB) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_CATM1_NBIOT) || defined(BOARD_HAS_CELLULAR) + + #if defined(BOARD_HAS_GSM) + typedef CellularSetting GSMSetting; + #endif //defined(BOARD_HAS_GSM) + + #if defined(BOARD_HAS_NB) + typedef CellularSetting NBSetting; + #endif //defined(BOARD_HAS_NB) + + #if defined(BOARD_HAS_CATM1_NBIOT) + struct CATM1Setting { + char pin[CellularPinLength]; + char apn[CellularApnLength]; + char login[CellularLoginLength]; + char pass[CellularPassLength]; + uint32_t band; + uint8_t rat; + }; + #endif //defined(BOARD_HAS_CATM1_NBIOT) + +#if defined(BOARD_HAS_LORA) + struct LoraSetting { + char appeui[LoraAppeuiLength]; + char appkey[LoraAppkeyLength]; + uint8_t band; + char channelMask[LoraChannelMaskLength]; + uint8_t deviceClass; + }; +#endif + + struct NetworkSetting { + NetworkAdapter type; + union { + #if defined(BOARD_HAS_WIFI) + WiFiSetting wifi; + #endif + + #if defined(BOARD_HAS_ETHERNET) + EthernetSetting eth; + #endif + + #if defined(BOARD_HAS_NB) + NBSetting nb; + #endif + + #if defined(BOARD_HAS_GSM) + GSMSetting gsm; + #endif + + #if defined(BOARD_HAS_CATM1_NBIOT) + CATM1Setting catm1; + #endif + + #if defined(BOARD_HAS_CELLULAR) + CellularSetting cell; + #endif + + #if defined(BOARD_HAS_LORA) + LoraSetting lora; + #endif + }; + }; +} From 10195f57d394baab08b823b49af4cf38ca05434d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 5 Jun 2024 14:34:40 +0200 Subject: [PATCH 02/17] readapting ConnectionHandlerInterface to use setting struct --- src/ConnectionHandlerInterface.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index 228827e7..eecf7108 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -29,6 +29,7 @@ #include #include #include "ConnectionHandlerDefinitions.h" +#include "connectionHandlerModels/settings.h" /****************************************************************************** TYPEDEFS @@ -40,10 +41,13 @@ typedef void (*OnNetworkEventCallback)(); CLASS DECLARATION ******************************************************************************/ +// forward declaration FIXME +class GenericConnectionHandler; + class ConnectionHandler { public: - ConnectionHandler(bool const keep_alive, NetworkAdapter interface); + ConnectionHandler(bool const keep_alive=true, NetworkAdapter interface=NetworkAdapter::NONE); NetworkConnectionState check(); @@ -77,6 +81,22 @@ class ConnectionHandler { void addDisconnectCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); void addErrorCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); + /** + * Update the interface settings. This can be performed only when the interface is + * in INIT state. otherwise nothing is performed. The type of the interface should match + * the type of the settings provided + * + * @return true if the update is successful, false otherwise + */ + virtual bool updateSetting(const models::NetworkSetting& s) { + if(_current_net_connection_state == NetworkConnectionState::INIT && s.type == _interface) { + memcpy(&_settings, &s, sizeof(s)); + return true; + } + + return false; + } + protected: bool _keep_alive; @@ -88,6 +108,8 @@ class ConnectionHandler { virtual NetworkConnectionState update_handleDisconnecting() = 0; virtual NetworkConnectionState update_handleDisconnected () = 0; + models::NetworkSetting _settings; + private: unsigned long _lastConnectionTickTime; @@ -95,5 +117,7 @@ class ConnectionHandler { OnNetworkEventCallback _on_connect_event_callback = NULL, _on_disconnect_event_callback = NULL, _on_error_event_callback = NULL; + + friend GenericConnectionHandler; }; From c066a8c7abc0705011712e7e33f602a702fb17e5 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 15:15:24 +0100 Subject: [PATCH 03/17] Virtual methods and destructors for ConnectionHnadler interface --- src/ConnectionHandlerInterface.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index eecf7108..cde533af 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -49,6 +49,7 @@ class ConnectionHandler { ConnectionHandler(bool const keep_alive=true, NetworkAdapter interface=NetworkAdapter::NONE); + virtual ~ConnectionHandler() {} NetworkConnectionState check(); @@ -73,10 +74,10 @@ class ConnectionHandler { return _interface; } - void connect(); - void disconnect(); + virtual void connect(); + virtual void disconnect(); - void addCallback(NetworkConnectionEvent const event, OnNetworkEventCallback callback); + virtual void addCallback(NetworkConnectionEvent const event, OnNetworkEventCallback callback); void addConnectCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); void addDisconnectCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); void addErrorCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); @@ -97,6 +98,8 @@ class ConnectionHandler { return false; } + virtual void setKeepAlive(bool keep_alive=true) { this->_keep_alive = keep_alive; } + protected: bool _keep_alive; From 3d7564d2f34c1abd346cc90082ae7689e3e7eec4 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 3 Apr 2025 17:07:04 +0200 Subject: [PATCH 04/17] splitting check() method into updateConnectionState() and updateCallback() --- src/ConnectionHandlerInterface.cpp | 82 +++++++++++++++++++----------- src/ConnectionHandlerInterface.h | 3 ++ 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/ConnectionHandlerInterface.cpp b/src/ConnectionHandlerInterface.cpp index 2fdc10e1..1f62bde2 100644 --- a/src/ConnectionHandlerInterface.cpp +++ b/src/ConnectionHandlerInterface.cpp @@ -46,42 +46,22 @@ NetworkConnectionState ConnectionHandler::check() if((now - _lastConnectionTickTime) > connectionTickTimeInterval) { _lastConnectionTickTime = now; - NetworkConnectionState next_net_connection_state = _current_net_connection_state; - /* While the state machine is implemented here, the concrete implementation of the - * states is done in the derived connection handlers. - */ - switch (_current_net_connection_state) - { - case NetworkConnectionState::INIT: next_net_connection_state = update_handleInit (); break; - case NetworkConnectionState::CONNECTING: next_net_connection_state = update_handleConnecting (); break; - case NetworkConnectionState::CONNECTED: next_net_connection_state = update_handleConnected (); break; - case NetworkConnectionState::DISCONNECTING: next_net_connection_state = update_handleDisconnecting(); break; - case NetworkConnectionState::DISCONNECTED: next_net_connection_state = update_handleDisconnected (); break; - case NetworkConnectionState::ERROR: break; - case NetworkConnectionState::CLOSED: break; - } + NetworkConnectionState old_net_connection_state = _current_net_connection_state; + NetworkConnectionState next_net_connection_state = updateConnectionState(); /* Here we are determining whether a state transition from one state to the next has * occurred - and if it has, we call eventually registered callbacks. */ - if(next_net_connection_state != _current_net_connection_state) - { - /* Check the next state to determine the kind of state conversion which has occurred (and call the appropriate callback) */ - if(next_net_connection_state == NetworkConnectionState::CONNECTED) - { - if(_on_connect_event_callback) _on_connect_event_callback(); - } - if(next_net_connection_state == NetworkConnectionState::DISCONNECTED) - { - if(_on_disconnect_event_callback) _on_disconnect_event_callback(); - } - if(next_net_connection_state == NetworkConnectionState::ERROR) - { - if(_on_error_event_callback) _on_error_event_callback(); - } - - /* Assign new state to the member variable holding the state */ + + if(old_net_connection_state != next_net_connection_state) { + updateCallback(next_net_connection_state); + + /* It may happen that the local _current_net_connection_state + * is not updated by the updateConnectionState() call. This is the case for GenericConnection handler + * where the call of updateConnectionState() is replaced by the inner ConnectionHandler call + * that updates its state, but not the outer one. For this reason it is required to perform this call twice + */ _current_net_connection_state = next_net_connection_state; } } @@ -89,6 +69,46 @@ NetworkConnectionState ConnectionHandler::check() return _current_net_connection_state; } +NetworkConnectionState ConnectionHandler::updateConnectionState() { + NetworkConnectionState next_net_connection_state = _current_net_connection_state; + + /* While the state machine is implemented here, the concrete implementation of the + * states is done in the derived connection handlers. + */ + switch (_current_net_connection_state) + { + case NetworkConnectionState::INIT: next_net_connection_state = update_handleInit (); break; + case NetworkConnectionState::CONNECTING: next_net_connection_state = update_handleConnecting (); break; + case NetworkConnectionState::CONNECTED: next_net_connection_state = update_handleConnected (); break; + case NetworkConnectionState::DISCONNECTING: next_net_connection_state = update_handleDisconnecting(); break; + case NetworkConnectionState::DISCONNECTED: next_net_connection_state = update_handleDisconnected (); break; + case NetworkConnectionState::ERROR: break; + case NetworkConnectionState::CLOSED: break; + } + + /* Assign new state to the member variable holding the state */ + _current_net_connection_state = next_net_connection_state; + + return next_net_connection_state; +} + +void ConnectionHandler::updateCallback(NetworkConnectionState next_net_connection_state) { + + /* Check the next state to determine the kind of state conversion which has occurred (and call the appropriate callback) */ + if(next_net_connection_state == NetworkConnectionState::CONNECTED) + { + if(_on_connect_event_callback) _on_connect_event_callback(); + } + if(next_net_connection_state == NetworkConnectionState::DISCONNECTED) + { + if(_on_disconnect_event_callback) _on_disconnect_event_callback(); + } + if(next_net_connection_state == NetworkConnectionState::ERROR) + { + if(_on_error_event_callback) _on_error_event_callback(); + } +} + void ConnectionHandler::connect() { if (_current_net_connection_state != NetworkConnectionState::INIT && _current_net_connection_state != NetworkConnectionState::CONNECTING) diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index cde533af..a60da81f 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -102,6 +102,9 @@ class ConnectionHandler { protected: + virtual NetworkConnectionState updateConnectionState(); + virtual void updateCallback(NetworkConnectionState next_net_connection_state); + bool _keep_alive; NetworkAdapter _interface; From 0c341ad7c8a8066fb1664d4dccb9996b5b6c02e9 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 10:44:46 +0100 Subject: [PATCH 05/17] readapting ConnectionHandler implementation to use setting struct --- src/CatM1ConnectionHandler.cpp | 29 +++++++---- src/CatM1ConnectionHandler.h | 9 +--- src/CellularConnectionHandler.cpp | 15 +++--- src/CellularConnectionHandler.h | 7 +-- src/EthernetConnectionHandler.cpp | 87 ++++++++++++++++--------------- src/EthernetConnectionHandler.h | 8 --- src/GSMConnectionHandler.cpp | 17 +++--- src/GSMConnectionHandler.h | 7 +-- src/LoRaConnectionHandler.cpp | 22 ++++---- src/LoRaConnectionHandler.h | 5 -- src/NBConnectionHandler.cpp | 19 ++++--- src/NBConnectionHandler.h | 7 +-- src/WiFiConnectionHandler.cpp | 18 ++++--- src/WiFiConnectionHandler.h | 6 +-- 14 files changed, 124 insertions(+), 132 deletions(-) diff --git a/src/CatM1ConnectionHandler.cpp b/src/CatM1ConnectionHandler.cpp index 0263a397..b739bea3 100644 --- a/src/CatM1ConnectionHandler.cpp +++ b/src/CatM1ConnectionHandler.cpp @@ -28,16 +28,21 @@ CTOR/DTOR ******************************************************************************/ -CatM1ConnectionHandler::CatM1ConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, RadioAccessTechnologyType rat, uint32_t band, bool const keep_alive) +CatM1ConnectionHandler::CatM1ConnectionHandler() +: ConnectionHandler(true, NetworkAdapter::CATM1) { } + +CatM1ConnectionHandler::CatM1ConnectionHandler( + const char * pin, const char * apn, const char * login, const char * pass, + RadioAccessTechnologyType rat, uint32_t band, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::CATM1} -, _pin(pin) -, _apn(apn) -, _login(login) -, _pass(pass) -, _rat(rat) -, _band(band) { - + _settings.type = NetworkAdapter::CATM1; + strncpy(_settings.catm1.pin, pin, sizeof(_settings.catm1.pin)-1); + strncpy(_settings.catm1.apn, apn, sizeof(_settings.catm1.apn)-1); + strncpy(_settings.catm1.login, login, sizeof(_settings.catm1.login)-1); + strncpy(_settings.catm1.pass, pass, sizeof(_settings.catm1.pass)-1); + _settings.catm1.rat = static_cast(rat); + _settings.catm1.band = band; } /****************************************************************************** @@ -64,7 +69,13 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleInit() NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() { - if(!GSM.begin(_pin, _apn, _login, _pass, _rat, _band)) + if(!GSM.begin( + _settings.catm1.pin, + _settings.catm1.apn, + _settings.catm1.login, + _settings.catm1.pass, + static_cast(_settings.catm1.rat) , + _settings.catm1.band)) { Debug.print(DBG_ERROR, F("The board was not able to register to the network...")); return NetworkConnectionState::ERROR; diff --git a/src/CatM1ConnectionHandler.h b/src/CatM1ConnectionHandler.h index 33ac9fea..67f317b7 100644 --- a/src/CatM1ConnectionHandler.h +++ b/src/CatM1ConnectionHandler.h @@ -40,6 +40,7 @@ class CatM1ConnectionHandler : public ConnectionHandler { public: + CatM1ConnectionHandler(); CatM1ConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, RadioAccessTechnologyType rat = CATM1, uint32_t band = BAND_3 | BAND_20 | BAND_19, bool const keep_alive = true); @@ -59,14 +60,6 @@ class CatM1ConnectionHandler : public ConnectionHandler private: - const char * _pin; - const char * _apn; - const char * _login; - const char * _pass; - - RadioAccessTechnologyType _rat; - uint32_t _band; - GSMUDP _gsm_udp; GSMClient _gsm_client; }; diff --git a/src/CellularConnectionHandler.cpp b/src/CellularConnectionHandler.cpp index 2e4499a0..d0877d3e 100644 --- a/src/CellularConnectionHandler.cpp +++ b/src/CellularConnectionHandler.cpp @@ -21,14 +21,17 @@ /****************************************************************************** CTOR/DTOR ******************************************************************************/ +CellularConnectionHandler::CellularConnectionHandler() +: ConnectionHandler(true, NetworkAdapter::CELL) {} CellularConnectionHandler::CellularConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::CELL} -, _pin(pin) -, _apn(apn) -, _login(login) -, _pass(pass) { + _settings.type = NetworkAdapter::CELL; + strncpy(_settings.cell.pin, pin, sizeof(_settings.cell.pin)-1); + strncpy(_settings.cell.apn, apn, sizeof(_settings.cell.apn)-1); + strncpy(_settings.cell.login, login, sizeof(_settings.cell.login)-1); + strncpy(_settings.cell.pass, pass, sizeof(_settings.cell.pass)-1); } @@ -55,7 +58,7 @@ NetworkConnectionState CellularConnectionHandler::update_handleInit() { _cellular.begin(); _cellular.setDebugStream(Serial); - if (String(_pin).length() > 0 && !_cellular.unlockSIM(_pin)) { + if (strlen(_settings.cell.pin) > 0 && !_cellular.unlockSIM(_settings.cell.pin)) { Debug.print(DBG_ERROR, F("SIM not present or wrong PIN")); return NetworkConnectionState::ERROR; } @@ -64,7 +67,7 @@ NetworkConnectionState CellularConnectionHandler::update_handleInit() NetworkConnectionState CellularConnectionHandler::update_handleConnecting() { - if (!_cellular.connect(_apn, _login, _pass)) { + if (!_cellular.connect(String(_settings.cell.apn), String(_settings.cell.login), String(_settings.cell.pass))) { Debug.print(DBG_ERROR, F("The board was not able to register to the network...")); return NetworkConnectionState::ERROR; } diff --git a/src/CellularConnectionHandler.h b/src/CellularConnectionHandler.h index 2addd29b..fcc02c66 100644 --- a/src/CellularConnectionHandler.h +++ b/src/CellularConnectionHandler.h @@ -33,7 +33,7 @@ class CellularConnectionHandler : public ConnectionHandler { public: - + CellularConnectionHandler(); CellularConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, bool const keep_alive = true); @@ -53,11 +53,6 @@ class CellularConnectionHandler : public ConnectionHandler private: - const char * _pin; - const char * _apn; - const char * _login; - const char * _pass; - ArduinoCellular _cellular; TinyGsmClient _gsm_client = _cellular.getNetworkClient(); }; diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index 14f7aee4..af5b118e 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -25,51 +25,41 @@ CTOR/DTOR ******************************************************************************/ -EthernetConnectionHandler::EthernetConnectionHandler(unsigned long const timeout, unsigned long const responseTimeout, bool const keep_alive) -: ConnectionHandler{keep_alive, NetworkAdapter::ETHERNET} -,_ip{INADDR_NONE} -,_dns{INADDR_NONE} -,_gateway{INADDR_NONE} -,_netmask{INADDR_NONE} -,_timeout{timeout} -,_response_timeout{responseTimeout} -{ - +static inline void fromIPAddress(const IPAddress src, models::ip_addr& dst) { + if(src.type() == IPv4) { + dst.dword[IPADDRESS_V4_DWORD_INDEX] = (uint32_t)src; + } else if(src.type() == IPv6) { + for(uint8_t i=0; i static ip configuration + if (ip != INADDR_NONE) { + if (Ethernet.begin(nullptr, ip, + IPAddress(_settings.eth.dns.type, _settings.eth.dns.bytes), + IPAddress(_settings.eth.gateway.type, _settings.eth.gateway.bytes), + IPAddress(_settings.eth.netmask.type, _settings.eth.netmask.bytes), + _settings.eth.timeout, + _settings.eth.response_timeout) == 0) { + Debug.print(DBG_ERROR, F("Failed to configure Ethernet, check cable connection")); - Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", _timeout, _response_timeout); + Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", + _settings.eth.timeout, _settings.eth.response_timeout); return NetworkConnectionState::CONNECTING; } + // An ip address is not provided -> dhcp configuration } else { - if (Ethernet.begin(nullptr, _timeout, _response_timeout) == 0) { + if (Ethernet.begin(nullptr, _settings.eth.timeout, _settings.eth.response_timeout) == 0) { Debug.print(DBG_ERROR, F("Waiting Ethernet configuration from DHCP server, check cable connection")); - Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", _timeout, _response_timeout); + Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", + _settings.eth.timeout, _settings.eth.response_timeout); + return NetworkConnectionState::CONNECTING; } } diff --git a/src/EthernetConnectionHandler.h b/src/EthernetConnectionHandler.h index 35a02cd9..8ddbbe42 100644 --- a/src/EthernetConnectionHandler.h +++ b/src/EthernetConnectionHandler.h @@ -64,14 +64,6 @@ class EthernetConnectionHandler : public ConnectionHandler private: - IPAddress _ip; - IPAddress _dns; - IPAddress _gateway; - IPAddress _netmask; - - unsigned long _timeout; - unsigned long _response_timeout; - EthernetUDP _eth_udp; EthernetClient _eth_client; diff --git a/src/GSMConnectionHandler.cpp b/src/GSMConnectionHandler.cpp index 34bf1792..75f9e536 100644 --- a/src/GSMConnectionHandler.cpp +++ b/src/GSMConnectionHandler.cpp @@ -46,15 +46,17 @@ __attribute__((weak)) void mkr_gsm_feed_watchdog() /****************************************************************************** CTOR/DTOR ******************************************************************************/ +GSMConnectionHandler::GSMConnectionHandler() +: ConnectionHandler(true, NetworkAdapter::GSM) {} GSMConnectionHandler::GSMConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::GSM} -, _pin(pin) -, _apn(apn) -, _login(login) -, _pass(pass) { - + _settings.type = NetworkAdapter::GSM; + strncpy(_settings.gsm.pin, pin, sizeof(_settings.gsm.pin)-1); + strncpy(_settings.gsm.apn, apn, sizeof(_settings.gsm.apn)-1); + strncpy(_settings.gsm.login, login, sizeof(_settings.gsm.login)-1); + strncpy(_settings.gsm.pass, pass, sizeof(_settings.gsm.pass)-1); } /****************************************************************************** @@ -74,7 +76,7 @@ NetworkConnectionState GSMConnectionHandler::update_handleInit() { mkr_gsm_feed_watchdog(); - if (_gsm.begin(_pin) != GSM_READY) + if (_gsm.begin(_settings.gsm.pin) != GSM_READY) { Debug.print(DBG_ERROR, F("SIM not present or wrong PIN")); return NetworkConnectionState::ERROR; @@ -88,7 +90,8 @@ NetworkConnectionState GSMConnectionHandler::update_handleInit() mkr_gsm_feed_watchdog(); - GSM3_NetworkStatus_t const network_status = _gprs.attachGPRS(_apn, _login, _pass, true); + GSM3_NetworkStatus_t const network_status = _gprs.attachGPRS( + _settings.gsm.apn, _settings.gsm.login, _settings.gsm.pass, true); Debug.print(DBG_DEBUG, F("GPRS.attachGPRS(): %d"), network_status); if (network_status == GSM3_NetworkStatus_t::ERROR) { diff --git a/src/GSMConnectionHandler.h b/src/GSMConnectionHandler.h index 1f3db49a..891fb989 100644 --- a/src/GSMConnectionHandler.h +++ b/src/GSMConnectionHandler.h @@ -39,7 +39,7 @@ class GSMConnectionHandler : public ConnectionHandler { public: - + GSMConnectionHandler(); GSMConnectionHandler(const char * pin, const char * apn, const char * login, const char * pass, bool const keep_alive = true); @@ -59,11 +59,6 @@ class GSMConnectionHandler : public ConnectionHandler private: - const char * _pin; - const char * _apn; - const char * _login; - const char * _pass; - GSM _gsm; GPRS _gprs; GSMUDP _gsm_udp; diff --git a/src/LoRaConnectionHandler.cpp b/src/LoRaConnectionHandler.cpp index 1f454a51..bc753fd2 100644 --- a/src/LoRaConnectionHandler.cpp +++ b/src/LoRaConnectionHandler.cpp @@ -46,13 +46,13 @@ typedef enum ******************************************************************************/ LoRaConnectionHandler::LoRaConnectionHandler(char const * appeui, char const * appkey, _lora_band const band, char const * channelMask, _lora_class const device_class) : ConnectionHandler{false, NetworkAdapter::LORA} -, _appeui(appeui) -, _appkey(appkey) -, _band(band) -, _channelMask(channelMask) -, _device_class(device_class) { - + _settings.type = NetworkAdapter::LORA; + strncpy(_settings.lora.appeui, appeui, sizeof(_settings.lora.appeui)-1); + strncpy(_settings.lora.appkey, appkey, sizeof(_settings.lora.appkey)-1); + _settings.lora.band = band; + strncpy(_settings.lora.channelMask, channelMask, sizeof(_settings.lora.channelMask)-1); + _settings.lora.deviceClass = device_class; } /****************************************************************************** @@ -103,18 +103,18 @@ bool LoRaConnectionHandler::available() NetworkConnectionState LoRaConnectionHandler::update_handleInit() { - if (!_modem.begin(_band)) + if (!_modem.begin((_lora_band)_settings.lora.band)) { Debug.print(DBG_ERROR, F("Something went wrong; are you indoor? Move near a window, then reset and retry.")); return NetworkConnectionState::ERROR; } // Set channelmask based on configuration - if (_channelMask) { - _modem.sendMask(_channelMask); + if (_settings.lora.channelMask) { + _modem.sendMask(_settings.lora.channelMask); } //A delay is required between _modem.begin(band) and _modem.joinOTAA(appeui, appkey) in order to let the chip to be correctly initialized before the connection attempt delay(100); - _modem.configureClass(_device_class); + _modem.configureClass((_lora_class)_settings.lora.deviceClass); delay(100); Debug.print(DBG_INFO, F("Connecting to the network")); return NetworkConnectionState::CONNECTING; @@ -122,7 +122,7 @@ NetworkConnectionState LoRaConnectionHandler::update_handleInit() NetworkConnectionState LoRaConnectionHandler::update_handleConnecting() { - bool const network_status = _modem.joinOTAA(_appeui, _appkey); + bool const network_status = _modem.joinOTAA(_settings.lora.appeui, _settings.lora.appkey); if (network_status != true) { Debug.print(DBG_ERROR, F("Connection to the network failed")); diff --git a/src/LoRaConnectionHandler.h b/src/LoRaConnectionHandler.h index 3ddcca24..cecf8302 100644 --- a/src/LoRaConnectionHandler.h +++ b/src/LoRaConnectionHandler.h @@ -73,11 +73,6 @@ class LoRaConnectionHandler : public ConnectionHandler private: - char const * _appeui; - char const * _appkey; - _lora_band _band; - char const * _channelMask; - _lora_class _device_class; LoRaModem _modem; }; diff --git a/src/NBConnectionHandler.cpp b/src/NBConnectionHandler.cpp index eb72f3e7..02d62ba2 100644 --- a/src/NBConnectionHandler.cpp +++ b/src/NBConnectionHandler.cpp @@ -45,6 +45,10 @@ __attribute__((weak)) void mkr_nb_feed_watchdog() /****************************************************************************** CTOR/DTOR ******************************************************************************/ + +NBConnectionHandler::NBConnectionHandler() +: ConnectionHandler(true, NetworkAdapter::NB) {} + NBConnectionHandler::NBConnectionHandler(char const * pin, bool const keep_alive) : NBConnectionHandler(pin, "", keep_alive) { @@ -59,12 +63,12 @@ NBConnectionHandler::NBConnectionHandler(char const * pin, char const * apn, boo NBConnectionHandler::NBConnectionHandler(char const * pin, char const * apn, char const * login, char const * pass, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::NB} -, _pin(pin) -, _apn(apn) -, _login(login) -, _pass(pass) { - + _settings.type = NetworkAdapter::NB; + strncpy(_settings.nb.pin, pin, sizeof(_settings.nb.pin)-1); + strncpy(_settings.nb.apn, apn, sizeof(_settings.nb.apn)-1); + strncpy(_settings.nb.login, login, sizeof(_settings.nb.login)-1); + strncpy(_settings.nb.pass, pass, sizeof(_settings.nb.pass)-1); } /****************************************************************************** @@ -84,7 +88,10 @@ NetworkConnectionState NBConnectionHandler::update_handleInit() { mkr_nb_feed_watchdog(); - if (_nb.begin(_pin, _apn, _login, _pass) == NB_READY) + if (_nb.begin(_settings.nb.pin, + _settings.nb.apn, + _settings.nb.login, + _settings.nb.pass) == NB_READY) { Debug.print(DBG_INFO, F("SIM card ok")); _nb.setTimeout(NB_TIMEOUT); diff --git a/src/NBConnectionHandler.h b/src/NBConnectionHandler.h index fd2afb6c..6641bb69 100644 --- a/src/NBConnectionHandler.h +++ b/src/NBConnectionHandler.h @@ -39,7 +39,7 @@ class NBConnectionHandler : public ConnectionHandler { public: - + NBConnectionHandler(); NBConnectionHandler(char const * pin, bool const keep_alive = true); NBConnectionHandler(char const * pin, char const * apn, bool const keep_alive = true); NBConnectionHandler(char const * pin, char const * apn, char const * login, char const * pass, bool const keep_alive = true); @@ -63,11 +63,6 @@ class NBConnectionHandler : public ConnectionHandler void changeConnectionState(NetworkConnectionState _newState); - char const * _pin; - char const * _apn; - char const * _login; - char const * _pass; - NB _nb; GPRS _nb_gprs; NBUDP _nb_udp; diff --git a/src/WiFiConnectionHandler.cpp b/src/WiFiConnectionHandler.cpp index 0cd2e126..efc30fa9 100644 --- a/src/WiFiConnectionHandler.cpp +++ b/src/WiFiConnectionHandler.cpp @@ -35,12 +35,16 @@ static int const ESP_WIFI_CONNECTION_TIMEOUT = 3000; CTOR/DTOR ******************************************************************************/ +WiFiConnectionHandler::WiFiConnectionHandler() +: ConnectionHandler(true, NetworkAdapter::WIFI) { +} + WiFiConnectionHandler::WiFiConnectionHandler(char const * ssid, char const * pass, bool const keep_alive) : ConnectionHandler{keep_alive, NetworkAdapter::WIFI} -, _ssid{ssid} -, _pass{pass} { - + _settings.type = NetworkAdapter::WIFI; + strncpy(_settings.wifi.ssid, ssid, sizeof(_settings.wifi.ssid)-1); + strncpy(_settings.wifi.pwd, pass, sizeof(_settings.wifi.pwd)-1); } /****************************************************************************** @@ -99,7 +103,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() { if (WiFi.status() != WL_CONNECTED) { - WiFi.begin(_ssid, _pass); + WiFi.begin(_settings.wifi.ssid, _settings.wifi.pwd); #if defined(ARDUINO_ARCH_ESP8266) /* Wait connection otherwise board won't connect */ unsigned long start = millis(); @@ -113,7 +117,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() if (WiFi.status() != NETWORK_CONNECTED) { #if !defined(__AVR__) - Debug.print(DBG_ERROR, F("Connection to \"%s\" failed"), _ssid); + 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::CONNECTING)]); #endif return NetworkConnectionState::CONNECTING; @@ -121,7 +125,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() else { #if !defined(__AVR__) - Debug.print(DBG_INFO, F("Connected to \"%s\""), _ssid); + Debug.print(DBG_INFO, F("Connected to \"%s\""), _settings.wifi.ssid); #endif #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); @@ -136,7 +140,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnected() { #if !defined(__AVR__) Debug.print(DBG_VERBOSE, F("WiFi.status(): %d"), WiFi.status()); - Debug.print(DBG_ERROR, F("Connection to \"%s\" lost."), _ssid); + Debug.print(DBG_ERROR, F("Connection to \"%s\" lost."), _settings.wifi.ssid); #endif if (_keep_alive) { diff --git a/src/WiFiConnectionHandler.h b/src/WiFiConnectionHandler.h index 2ee674a5..1d360b70 100644 --- a/src/WiFiConnectionHandler.h +++ b/src/WiFiConnectionHandler.h @@ -62,7 +62,7 @@ class WiFiConnectionHandler : public ConnectionHandler { public: - + WiFiConnectionHandler(); WiFiConnectionHandler(char const * ssid, char const * pass, bool const keep_alive = true); @@ -80,10 +80,6 @@ class WiFiConnectionHandler : public ConnectionHandler virtual NetworkConnectionState update_handleDisconnected () override; private: - - char const * _ssid; - char const * _pass; - WiFiUDP _wifi_udp; WiFiClient _wifi_client; }; From 4abd7a230edc22c59476fba88c6c9726d212da18 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 10:33:51 +0100 Subject: [PATCH 06/17] defining a wrapper connection handler with the objective of being generic --- src/ConnectionHandlerInterface.h | 2 +- src/GenericConnectionHandler.cpp | 151 +++++++++++++++++++++++++++++++ src/GenericConnectionHandler.h | 73 +++++++++++++++ 3 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/GenericConnectionHandler.cpp create mode 100644 src/GenericConnectionHandler.h diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index a60da81f..80819605 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -51,7 +51,7 @@ class ConnectionHandler { virtual ~ConnectionHandler() {} - NetworkConnectionState check(); + virtual NetworkConnectionState check(); #if not defined(BOARD_HAS_LORA) virtual unsigned long getTime() = 0; diff --git a/src/GenericConnectionHandler.cpp b/src/GenericConnectionHandler.cpp new file mode 100644 index 00000000..f1f9eb6b --- /dev/null +++ b/src/GenericConnectionHandler.cpp @@ -0,0 +1,151 @@ +/* + This file is part of the Arduino_ConnectionHandler library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include "GenericConnectionHandler.h" +#include "Arduino_ConnectionHandler.h" + +static inline ConnectionHandler* instantiate_handler(NetworkAdapter adapter); + +bool GenericConnectionHandler::updateSetting(const models::NetworkSetting& s) { + if(_ch != nullptr && _ch->_current_net_connection_state != NetworkConnectionState::INIT) { + // If the internal connection handler is already being used and not in INIT phase we cannot update the settings + return false; + } else if(_ch != nullptr && _ch->_current_net_connection_state == NetworkConnectionState::INIT && _interface != s.type) { + // If the internal connection handler is already being used and in INIT phase and the interface type is being changed + // -> we need to deallocate the previously allocated handler + + // if interface type is not being changed -> we just need to call updateSettings + delete _ch; + _ch = nullptr; + } + + if(_ch == nullptr) { + _ch = instantiate_handler(s.type); + } + + if(_ch != nullptr) { + _interface = s.type; + _ch->setKeepAlive(_keep_alive); + return _ch->updateSetting(s); + } else { + _interface = NetworkAdapter::NONE; + + return false; + } +} + +NetworkConnectionState GenericConnectionHandler::updateConnectionState() { + return _ch != nullptr ? _ch->updateConnectionState() : NetworkConnectionState::INIT; +} + +NetworkConnectionState GenericConnectionHandler::update_handleInit() { + return _ch != nullptr ? _ch->update_handleInit() : NetworkConnectionState::INIT; +} + +NetworkConnectionState GenericConnectionHandler::update_handleConnecting() { + return _ch != nullptr ? _ch->update_handleConnecting() : NetworkConnectionState::INIT; +} + +NetworkConnectionState GenericConnectionHandler::update_handleConnected() { + return _ch != nullptr ? _ch->update_handleConnected() : NetworkConnectionState::INIT; +} + +NetworkConnectionState GenericConnectionHandler::update_handleDisconnecting() { + return _ch != nullptr ? _ch->update_handleDisconnecting() : NetworkConnectionState::INIT; +} + +NetworkConnectionState GenericConnectionHandler::update_handleDisconnected() { + return _ch != nullptr ? _ch->update_handleDisconnected() : NetworkConnectionState::INIT; +} + +#if not (defined(BOARD_HAS_LORA) or defined(BOARD_HAS_NOTECARD)) +unsigned long GenericConnectionHandler::getTime() { + return _ch != nullptr ? _ch->getTime() : 0; +} + +Client & GenericConnectionHandler::getClient() { + return _ch->getClient(); // NOTE _ch may be nullptr +} + +UDP & GenericConnectionHandler::getUDP() { + return _ch->getUDP(); // NOTE _ch may be nullptr +} + +#endif // not (defined(BOARD_HAS_LORA) or defined(BOARD_HAS_NOTECARD)) + +void GenericConnectionHandler::connect() { + if(_ch!=nullptr) { + _ch->connect(); + } + ConnectionHandler::connect(); +} + +void GenericConnectionHandler::disconnect() { + if(_ch!=nullptr) { + _ch->disconnect(); + } + ConnectionHandler::disconnect(); +} + +void GenericConnectionHandler::setKeepAlive(bool keep_alive) { + _keep_alive = keep_alive; + + if(_ch!=nullptr) { + _ch->setKeepAlive(keep_alive); + } +} + +static inline ConnectionHandler* instantiate_handler(NetworkAdapter adapter) { + switch(adapter) { + #if defined(BOARD_HAS_WIFI) + case NetworkAdapter::WIFI: + return new WiFiConnectionHandler(); + break; + #endif + + #if defined(BOARD_HAS_ETHERNET) + case NetworkAdapter::ETHERNET: + return new EthernetConnectionHandler(); + break; + #endif + + #if defined(BOARD_HAS_NB) + case NetworkAdapter::NB: + return new NBConnectionHandler(); + break; + #endif + + #if defined(BOARD_HAS_GSM) + case NetworkAdapter::GSM: + return new GSMConnectionHandler(); + break; + #endif + + #if defined(BOARD_HAS_CATM1_NBIOT) + case NetworkAdapter::CATM1: + return new CatM1ConnectionHandler(); + break; + #endif + + #if defined(BOARD_HAS_CELLULAR) + case NetworkAdapter::CELL: + return new CellularConnectionHandler(); + break; + #endif + + default: + Debug.print(DBG_ERROR, "Network adapter not supported by this platform: %d", adapter); + return nullptr; + } +} diff --git a/src/GenericConnectionHandler.h b/src/GenericConnectionHandler.h new file mode 100644 index 00000000..e1b315e4 --- /dev/null +++ b/src/GenericConnectionHandler.h @@ -0,0 +1,73 @@ +/* + This file is part of the Arduino_ConnectionHandler library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_GENERIC_CONNECTION_HANDLER_H_ +#define ARDUINO_GENERIC_CONNECTION_HANDLER_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include "ConnectionHandlerInterface.h" + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ + +/** GenericConnectionHandler class + * This class aims to wrap a connectionHandler and provide a generic way to + * instantiate a specific connectionHandler type + */ +class GenericConnectionHandler : public ConnectionHandler +{ + public: + + GenericConnectionHandler(bool const keep_alive=true): ConnectionHandler(keep_alive), _ch(nullptr) {} + + #if defined(BOARD_HAS_NOTECARD) || defined(BOARD_HAS_LORA) + virtual bool available() = 0; + virtual int read() = 0; + virtual int write(const uint8_t *buf, size_t size) = 0; + #else + unsigned long getTime() override; + + /* + * NOTE: The following functions have a huge risk of returning a reference to a non existing memory location + * It is important to make sure that the internal connection handler is already allocated before calling them + * When updateSettings is called and the internal connectionHandler is reallocated the references to TCP and UDP + * handles should be deleted. + */ + Client & getClient() override; + UDP & getUDP() override; + #endif + + bool updateSetting(const models::NetworkSetting& s) override; + + void connect() override; + void disconnect() override; + + void setKeepAlive(bool keep_alive=true) override; + + protected: + + NetworkConnectionState updateConnectionState() override; + + NetworkConnectionState update_handleInit () override; + NetworkConnectionState update_handleConnecting () override; + NetworkConnectionState update_handleConnected () override; + NetworkConnectionState update_handleDisconnecting() override; + NetworkConnectionState update_handleDisconnected () override; + + private: + + ConnectionHandler* _ch; +}; + +#endif /* ARDUINO_GENERIC_CONNECTION_HANDLER_H_ */ From 773544342772a56076c4c3c22ee89be25ffb86c9 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 24 Sep 2024 12:33:13 +0200 Subject: [PATCH 07/17] adding NONE as interface in order to make sense of GenericConnectionHandler --- src/ConnectionHandlerDefinitions.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ConnectionHandlerDefinitions.h b/src/ConnectionHandlerDefinitions.h index 4f295592..9297dc0c 100644 --- a/src/ConnectionHandlerDefinitions.h +++ b/src/ConnectionHandlerDefinitions.h @@ -174,6 +174,7 @@ enum class NetworkConnectionEvent { }; enum class NetworkAdapter { + NONE, WIFI, ETHERNET, NB, From 2084b1697d05c1d5beed96a4b770cfa89f002e08 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 26 Sep 2024 11:27:36 +0200 Subject: [PATCH 08/17] EthernetConnectionHandler improving formatting for constructors and removing redundant constructor with strings --- src/EthernetConnectionHandler.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/EthernetConnectionHandler.h b/src/EthernetConnectionHandler.h index 8ddbbe42..738b6a8c 100644 --- a/src/EthernetConnectionHandler.h +++ b/src/EthernetConnectionHandler.h @@ -44,16 +44,24 @@ class EthernetConnectionHandler : public ConnectionHandler { public: - EthernetConnectionHandler(unsigned long const timeout = 15000, unsigned long const responseTimeout = 4000, bool const keep_alive = true); - EthernetConnectionHandler(const IPAddress ip, const IPAddress dns, const IPAddress gateway, const IPAddress netmask, unsigned long const timeout = 15000, unsigned long const responseTimeout = 4000, bool const keep_alive = true); - EthernetConnectionHandler(const char * ip, const char * dns, const char * gateway, const char * netmask, unsigned long const timeout = 15000, unsigned long const responseTimeout = 4000, bool const keep_alive = true); - + EthernetConnectionHandler( + unsigned long const timeout = 15000, + unsigned long const responseTimeout = 4000, + bool const keep_alive = true); + + EthernetConnectionHandler( + const IPAddress ip, + const IPAddress dns, + const IPAddress gateway, + const IPAddress netmask, + unsigned long const timeout = 15000, + unsigned long const responseTimeout = 4000, + bool const keep_alive = true); virtual unsigned long getTime() override { return 0; } virtual Client & getClient() override{ return _eth_client; } virtual UDP & getUDP() override { return _eth_udp; } - protected: virtual NetworkConnectionState update_handleInit () override; From 9a641912d9dd2bfdfd24a88c4576d3dfcd950a02 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 25 Sep 2024 12:22:28 +0200 Subject: [PATCH 09/17] adding an example for GenericConnectionHandler --- .../GenericConnectionHandlerDemo.ino | 139 ++++++++++++++++++ .../arduino_secrets.h | 19 +++ 2 files changed, 158 insertions(+) create mode 100644 examples/GenericConnectionHandlerDemo/GenericConnectionHandlerDemo.ino create mode 100644 examples/GenericConnectionHandlerDemo/arduino_secrets.h diff --git a/examples/GenericConnectionHandlerDemo/GenericConnectionHandlerDemo.ino b/examples/GenericConnectionHandlerDemo/GenericConnectionHandlerDemo.ino new file mode 100644 index 00000000..2ce18f7e --- /dev/null +++ b/examples/GenericConnectionHandlerDemo/GenericConnectionHandlerDemo.ino @@ -0,0 +1,139 @@ +/* SECRET_ fields are in `arduino_secrets.h` (included below) + * + * If using a WiFi board (Arduino MKR1000, MKR WiFi 1010, Nano 33 IoT, UNO + * WiFi Rev 2 or ESP8266/32), create a WiFiConnectionHandler object by adding + * Network Name (SECRET_WIFI_SSID) and password (SECRET_WIFI_PASS) in the + * arduino_secrets.h file (or Secrets tab in Create Web Editor). + * + * WiFiConnectionHandler conMan(SECRET_WIFI_SSID, SECRET_WIFI_PASS); + * + * If using a MKR GSM 1400 or other GSM boards supporting the same API you'll + * need a GSMConnectionHandler object as follows + * + * GSMConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS); + * + * If using a MKR NB1500 you'll need a NBConnectionHandler object as follows + * + * NBConnectionHandler conMan(SECRET_PIN); + * + * If using a Portenta + Ethernet shield you'll need a EthernetConnectionHandler object as follows: + * + * DHCP mode + * EthernetConnectionHandler conMan; + * + * Manual configuration + * EthernetConnectionHandler conMan(SECRET_IP, SECRET_DNS, SECRET_GATEWAY, SECRET_NETMASK); + * + * Manual configuration will fallback on DHCP mode if SECRET_IP is invalid or equal to INADDR_NONE. + * + */ + +#include + +#include "arduino_secrets.h" + +#define CONN_TOGGLE_MS 60000 + +#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 + +GenericConnectionHandler conMan; + + +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 + + models::NetworkSetting setting = models::settingsDefault(NetworkAdapter::WIFI); + + strcpy(setting.wifi.ssid, SECRET_WIFI_SSID); + strcpy(setting.wifi.pwd, SECRET_WIFI_PASS); + + /* 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); + + conMan.updateSetting(setting); + Serial.print("Network Adapter Interface: "); + switch (conMan.getInterface()) { + case NetworkAdapter::WIFI: + Serial.println("Wi-Fi"); + break; + case NetworkAdapter::ETHERNET: + Serial.println("Ethernet"); + break; + case NetworkAdapter::NB: + Serial.println("Narrowband"); + break; + case NetworkAdapter::GSM: + Serial.println("GSM"); + break; + case NetworkAdapter::LORA: + Serial.println("LoRa"); + break; + case NetworkAdapter::CATM1: + Serial.println("Category M1"); + break; + case NetworkAdapter::CELL: + Serial.println("Cellular"); + break; + default: + Serial.println("Unknown"); + break; + } +} + +void loop() { + /* Toggle the connection every `CONN_TOGGLE_MS` milliseconds */ + if ((millis() - lastConnToggleMs) > CONN_TOGGLE_MS) { + Serial.println("Toggling connection..."); + if (attemptConnect) { + conMan.connect(); + } else { + conMan.disconnect(); + } + attemptConnect = !attemptConnect; + lastConnToggleMs = millis(); + } + + /* The following code keeps on running connection workflows on our + * ConnectionHandler object, hence allowing reconnection in case of failure + * and notification of connect/disconnect event if enabled (see + * addConnectCallback/addDisconnectCallback) NOTE: any use of delay() within + * the loop or methods called from it will delay the execution of .update(), + * which might not guarantee the correct functioning of the ConnectionHandler + * object. + */ + 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/GenericConnectionHandlerDemo/arduino_secrets.h b/examples/GenericConnectionHandlerDemo/arduino_secrets.h new file mode 100644 index 00000000..cecefa42 --- /dev/null +++ b/examples/GenericConnectionHandlerDemo/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"; From 2760757e0a050a9278a048f7c6ac97d1bff06caa Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 22 Jan 2025 13:22:57 +0100 Subject: [PATCH 10/17] adding a function to get the dafault initialization values for NetworkSetting --- src/connectionHandlerModels/settings.h | 2 + .../settings_default.h | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/connectionHandlerModels/settings_default.h diff --git a/src/connectionHandlerModels/settings.h b/src/connectionHandlerModels/settings.h index b47960c4..40319d66 100644 --- a/src/connectionHandlerModels/settings.h +++ b/src/connectionHandlerModels/settings.h @@ -126,3 +126,5 @@ namespace models { }; }; } + +#include "settings_default.h" diff --git a/src/connectionHandlerModels/settings_default.h b/src/connectionHandlerModels/settings_default.h new file mode 100644 index 00000000..dc9a4efd --- /dev/null +++ b/src/connectionHandlerModels/settings_default.h @@ -0,0 +1,72 @@ +/* + This file is part of the Arduino_ConnectionHandler library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once +#include "settings.h" + +namespace models { + + /* + * if the cpp version is older than cpp14 then a constexpr function cannot include + * other than a simple return statement, thsu we can define it only as inline + */ + #if __cplusplus > 201103L + constexpr NetworkSetting settingsDefault(NetworkAdapter type) { + #else + inline NetworkSetting settingsDefault(NetworkAdapter type) { + #endif + + NetworkSetting res = {type}; + + switch(type) { + #if defined(BOARD_HAS_ETHERNET) + case NetworkAdapter::ETHERNET: + res.eth.timeout = 15000; + res.eth.response_timeout = 4000; + break; + #endif //defined(BOARD_HAS_ETHERNET) + + #if defined(BOARD_HAS_CATM1_NBIOT) + case NetworkAdapter::CATM1: + res.catm1.rat = 7; // CATM1 + res.catm1.band = 0x04 | 0x80000 | 0x40000; // BAND_3 | BAND_20 | BAND_19 + break; + #endif //defined(BOARD_HAS_CATM1_NBIOT) + + #if defined(BOARD_HAS_LORA) + case NetworkAdapter::LORA: + res.lora.band = 5; // _lora_band::EU868 + res.lora.channelMask[0] = '\0'; + res.lora.deviceClass = 'A'; // _lora_class::CLASS_A + break; + #endif //defined(BOARD_HAS_LORA) + + #if defined(BOARD_HAS_WIFI) + case NetworkAdapter::WIFI: // nothing todo, default optional values are fine with 0 + #endif //defined(BOARD_HAS_WIFI) + + #if defined(BOARD_HAS_NB) + case NetworkAdapter::NB: // nothing todo, default optional values are fine with 0 + #endif //defined(BOARD_HAS_NB) + + #if defined(BOARD_HAS_GSM) + case NetworkAdapter::GSM: // nothing todo, default optional values are fine with 0 + #endif //defined(BOARD_HAS_GSM) + + #if defined(BOARD_HAS_CELLULAR) + case NetworkAdapter::CELL: // nothing todo, default optional values are fine with 0 + #endif //defined(BOARD_HAS_CELLULAR) + default: + (void) 0; + } + + return res; + } +} From 12a4c635de5a74ddc2a073882c2d93affcc3b091 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 23 Dec 2024 20:38:58 +0100 Subject: [PATCH 11/17] set connected state after checking internet availability use ping for all connectivity compile fix for esp8266 and esp32 remove check ping for mkrnb --- src/CatM1ConnectionHandler.cpp | 30 +++++++++++++++++++++------ src/CellularConnectionHandler.cpp | 19 +++++++++++++---- src/EthernetConnectionHandler.cpp | 34 +++++++++++++++++++++++-------- src/WiFiConnectionHandler.cpp | 28 +++++++++++++++++++------ 4 files changed, 87 insertions(+), 24 deletions(-) diff --git a/src/CatM1ConnectionHandler.cpp b/src/CatM1ConnectionHandler.cpp index b739bea3..899d7c35 100644 --- a/src/CatM1ConnectionHandler.cpp +++ b/src/CatM1ConnectionHandler.cpp @@ -64,11 +64,7 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleInit() pinMode(ON_MKR2, OUTPUT); digitalWrite(ON_MKR2, HIGH); #endif - return NetworkConnectionState::CONNECTING; -} -NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() -{ if(!GSM.begin( _settings.catm1.pin, _settings.catm1.apn, @@ -80,8 +76,30 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() Debug.print(DBG_ERROR, F("The board was not able to register to the network...")); return NetworkConnectionState::ERROR; } - Debug.print(DBG_INFO, F("Connected to Network")); - return NetworkConnectionState::CONNECTED; + + + return NetworkConnectionState::CONNECTING; +} + +NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() +{ + if (!GSM.isConnected()) + { + return NetworkConnectionState::INIT; + } + int ping_result = GSM.ping("time.arduino.cc"); + Debug.print(DBG_INFO, F("GSM.ping(): %d"), ping_result); + 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)]); + return NetworkConnectionState::CONNECTING; + } + else + { + Debug.print(DBG_INFO, F("Connected to Internet")); + return NetworkConnectionState::CONNECTED; + } } NetworkConnectionState CatM1ConnectionHandler::update_handleConnected() diff --git a/src/CellularConnectionHandler.cpp b/src/CellularConnectionHandler.cpp index d0877d3e..59be8026 100644 --- a/src/CellularConnectionHandler.cpp +++ b/src/CellularConnectionHandler.cpp @@ -62,16 +62,27 @@ NetworkConnectionState CellularConnectionHandler::update_handleInit() Debug.print(DBG_ERROR, F("SIM not present or wrong PIN")); return NetworkConnectionState::ERROR; } - return NetworkConnectionState::CONNECTING; -} -NetworkConnectionState CellularConnectionHandler::update_handleConnecting() -{ if (!_cellular.connect(String(_settings.cell.apn), String(_settings.cell.login), String(_settings.cell.pass))) { Debug.print(DBG_ERROR, F("The board was not able to register to the network...")); return NetworkConnectionState::ERROR; } Debug.print(DBG_INFO, F("Connected to Network")); + return NetworkConnectionState::CONNECTING; +} + +NetworkConnectionState CellularConnectionHandler::update_handleConnecting() +{ + if (!_cellular.isConnectedToInternet()) { + return NetworkConnectionState::INIT; + } + + 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)]); + return NetworkConnectionState::CONNECTING; + } + return NetworkConnectionState::CONNECTED; } diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index af5b118e..2c9049ce 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -20,6 +20,7 @@ #ifdef BOARD_HAS_ETHERNET /* Only compile if the board has ethernet */ #include "EthernetConnectionHandler.h" +#include /****************************************************************************** CTOR/DTOR @@ -72,11 +73,6 @@ NetworkConnectionState EthernetConnectionHandler::update_handleInit() Debug.print(DBG_ERROR, F("Error, ethernet shield was not found.")); return NetworkConnectionState::ERROR; } - return NetworkConnectionState::CONNECTING; -} - -NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() -{ IPAddress ip(_settings.eth.ip.type, _settings.eth.ip.bytes); // An ip address is provided -> static ip configuration @@ -91,7 +87,7 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() Debug.print(DBG_ERROR, F("Failed to configure Ethernet, check cable connection")); Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", _settings.eth.timeout, _settings.eth.response_timeout); - return NetworkConnectionState::CONNECTING; + return NetworkConnectionState::INIT; } // An ip address is not provided -> dhcp configuration } else { @@ -100,11 +96,33 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d", _settings.eth.timeout, _settings.eth.response_timeout); - return NetworkConnectionState::CONNECTING; + return NetworkConnectionState::INIT; } } - return NetworkConnectionState::CONNECTED; + return NetworkConnectionState::CONNECTING; +} + +NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() +{ + if (Ethernet.linkStatus() == LinkOFF) { + return NetworkConnectionState::INIT; + } + + int ping_result = Ethernet.ping("time.arduino.cc"); + Debug.print(DBG_INFO, F("Ethernet.ping(): %d"), ping_result); + 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)]); + return NetworkConnectionState::CONNECTING; + } + else + { + Debug.print(DBG_INFO, F("Connected to Internet")); + return NetworkConnectionState::CONNECTED; + } + } NetworkConnectionState EthernetConnectionHandler::update_handleConnected() diff --git a/src/WiFiConnectionHandler.cpp b/src/WiFiConnectionHandler.cpp index efc30fa9..4e2d9a85 100644 --- a/src/WiFiConnectionHandler.cpp +++ b/src/WiFiConnectionHandler.cpp @@ -96,11 +96,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleInit() #else WiFi.mode(WIFI_STA); #endif /* #if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) */ - return NetworkConnectionState::CONNECTING; -} -NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() -{ if (WiFi.status() != WL_CONNECTED) { WiFi.begin(_settings.wifi.ssid, _settings.wifi.pwd); @@ -120,7 +116,7 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() 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::CONNECTING)]); #endif - return NetworkConnectionState::CONNECTING; + return NetworkConnectionState::INIT; } else { @@ -130,8 +126,28 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) configTime(0, 0, "time.arduino.cc", "pool.ntp.org", "time.nist.gov"); #endif - return NetworkConnectionState::CONNECTED; + return NetworkConnectionState::CONNECTING; + } +} + +NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() +{ + if (WiFi.status() != WL_CONNECTED){ + return NetworkConnectionState::INIT; } + #if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) + int ping_result = WiFi.ping("time.arduino.cc"); + Debug.print(DBG_INFO, F("WiFi.ping(): %d"), ping_result); + 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)]); + return NetworkConnectionState::CONNECTING; + } + #endif + Debug.print(DBG_INFO, F("Connected to Internet")); + return NetworkConnectionState::CONNECTED; + } NetworkConnectionState WiFiConnectionHandler::update_handleConnected() From a5cf9a06c9d40c303cb923d43a43e3cbd8250672 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Wed, 15 Jan 2025 15:38:42 +0100 Subject: [PATCH 12/17] update init interval --- src/ConnectionHandlerDefinitions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ConnectionHandlerDefinitions.h b/src/ConnectionHandlerDefinitions.h index 9297dc0c..4cefc5de 100644 --- a/src/ConnectionHandlerDefinitions.h +++ b/src/ConnectionHandlerDefinitions.h @@ -191,12 +191,12 @@ enum class NetworkAdapter { static unsigned int const CHECK_INTERVAL_TABLE[] = { - /* INIT */ 100, #if defined(BOARD_HAS_NOTECARD) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) - /* CONNECTING */ 4000, + /* INIT */ 4000, #else - /* CONNECTING */ 500, + /* INIT */ 500, #endif + /* CONNECTING */ 500, /* CONNECTED */ 10000, /* DISCONNECTING */ 100, /* DISCONNECTED */ 1000, From c2a81e593716b752dcec7eb6c84a44512d4c1092 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Tue, 8 Apr 2025 11:15:25 +0200 Subject: [PATCH 13/17] enable or disable check internet availability --- src/CatM1ConnectionHandler.cpp | 7 +++++-- src/CellularConnectionHandler.cpp | 4 ++++ src/ConnectionHandlerInterface.cpp | 1 + src/ConnectionHandlerInterface.h | 4 ++++ src/EthernetConnectionHandler.cpp | 4 ++++ src/GSMConnectionHandler.cpp | 6 ++++++ src/GenericConnectionHandler.cpp | 1 + src/WiFiConnectionHandler.cpp | 5 +++++ 8 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/CatM1ConnectionHandler.cpp b/src/CatM1ConnectionHandler.cpp index 899d7c35..2a63dea0 100644 --- a/src/CatM1ConnectionHandler.cpp +++ b/src/CatM1ConnectionHandler.cpp @@ -76,8 +76,6 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleInit() Debug.print(DBG_ERROR, F("The board was not able to register to the network...")); return NetworkConnectionState::ERROR; } - - return NetworkConnectionState::CONNECTING; } @@ -87,6 +85,11 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting() { return NetworkConnectionState::INIT; } + + if(!_check_internet_availability){ + return NetworkConnectionState::CONNECTED; + } + int ping_result = GSM.ping("time.arduino.cc"); Debug.print(DBG_INFO, F("GSM.ping(): %d"), ping_result); if (ping_result < 0) diff --git a/src/CellularConnectionHandler.cpp b/src/CellularConnectionHandler.cpp index 59be8026..c6a90774 100644 --- a/src/CellularConnectionHandler.cpp +++ b/src/CellularConnectionHandler.cpp @@ -77,6 +77,10 @@ NetworkConnectionState CellularConnectionHandler::update_handleConnecting() return NetworkConnectionState::INIT; } + if (!_check_internet_availability) { + return NetworkConnectionState::CONNECTED; + } + 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)]); diff --git a/src/ConnectionHandlerInterface.cpp b/src/ConnectionHandlerInterface.cpp index 1f62bde2..237b465d 100644 --- a/src/ConnectionHandlerInterface.cpp +++ b/src/ConnectionHandlerInterface.cpp @@ -29,6 +29,7 @@ ConnectionHandler::ConnectionHandler(bool const keep_alive, NetworkAdapter inter : _keep_alive{keep_alive} , _interface{interface} , _lastConnectionTickTime{millis()} +, _check_internet_availability{false} , _current_net_connection_state{NetworkConnectionState::INIT} { diff --git a/src/ConnectionHandlerInterface.h b/src/ConnectionHandlerInterface.h index 80819605..6af40d47 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -76,6 +76,9 @@ class ConnectionHandler { virtual void connect(); virtual void disconnect(); + void enableCheckInternetAvailability(bool enable) { + _check_internet_availability = enable; + } virtual void addCallback(NetworkConnectionEvent const event, OnNetworkEventCallback callback); void addConnectCallback(OnNetworkEventCallback callback) __attribute__((deprecated)); @@ -106,6 +109,7 @@ class ConnectionHandler { virtual void updateCallback(NetworkConnectionState next_net_connection_state); bool _keep_alive; + bool _check_internet_availability; NetworkAdapter _interface; virtual NetworkConnectionState update_handleInit () = 0; diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index 2c9049ce..543f0737 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -109,6 +109,10 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting() return NetworkConnectionState::INIT; } + if (!_check_internet_availability) { + return NetworkConnectionState::CONNECTED; + } + int ping_result = Ethernet.ping("time.arduino.cc"); Debug.print(DBG_INFO, F("Ethernet.ping(): %d"), ping_result); if (ping_result < 0) diff --git a/src/GSMConnectionHandler.cpp b/src/GSMConnectionHandler.cpp index 75f9e536..64b04d0e 100644 --- a/src/GSMConnectionHandler.cpp +++ b/src/GSMConnectionHandler.cpp @@ -53,6 +53,8 @@ GSMConnectionHandler::GSMConnectionHandler(const char * pin, const char * apn, c : ConnectionHandler{keep_alive, NetworkAdapter::GSM} { _settings.type = NetworkAdapter::GSM; + // To keep the backward compatibility, the user can call enableCheckInternetAvailability(false) for disabling the check + _check_internet_availability = true; strncpy(_settings.gsm.pin, pin, sizeof(_settings.gsm.pin)-1); strncpy(_settings.gsm.apn, apn, sizeof(_settings.gsm.apn)-1); strncpy(_settings.gsm.login, login, sizeof(_settings.gsm.login)-1); @@ -105,6 +107,10 @@ NetworkConnectionState GSMConnectionHandler::update_handleInit() NetworkConnectionState GSMConnectionHandler::update_handleConnecting() { + if(!_check_internet_availability){ + return NetworkConnectionState::CONNECTED; + } + Debug.print(DBG_INFO, F("Sending PING to outer space...")); int const ping_result = _gprs.ping("time.arduino.cc"); Debug.print(DBG_INFO, F("GPRS.ping(): %d"), ping_result); diff --git a/src/GenericConnectionHandler.cpp b/src/GenericConnectionHandler.cpp index f1f9eb6b..ce6c198c 100644 --- a/src/GenericConnectionHandler.cpp +++ b/src/GenericConnectionHandler.cpp @@ -37,6 +37,7 @@ bool GenericConnectionHandler::updateSetting(const models::NetworkSetting& s) { if(_ch != nullptr) { _interface = s.type; _ch->setKeepAlive(_keep_alive); + _ch->enableCheckInternetAvailability(_check_internet_availability); return _ch->updateSetting(s); } else { _interface = NetworkAdapter::NONE; diff --git a/src/WiFiConnectionHandler.cpp b/src/WiFiConnectionHandler.cpp index 4e2d9a85..218e1cc1 100644 --- a/src/WiFiConnectionHandler.cpp +++ b/src/WiFiConnectionHandler.cpp @@ -135,6 +135,11 @@ NetworkConnectionState WiFiConnectionHandler::update_handleConnecting() if (WiFi.status() != WL_CONNECTED){ return NetworkConnectionState::INIT; } + + if(!_check_internet_availability){ + return NetworkConnectionState::CONNECTED; + } + #if !defined(ARDUINO_ARCH_ESP8266) && !defined(ARDUINO_ARCH_ESP32) int ping_result = WiFi.ping("time.arduino.cc"); Debug.print(DBG_INFO, F("WiFi.ping(): %d"), ping_result); From f3412f69876f3f867a02cc2f22680e29a3bca5d6 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 8 May 2025 12:04:17 +0200 Subject: [PATCH 14/17] add example --- .github/workflows/compile-examples.yml | 1 + .../CheckInternetAvailabilityDemo.ino | 152 ++++++++++++++++++ .../arduino_secrets.h | 19 +++ 3 files changed, 172 insertions(+) create mode 100644 examples/CheckInternetAvailabilityDemo/CheckInternetAvailabilityDemo.ino create mode 100644 examples/CheckInternetAvailabilityDemo/arduino_secrets.h diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 808258ed..5541359d 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -38,6 +38,7 @@ jobs: - name: Blues Wireless Notecard SKETCH_PATHS: | - examples/ConnectionHandlerDemo + - examples/CheckInternetAvailabilityDemo ARDUINOCORE_MBED_STAGING_PATH: extras/ArduinoCore-mbed ARDUINOCORE_API_STAGING_PATH: extras/ArduinoCore-API SKETCHES_REPORTS_PATH: sketches-reports diff --git a/examples/CheckInternetAvailabilityDemo/CheckInternetAvailabilityDemo.ino b/examples/CheckInternetAvailabilityDemo/CheckInternetAvailabilityDemo.ino new file mode 100644 index 00000000..ca530ddf --- /dev/null +++ b/examples/CheckInternetAvailabilityDemo/CheckInternetAvailabilityDemo.ino @@ -0,0 +1,152 @@ +/* SECRET_ fields are in `arduino_secrets.h` (included below) + * + * If using a WiFi board (Arduino MKR1000, MKR WiFi 1010, Nano 33 IoT, UNO + * WiFi Rev 2 or ESP8266/32), create a WiFiConnectionHandler object by adding + * Network Name (SECRET_WIFI_SSID) and password (SECRET_WIFI_PASS) in the + * arduino_secrets.h file (or Secrets tab in Create Web Editor). + * + * WiFiConnectionHandler conMan(SECRET_WIFI_SSID, SECRET_WIFI_PASS); + * + * If using a MKR GSM 1400 or other GSM boards supporting the same API you'll + * need a GSMConnectionHandler object as follows + * + * GSMConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS); + * + * If using a MKR NB1500 you'll need a NBConnectionHandler object as follows + * + * NBConnectionHandler conMan(SECRET_PIN); + * + * If using a Portenta + Ethernet shield you'll need a EthernetConnectionHandler object as follows: + * + * DHCP mode + * EthernetConnectionHandler conMan; + * + * Manual configuration + * EthernetConnectionHandler conMan(SECRET_IP, SECRET_DNS, SECRET_GATEWAY, SECRET_NETMASK); + * + * Manual configuration will fallback on DHCP mode if SECRET_IP is invalid or equal to INADDR_NONE. + * + * This sketch enables the ConnectionHandler to check for internet availability (only for IP based connectivity) + * before reporting the Connected state. By default the check is disabled. + * + */ + +#include + +#include "arduino_secrets.h" + +#define CONN_TOGGLE_MS 60000 + +#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 + /* Enable the connection handler to check for internet availability. + * By default is disabled. + */ + conMan.enableCheckInternetAvailability(true); + /* 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); + + Serial.print("Network Adapter Interface: "); + switch (conMan.getInterface()) { + case NetworkAdapter::WIFI: + Serial.println("Wi-Fi"); + break; + case NetworkAdapter::ETHERNET: + Serial.println("Ethernet"); + break; + case NetworkAdapter::NB: + Serial.println("Narrowband"); + break; + case NetworkAdapter::GSM: + Serial.println("GSM"); + break; + case NetworkAdapter::LORA: + Serial.println("LoRa"); + break; + case NetworkAdapter::CATM1: + Serial.println("Category M1"); + break; + case NetworkAdapter::CELL: + Serial.println("Cellular"); + break; + default: + Serial.println("Unknown"); + break; + } +} + +void loop() { + /* Toggle the connection every `CONN_TOGGLE_MS` milliseconds */ + if ((millis() - lastConnToggleMs) > CONN_TOGGLE_MS) { + Serial.println("Toggling connection..."); + if (attemptConnect) { + conMan.connect(); + } else { + conMan.disconnect(); + } + attemptConnect = !attemptConnect; + lastConnToggleMs = millis(); + } + + /* The following code keeps on running connection workflows on our + * ConnectionHandler object, hence allowing reconnection in case of failure + * and notification of connect/disconnect event if enabled (see + * addConnectCallback/addDisconnectCallback) NOTE: any use of delay() within + * the loop or methods called from it will delay the execution of .update(), + * which might not guarantee the correct functioning of the ConnectionHandler + * object. + */ + 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/CheckInternetAvailabilityDemo/arduino_secrets.h b/examples/CheckInternetAvailabilityDemo/arduino_secrets.h new file mode 100644 index 00000000..f9906f69 --- /dev/null +++ b/examples/CheckInternetAvailabilityDemo/arduino_secrets.h @@ -0,0 +1,19 @@ +// Required for WiFiConnectionHandler +const char SECRET_WIFI_SSID[] = "NETWORK NAME"; +const char SECRET_WIFI_PASS[] = "NETWORK 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"; From 510d8e512a22d9960d19f0d07670554f238da874 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 8 May 2025 14:59:33 +0200 Subject: [PATCH 15/17] fix debug message for retrying in init state --- src/WiFiConnectionHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WiFiConnectionHandler.cpp b/src/WiFiConnectionHandler.cpp index 218e1cc1..37d3ff66 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::CONNECTING)]); + Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast(NetworkConnectionState::INIT)]); #endif return NetworkConnectionState::INIT; } From 4f3731efa31f4889095e6191d212a98a3cc21a70 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 8 May 2025 15:28:17 +0200 Subject: [PATCH 16/17] remove udp include --- src/EthernetConnectionHandler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/EthernetConnectionHandler.cpp b/src/EthernetConnectionHandler.cpp index 543f0737..6e730381 100644 --- a/src/EthernetConnectionHandler.cpp +++ b/src/EthernetConnectionHandler.cpp @@ -20,7 +20,6 @@ #ifdef BOARD_HAS_ETHERNET /* Only compile if the board has ethernet */ #include "EthernetConnectionHandler.h" -#include /****************************************************************************** CTOR/DTOR From 34a52e4f20ac1263ca3df1d6c00b9ef8d2b0f254 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 12 May 2025 08:41:56 +0200 Subject: [PATCH 17/17] Release 1.1.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 4539afee..3592a568 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Arduino_ConnectionHandler -version=1.0.2 +version=1.1.0 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) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy