Skip to content

Commit be3d131

Browse files
authored
Merge pull request #137 from fabik111/check-access-internet
Check internet availability
2 parents 0786d7a + 4f3731e commit be3d131

12 files changed

+289
-27
lines changed

.github/workflows/compile-examples.yml

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
- name: Blues Wireless Notecard
3939
SKETCH_PATHS: |
4040
- examples/ConnectionHandlerDemo
41+
- examples/CheckInternetAvailabilityDemo
4142
ARDUINOCORE_MBED_STAGING_PATH: extras/ArduinoCore-mbed
4243
ARDUINOCORE_API_STAGING_PATH: extras/ArduinoCore-API
4344
SKETCHES_REPORTS_PATH: sketches-reports
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/* SECRET_ fields are in `arduino_secrets.h` (included below)
2+
*
3+
* If using a WiFi board (Arduino MKR1000, MKR WiFi 1010, Nano 33 IoT, UNO
4+
* WiFi Rev 2 or ESP8266/32), create a WiFiConnectionHandler object by adding
5+
* Network Name (SECRET_WIFI_SSID) and password (SECRET_WIFI_PASS) in the
6+
* arduino_secrets.h file (or Secrets tab in Create Web Editor).
7+
*
8+
* WiFiConnectionHandler conMan(SECRET_WIFI_SSID, SECRET_WIFI_PASS);
9+
*
10+
* If using a MKR GSM 1400 or other GSM boards supporting the same API you'll
11+
* need a GSMConnectionHandler object as follows
12+
*
13+
* GSMConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS);
14+
*
15+
* If using a MKR NB1500 you'll need a NBConnectionHandler object as follows
16+
*
17+
* NBConnectionHandler conMan(SECRET_PIN);
18+
*
19+
* If using a Portenta + Ethernet shield you'll need a EthernetConnectionHandler object as follows:
20+
*
21+
* DHCP mode
22+
* EthernetConnectionHandler conMan;
23+
*
24+
* Manual configuration
25+
* EthernetConnectionHandler conMan(SECRET_IP, SECRET_DNS, SECRET_GATEWAY, SECRET_NETMASK);
26+
*
27+
* Manual configuration will fallback on DHCP mode if SECRET_IP is invalid or equal to INADDR_NONE.
28+
*
29+
* This sketch enables the ConnectionHandler to check for internet availability (only for IP based connectivity)
30+
* before reporting the Connected state. By default the check is disabled.
31+
*
32+
*/
33+
34+
#include <Arduino_ConnectionHandler.h>
35+
36+
#include "arduino_secrets.h"
37+
38+
#define CONN_TOGGLE_MS 60000
39+
40+
#if !(defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_LORA) || \
41+
defined(BOARD_HAS_NB) || defined(BOARD_HAS_ETHERNET) || defined(BOARD_HAS_CATM1_NBIOT))
42+
#error "Please check Arduino Connection Handler supported boards list: https://github.com/arduino-libraries/Arduino_ConnectionHandler/blob/master/README.md"
43+
#endif
44+
45+
#if defined(BOARD_HAS_ETHERNET)
46+
EthernetConnectionHandler conMan(SECRET_IP, SECRET_DNS, SECRET_GATEWAY, SECRET_NETMASK);
47+
#elif defined(BOARD_HAS_WIFI)
48+
WiFiConnectionHandler conMan(SECRET_WIFI_SSID, SECRET_WIFI_PASS);
49+
#elif defined(BOARD_HAS_GSM)
50+
GSMConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS);
51+
#elif defined(BOARD_HAS_NB)
52+
NBConnectionHandler conMan(SECRET_PIN);
53+
#elif defined(BOARD_HAS_LORA)
54+
LoRaConnectionHandler conMan(SECRET_APP_EUI, SECRET_APP_KEY);
55+
#elif defined(BOARD_HAS_CATM1_NBIOT)
56+
CatM1ConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS);
57+
#elif defined(BOARD_HAS_CELLULAR)
58+
CellularConnectionHandler conMan(SECRET_PIN, SECRET_APN, SECRET_GSM_USER, SECRET_GSM_PASS);
59+
#endif
60+
61+
bool attemptConnect = false;
62+
uint32_t lastConnToggleMs = 0;
63+
64+
void setup() {
65+
/* Initialize serial debug port and wait up to 5 seconds for port to open */
66+
Serial.begin(9600);
67+
for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime <= 5000); ) { }
68+
69+
#ifndef __AVR__
70+
/* Set the debug message level:
71+
* - DBG_ERROR: Only show error messages
72+
* - DBG_WARNING: Show warning and error messages
73+
* - DBG_INFO: Show info, warning, and error messages
74+
* - DBG_DEBUG: Show debug, info, warning, and error messages
75+
* - DBG_VERBOSE: Show all messages
76+
*/
77+
setDebugMessageLevel(DBG_INFO);
78+
#endif
79+
/* Enable the connection handler to check for internet availability.
80+
* By default is disabled.
81+
*/
82+
conMan.enableCheckInternetAvailability(true);
83+
/* Add callbacks to the ConnectionHandler object to get notified of network
84+
* connection events. */
85+
conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);
86+
conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect);
87+
conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError);
88+
89+
Serial.print("Network Adapter Interface: ");
90+
switch (conMan.getInterface()) {
91+
case NetworkAdapter::WIFI:
92+
Serial.println("Wi-Fi");
93+
break;
94+
case NetworkAdapter::ETHERNET:
95+
Serial.println("Ethernet");
96+
break;
97+
case NetworkAdapter::NB:
98+
Serial.println("Narrowband");
99+
break;
100+
case NetworkAdapter::GSM:
101+
Serial.println("GSM");
102+
break;
103+
case NetworkAdapter::LORA:
104+
Serial.println("LoRa");
105+
break;
106+
case NetworkAdapter::CATM1:
107+
Serial.println("Category M1");
108+
break;
109+
case NetworkAdapter::CELL:
110+
Serial.println("Cellular");
111+
break;
112+
default:
113+
Serial.println("Unknown");
114+
break;
115+
}
116+
}
117+
118+
void loop() {
119+
/* Toggle the connection every `CONN_TOGGLE_MS` milliseconds */
120+
if ((millis() - lastConnToggleMs) > CONN_TOGGLE_MS) {
121+
Serial.println("Toggling connection...");
122+
if (attemptConnect) {
123+
conMan.connect();
124+
} else {
125+
conMan.disconnect();
126+
}
127+
attemptConnect = !attemptConnect;
128+
lastConnToggleMs = millis();
129+
}
130+
131+
/* The following code keeps on running connection workflows on our
132+
* ConnectionHandler object, hence allowing reconnection in case of failure
133+
* and notification of connect/disconnect event if enabled (see
134+
* addConnectCallback/addDisconnectCallback) NOTE: any use of delay() within
135+
* the loop or methods called from it will delay the execution of .update(),
136+
* which might not guarantee the correct functioning of the ConnectionHandler
137+
* object.
138+
*/
139+
conMan.check();
140+
}
141+
142+
void onNetworkConnect() {
143+
Serial.println(">>>> CONNECTED to network");
144+
}
145+
146+
void onNetworkDisconnect() {
147+
Serial.println(">>>> DISCONNECTED from network");
148+
}
149+
150+
void onNetworkError() {
151+
Serial.println(">>>> ERROR");
152+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Required for WiFiConnectionHandler
2+
const char SECRET_WIFI_SSID[] = "NETWORK NAME";
3+
const char SECRET_WIFI_PASS[] = "NETWORK PASSWORD";
4+
5+
// Required for GSMConnectionHandler
6+
const char SECRET_APN[] = "MOBILE PROVIDER APN ADDRESS";
7+
const char SECRET_PIN[] = "0000"; // Required for NBConnectionHandler
8+
const char SECRET_GSM_USER[] = "GSM USERNAME";
9+
const char SECRET_GSM_PASS[] = "GSM PASSWORD";
10+
11+
// Required for LoRaConnectionHandler
12+
const char SECRET_APP_EUI[] = "APP_EUI";
13+
const char SECRET_APP_KEY[] = "APP_KEY";
14+
15+
// Required for EthernetConnectionHandler (without DHCP mode)
16+
const char SECRET_IP[] = "IP ADDRESS";
17+
const char SECRET_DNS[] = "DNS ADDRESS";
18+
const char SECRET_GATEWAY[] = "GATEWAY ADDRESS";
19+
const char SECRET_NETMASK[] = "NETWORK MASK";

src/CatM1ConnectionHandler.cpp

+27-6
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,7 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleInit()
6464
pinMode(ON_MKR2, OUTPUT);
6565
digitalWrite(ON_MKR2, HIGH);
6666
#endif
67-
return NetworkConnectionState::CONNECTING;
68-
}
6967

70-
NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting()
71-
{
7268
if(!GSM.begin(
7369
_settings.catm1.pin,
7470
_settings.catm1.apn,
@@ -80,8 +76,33 @@ NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting()
8076
Debug.print(DBG_ERROR, F("The board was not able to register to the network..."));
8177
return NetworkConnectionState::ERROR;
8278
}
83-
Debug.print(DBG_INFO, F("Connected to Network"));
84-
return NetworkConnectionState::CONNECTED;
79+
return NetworkConnectionState::CONNECTING;
80+
}
81+
82+
NetworkConnectionState CatM1ConnectionHandler::update_handleConnecting()
83+
{
84+
if (!GSM.isConnected())
85+
{
86+
return NetworkConnectionState::INIT;
87+
}
88+
89+
if(!_check_internet_availability){
90+
return NetworkConnectionState::CONNECTED;
91+
}
92+
93+
int ping_result = GSM.ping("time.arduino.cc");
94+
Debug.print(DBG_INFO, F("GSM.ping(): %d"), ping_result);
95+
if (ping_result < 0)
96+
{
97+
Debug.print(DBG_ERROR, F("Internet check failed"));
98+
Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast<unsigned int>(NetworkConnectionState::CONNECTING)]);
99+
return NetworkConnectionState::CONNECTING;
100+
}
101+
else
102+
{
103+
Debug.print(DBG_INFO, F("Connected to Internet"));
104+
return NetworkConnectionState::CONNECTED;
105+
}
85106
}
86107

87108
NetworkConnectionState CatM1ConnectionHandler::update_handleConnected()

src/CellularConnectionHandler.cpp

+19-4
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,31 @@ NetworkConnectionState CellularConnectionHandler::update_handleInit()
6262
Debug.print(DBG_ERROR, F("SIM not present or wrong PIN"));
6363
return NetworkConnectionState::ERROR;
6464
}
65-
return NetworkConnectionState::CONNECTING;
66-
}
6765

68-
NetworkConnectionState CellularConnectionHandler::update_handleConnecting()
69-
{
7066
if (!_cellular.connect(String(_settings.cell.apn), String(_settings.cell.login), String(_settings.cell.pass))) {
7167
Debug.print(DBG_ERROR, F("The board was not able to register to the network..."));
7268
return NetworkConnectionState::ERROR;
7369
}
7470
Debug.print(DBG_INFO, F("Connected to Network"));
71+
return NetworkConnectionState::CONNECTING;
72+
}
73+
74+
NetworkConnectionState CellularConnectionHandler::update_handleConnecting()
75+
{
76+
if (!_cellular.isConnectedToInternet()) {
77+
return NetworkConnectionState::INIT;
78+
}
79+
80+
if (!_check_internet_availability) {
81+
return NetworkConnectionState::CONNECTED;
82+
}
83+
84+
if(getTime() == 0){
85+
Debug.print(DBG_ERROR, F("Internet check failed"));
86+
Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast<unsigned int>(NetworkConnectionState::CONNECTING)]);
87+
return NetworkConnectionState::CONNECTING;
88+
}
89+
7590
return NetworkConnectionState::CONNECTED;
7691
}
7792

src/ConnectionHandlerDefinitions.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,12 @@ enum class NetworkAdapter {
191191

192192
static unsigned int const CHECK_INTERVAL_TABLE[] =
193193
{
194-
/* INIT */ 100,
195194
#if defined(BOARD_HAS_NOTECARD) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
196-
/* CONNECTING */ 4000,
195+
/* INIT */ 4000,
197196
#else
198-
/* CONNECTING */ 500,
197+
/* INIT */ 500,
199198
#endif
199+
/* CONNECTING */ 500,
200200
/* CONNECTED */ 10000,
201201
/* DISCONNECTING */ 100,
202202
/* DISCONNECTED */ 1000,

src/ConnectionHandlerInterface.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ConnectionHandler::ConnectionHandler(bool const keep_alive, NetworkAdapter inter
2929
: _keep_alive{keep_alive}
3030
, _interface{interface}
3131
, _lastConnectionTickTime{millis()}
32+
, _check_internet_availability{false}
3233
, _current_net_connection_state{NetworkConnectionState::INIT}
3334
{
3435

src/ConnectionHandlerInterface.h

+4
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ConnectionHandler {
7676

7777
virtual void connect();
7878
virtual void disconnect();
79+
void enableCheckInternetAvailability(bool enable) {
80+
_check_internet_availability = enable;
81+
}
7982

8083
virtual void addCallback(NetworkConnectionEvent const event, OnNetworkEventCallback callback);
8184
void addConnectCallback(OnNetworkEventCallback callback) __attribute__((deprecated));
@@ -106,6 +109,7 @@ class ConnectionHandler {
106109
virtual void updateCallback(NetworkConnectionState next_net_connection_state);
107110

108111
bool _keep_alive;
112+
bool _check_internet_availability;
109113
NetworkAdapter _interface;
110114

111115
virtual NetworkConnectionState update_handleInit () = 0;

src/EthernetConnectionHandler.cpp

+29-8
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,6 @@ NetworkConnectionState EthernetConnectionHandler::update_handleInit()
7272
Debug.print(DBG_ERROR, F("Error, ethernet shield was not found."));
7373
return NetworkConnectionState::ERROR;
7474
}
75-
return NetworkConnectionState::CONNECTING;
76-
}
77-
78-
NetworkConnectionState EthernetConnectionHandler::update_handleConnecting()
79-
{
8075
IPAddress ip(_settings.eth.ip.type, _settings.eth.ip.bytes);
8176

8277
// An ip address is provided -> static ip configuration
@@ -91,7 +86,7 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting()
9186
Debug.print(DBG_ERROR, F("Failed to configure Ethernet, check cable connection"));
9287
Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d",
9388
_settings.eth.timeout, _settings.eth.response_timeout);
94-
return NetworkConnectionState::CONNECTING;
89+
return NetworkConnectionState::INIT;
9590
}
9691
// An ip address is not provided -> dhcp configuration
9792
} else {
@@ -100,11 +95,37 @@ NetworkConnectionState EthernetConnectionHandler::update_handleConnecting()
10095
Debug.print(DBG_VERBOSE, "timeout: %d, response timeout: %d",
10196
_settings.eth.timeout, _settings.eth.response_timeout);
10297

103-
return NetworkConnectionState::CONNECTING;
98+
return NetworkConnectionState::INIT;
10499
}
105100
}
106101

107-
return NetworkConnectionState::CONNECTED;
102+
return NetworkConnectionState::CONNECTING;
103+
}
104+
105+
NetworkConnectionState EthernetConnectionHandler::update_handleConnecting()
106+
{
107+
if (Ethernet.linkStatus() == LinkOFF) {
108+
return NetworkConnectionState::INIT;
109+
}
110+
111+
if (!_check_internet_availability) {
112+
return NetworkConnectionState::CONNECTED;
113+
}
114+
115+
int ping_result = Ethernet.ping("time.arduino.cc");
116+
Debug.print(DBG_INFO, F("Ethernet.ping(): %d"), ping_result);
117+
if (ping_result < 0)
118+
{
119+
Debug.print(DBG_ERROR, F("Internet check failed"));
120+
Debug.print(DBG_INFO, F("Retrying in \"%d\" milliseconds"), CHECK_INTERVAL_TABLE[static_cast<unsigned int>(NetworkConnectionState::CONNECTING)]);
121+
return NetworkConnectionState::CONNECTING;
122+
}
123+
else
124+
{
125+
Debug.print(DBG_INFO, F("Connected to Internet"));
126+
return NetworkConnectionState::CONNECTED;
127+
}
128+
108129
}
109130

110131
NetworkConnectionState EthernetConnectionHandler::update_handleConnected()

src/GSMConnectionHandler.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ GSMConnectionHandler::GSMConnectionHandler(const char * pin, const char * apn, c
5353
: ConnectionHandler{keep_alive, NetworkAdapter::GSM}
5454
{
5555
_settings.type = NetworkAdapter::GSM;
56+
// To keep the backward compatibility, the user can call enableCheckInternetAvailability(false) for disabling the check
57+
_check_internet_availability = true;
5658
strncpy(_settings.gsm.pin, pin, sizeof(_settings.gsm.pin)-1);
5759
strncpy(_settings.gsm.apn, apn, sizeof(_settings.gsm.apn)-1);
5860
strncpy(_settings.gsm.login, login, sizeof(_settings.gsm.login)-1);
@@ -105,6 +107,10 @@ NetworkConnectionState GSMConnectionHandler::update_handleInit()
105107

106108
NetworkConnectionState GSMConnectionHandler::update_handleConnecting()
107109
{
110+
if(!_check_internet_availability){
111+
return NetworkConnectionState::CONNECTED;
112+
}
113+
108114
Debug.print(DBG_INFO, F("Sending PING to outer space..."));
109115
int const ping_result = _gprs.ping("time.arduino.cc");
110116
Debug.print(DBG_INFO, F("GPRS.ping(): %d"), ping_result);

src/GenericConnectionHandler.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bool GenericConnectionHandler::updateSetting(const models::NetworkSetting& s) {
3737
if(_ch != nullptr) {
3838
_interface = s.type;
3939
_ch->setKeepAlive(_keep_alive);
40+
_ch->enableCheckInternetAvailability(_check_internet_availability);
4041
return _ch->updateSetting(s);
4142
} else {
4243
_interface = NetworkAdapter::NONE;

0 commit comments

Comments
 (0)