Skip to content

Commit bce49c3

Browse files
committed
Add capacity to fail_fast
Add an optional fail_fast parameter to run() and mqttStatus() to allow them to return promptly if desired by the calling sketch. Detect a network failure and attempt to reconnect unless fail_fast is true.
1 parent 3950f25 commit bce49c3

File tree

3 files changed

+48
-26
lines changed

3 files changed

+48
-26
lines changed

src/AdafruitIO.cpp

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ void AdafruitIO::connect()
3939
{
4040

4141
AIO_DEBUG_PRINTLN("AdafruitIO::connect()");
42+
43+
_last_mqtt_connect = 0; // need to start over fresh
44+
_status = AIO_IDLE;
45+
_last_ping = 0;
4246

4347
if(_err_sub) {
4448
// setup error sub
@@ -165,18 +169,28 @@ const __FlashStringHelper* AdafruitIO::statusText()
165169
}
166170
}
167171

168-
aio_status_t AdafruitIO::run(uint16_t busywait_ms)
172+
aio_status_t AdafruitIO::run(uint16_t busywait_ms, bool fail_fast)
169173
{
170174
uint32_t timeStart = millis();
171-
// If we aren't network connected, return status -- fail quickly
172-
if(status() < AIO_NET_CONNECTED) {
173-
return status();
175+
if(status() < AIO_NET_CONNECTED) { // If we aren't network connected...
176+
if(fail_fast) return status(); // return status and fail quickly
177+
else{ // or try to reconnect from the start
178+
AIO_ERROR_PRINT("run() connection failed -- retrying");
179+
unsigned long started = millis();
180+
connect();
181+
// wait for a full AIO connection then carry on
182+
while(status() < AIO_CONNECTED) {
183+
// or return an error if the reconnection times out
184+
if(millis() - started > AIO_NET_CONNECTION_TIMEOUT) return status();
185+
delay(500);
186+
}
187+
}
174188
}
175189

176190
// loop until we have a connection
177191
// mqttStatus() will try to reconnect before returning
178-
while(mqttStatus() != AIO_CONNECTED && millis() - timeStart < AIO_MQTT_CONNECTION_TIMEOUT){}
179-
if(mqttStatus() != AIO_CONNECTED) return status();
192+
while(mqttStatus(fail_fast) != AIO_CONNECTED && millis() - timeStart < AIO_MQTT_CONNECTION_TIMEOUT){}
193+
if(mqttStatus(fail_fast) != AIO_CONNECTED) return status();
180194

181195
if(busywait_ms > 0)
182196
_packetread_timeout = busywait_ms;
@@ -237,7 +251,7 @@ char* AdafruitIO::userAgent()
237251
return _user_agent;
238252
}
239253

240-
aio_status_t AdafruitIO::mqttStatus()
254+
aio_status_t AdafruitIO::mqttStatus(bool fail_fast)
241255
{
242256
// if the connection failed,
243257
// return so we don't hammer IO
@@ -251,21 +265,26 @@ aio_status_t AdafruitIO::mqttStatus()
251265
if(_mqtt->connected())
252266
return AIO_CONNECTED;
253267

254-
switch(_mqtt->connect(_username, _key)) {
255-
case 0:
256-
return AIO_CONNECTED;
257-
case 1: // invalid mqtt protocol
258-
case 2: // client id rejected
259-
case 4: // malformed user/pass
260-
case 5: // unauthorized
261-
return AIO_CONNECT_FAILED;
262-
case 3: // mqtt service unavailable
263-
case 6: // throttled
264-
case 7: // banned -> all MQTT bans are temporary, so eventual retry is permitted
265-
// delay to prevent fast reconnects
266-
delay(AIO_THROTTLE_RECONNECT_INTERVAL);
267-
return AIO_DISCONNECTED;
268-
default:
269-
return AIO_DISCONNECTED;
268+
// prevent fast reconnect attempts, except for the first time through
269+
if(_last_mqtt_connect == 0 || millis() - _last_mqtt_connect > AIO_THROTTLE_RECONNECT_INTERVAL){
270+
_last_mqtt_connect = millis();
271+
switch(_mqtt->connect(_username, _key)) {
272+
case 0:
273+
return AIO_CONNECTED;
274+
case 1: // invalid mqtt protocol
275+
case 2: // client id rejected
276+
case 4: // malformed user/pass
277+
case 5: // unauthorized
278+
return AIO_CONNECT_FAILED;
279+
case 3: // mqtt service unavailable
280+
case 6: // throttled
281+
case 7: // banned -> all MQTT bans are temporary, so eventual retry is permitted
282+
// delay to prevent fast reconnects and fast returns (backward compatibility)
283+
if(!fail_fast) delay(AIO_THROTTLE_RECONNECT_INTERVAL);
284+
return AIO_DISCONNECTED;
285+
default:
286+
return AIO_DISCONNECTED;
287+
}
270288
}
289+
return AIO_DISCONNECTED;
271290
}

src/AdafruitIO.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class AdafruitIO {
4545
virtual ~AdafruitIO();
4646

4747
void connect();
48-
aio_status_t run(uint16_t busywait_ms = 0);
48+
aio_status_t run(uint16_t busywait_ms = 0, bool fail_fast = false);
4949

5050
AdafruitIO_Feed* feed(const char *name);
5151
AdafruitIO_Feed* feed(const char *name, const char *owner);
@@ -57,7 +57,7 @@ class AdafruitIO {
5757

5858
aio_status_t status();
5959
virtual aio_status_t networkStatus() = 0;
60-
aio_status_t mqttStatus();
60+
aio_status_t mqttStatus(bool fail_fast = false);
6161

6262
char* boardID();
6363
const char* boardType();
@@ -69,6 +69,7 @@ class AdafruitIO {
6969
virtual void _connect() = 0;
7070
aio_status_t _status = AIO_IDLE;
7171
uint32_t _last_ping = 0;
72+
uint32_t _last_mqtt_connect = 0;
7273

7374
Adafruit_MQTT *_mqtt;
7475
HttpClient *_http;

src/AdafruitIO_Definitions.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ class AdafruitIOGroupCallback {
7272
#define AIO_PING_INTERVAL 60000
7373
// Time to wait between re-connecting to Adafruit IO after throttled
7474
#define AIO_THROTTLE_RECONNECT_INTERVAL 60000
75-
// Time to wait for a successful reconnection of MQTT
75+
// Time to wait for a successful reconnection after MQTT disconnect
7676
#define AIO_MQTT_CONNECTION_TIMEOUT 60000
77+
// Time to wait for a successful reconnection after network disconnect
78+
#define AIO_NET_CONNECTION_TIMEOUT 60000
7779

7880
#define AIO_ERROR_TOPIC "/errors"
7981
#define AIO_THROTTLE_TOPIC "/throttle"

0 commit comments

Comments
 (0)