From 5c8c8bb4310c3c9d9509f6fc92976d49ee5d26d8 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 4 Jun 2024 16:01:19 +0200 Subject: [PATCH 01/10] defining interface settings in a struct --- src/settings/settings.h | 128 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/settings/settings.h diff --git a/src/settings/settings.h b/src/settings/settings.h new file mode 100644 index 0000000..b47960c --- /dev/null +++ b/src/settings/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 28afd48ae133f5815eb49bbf741da8a2cfb23ec0 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 5 Jun 2024 14:34:40 +0200 Subject: [PATCH 02/10] 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 228827e..0b1d7a4 100644 --- a/src/ConnectionHandlerInterface.h +++ b/src/ConnectionHandlerInterface.h @@ -29,6 +29,7 @@ #include #include #include "ConnectionHandlerDefinitions.h" +#include "settings/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 c1acaff6e4fb6d9bb820fc13bd19d2b26c823f77 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 15:15:24 +0100 Subject: [PATCH 03/10] 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 0b1d7a4..5398805 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 f2d3194f5f143e0724c378fe09f77a9b166e33b7 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 3 Apr 2025 17:07:04 +0200 Subject: [PATCH 04/10] 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 2fdc10e..1f62bde 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 5398805..7b9b4e0 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 8007e6d208dc2131780fb56ca1c18c6311822658 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 10:44:46 +0100 Subject: [PATCH 05/10] 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 0263a39..b739bea 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 33ac9fe..67f317b 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 2e4499a..d0877d3 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 2addd29..fcc02c6 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 14f7aee..af5b118 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 35a02cd..8ddbbe4 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 34bf179..75f9e53 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 1f3db49..891fb98 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 1f454a5..bc753fd 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 3ddcca2..cecf830 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 eb72f3e..02d62ba 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 fd2afb6..6641bb6 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 0cd2e12..efc30fa 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 2ee674a..1d360b7 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 a7deaa13a65999b4dfeacf01e57a24b0fe0c217b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 5 Dec 2024 10:33:51 +0100 Subject: [PATCH 06/10] 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 7b9b4e0..44cd499 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 0000000..f1f9eb6 --- /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 0000000..e1b315e --- /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 75ac444a051e5c9c2bb55881bb4000d90a495426 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 24 Sep 2024 12:33:13 +0200 Subject: [PATCH 07/10] 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 4f29559..9297dc0 100644 --- a/src/ConnectionHandlerDefinitions.h +++ b/src/ConnectionHandlerDefinitions.h @@ -174,6 +174,7 @@ enum class NetworkConnectionEvent { }; enum class NetworkAdapter { + NONE, WIFI, ETHERNET, NB, From 1b704bbe0eeef8831ce17821c652a909bb58c8fa Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 26 Sep 2024 11:27:36 +0200 Subject: [PATCH 08/10] 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 8ddbbe4..738b6a8 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 4b9301c0975ea8a3809d49050698ef0b1182ac14 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 25 Sep 2024 12:22:28 +0200 Subject: [PATCH 09/10] 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 0000000..2ce18f7 --- /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 0000000..cecefa4 --- /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 f34627dda938841c4655361ceda65f6e81fd14b7 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 22 Jan 2025 13:22:57 +0100 Subject: [PATCH 10/10] adding a function to get the dafault initialization values for NetworkSetting --- src/settings/settings.h | 2 + src/settings/settings_default.h | 72 +++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/settings/settings_default.h diff --git a/src/settings/settings.h b/src/settings/settings.h index b47960c..40319d6 100644 --- a/src/settings/settings.h +++ b/src/settings/settings.h @@ -126,3 +126,5 @@ namespace models { }; }; } + +#include "settings_default.h" diff --git a/src/settings/settings_default.h b/src/settings/settings_default.h new file mode 100644 index 0000000..dc9a4ef --- /dev/null +++ b/src/settings/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; + } +}