Skip to content

Commit c212b86

Browse files
authored
Merge pull request #900 from adafruit/tyeth/issue899
fix(ping): Avoid Device Connection Flipping, KeepAlive Fixup
2 parents 6cd8f5f + d96961e commit c212b86

File tree

2 files changed

+36
-18
lines changed

2 files changed

+36
-18
lines changed

src/Wippersnapper.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,27 +1735,40 @@ void cbThrottleTopic(char *throttleData, uint16_t len) {
17351735
(void)len; // marking unused parameter to avoid compiler warning
17361736
WS_DEBUG_PRINT("IO Throttle Error: ");
17371737
WS_DEBUG_PRINTLNVAR(throttleData);
1738-
char *throttleMessage;
1739-
// Parse out # of seconds from message buffer
1740-
throttleMessage = strtok(throttleData, ",");
1741-
throttleMessage = strtok(NULL, " ");
1742-
// Convert from seconds to to millis
1743-
int throttleDuration = atoi(throttleMessage) * 1000;
1744-
1738+
uint32_t throttleDuration = 60000UL; // duration of throttle in ms
1739+
bool parsingSuccessful = false;
1740+
if (throttleData != NULL) {
1741+
char *throttleMessage;
1742+
// Parse out # of seconds from message buffer
1743+
throttleMessage = strtok(throttleData, ",");
1744+
if (throttleMessage != NULL) {
1745+
throttleMessage = strtok(NULL, " ");
1746+
if (throttleMessage != NULL) {
1747+
// Convert from seconds to to millis
1748+
throttleDuration = (uint32_t)atoi(throttleMessage) * 1000UL;
1749+
parsingSuccessful = true;
1750+
}
1751+
}
1752+
}
1753+
if (!parsingSuccessful) {
1754+
WS_DEBUG_PRINTLN("ERROR: Unable to parse throttle duration from message, "
1755+
"please report this! Defaulting to 60s.");
1756+
}
17451757
WS_DEBUG_PRINT("Device is throttled for ");
17461758
WS_DEBUG_PRINTVAR(throttleDuration);
17471759
WS_DEBUG_PRINTLN("ms and blocking command execution.");
17481760

17491761
// If throttle duration is less than the keepalive interval, delay for the
17501762
// full keepalive interval
1751-
if (throttleDuration < WS_KEEPALIVE_INTERVAL_MS) {
1752-
delay(WS_KEEPALIVE_INTERVAL_MS);
1763+
if (throttleDuration < WS_DEVICE_PING_MS) {
1764+
delay(WS_DEVICE_PING_MS);
17531765
} else {
1754-
// round to nearest millis to prevent delaying for less time than req'd.
1755-
float throttleLoops = ceil(throttleDuration / WS_KEEPALIVE_INTERVAL_MS);
1766+
// Round up so throttling never ends earlier than requested.
1767+
uint32_t throttleLoops =
1768+
(throttleDuration + WS_DEVICE_PING_MS - 1) / WS_DEVICE_PING_MS;
17561769
// block the run() loop
17571770
while (throttleLoops > 0) {
1758-
delay(WS_KEEPALIVE_INTERVAL_MS);
1771+
delay(WS_DEVICE_PING_MS);
17591772
WS.feedWDT();
17601773
WS._mqtt->ping();
17611774
throttleLoops--;
@@ -2474,7 +2487,7 @@ void Wippersnapper::runNetFSM() {
24742487
fsmNetwork = FSM_NET_CHECK_NETWORK;
24752488
break;
24762489
case FSM_NET_ESTABLISH_MQTT:
2477-
WS._mqtt->setKeepAliveInterval(WS_KEEPALIVE_INTERVAL_MS / 1000);
2490+
WS._mqtt->setKeepAliveInterval(_brokerKeepAliveIntervalSeconds);
24782491
// Attempt to connect
24792492
maxAttempts = 5;
24802493
while (maxAttempts > 0) {
@@ -2599,9 +2612,8 @@ ws_board_status_t Wippersnapper::getBoardStatus() { return WS._boardStatus; }
25992612
*/
26002613
/**************************************************************************/
26012614
void Wippersnapper::pingBroker() {
2602-
// ping within keepalive-10% to keep connection open
2603-
if (millis() > (_prv_ping + (WS_KEEPALIVE_INTERVAL_MS -
2604-
(WS_KEEPALIVE_INTERVAL_MS * 0.10)))) {
2615+
// if it's past time to send the next ping
2616+
if (millis() > (_prv_ping + WS_DEVICE_PING_MS)) {
26052617
WS_DEBUG_PRINT("Sending MQTT PING: ");
26062618
if (WS._mqtt->ping()) {
26072619
WS_DEBUG_PRINTLN("SUCCESS!");
@@ -2795,6 +2807,8 @@ void Wippersnapper::connect() {
27952807
// Dump device info to the serial monitor
27962808
printDeviceInfo();
27972809

2810+
_brokerKeepAliveIntervalSeconds = WS_BROKER_KEEPALIVE_MS / 1000;
2811+
27982812
// Generate device identifier
27992813
if (!generateDeviceUID()) {
28002814
haltError("Unable to generate Device UID");

src/Wippersnapper.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,10 @@ typedef enum {
248248

249249
#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks
250250
/* MQTT Configuration */
251-
#define WS_KEEPALIVE_INTERVAL_MS \
252-
5000 ///< Session keepalive interval time, in milliseconds
251+
#define WS_BROKER_KEEPALIVE_MS \
252+
11000 ///< Maximum time without a ping before broker disconnects (ms)
253+
#define WS_DEVICE_PING_MS \
254+
5000 ///< Interval at which device sends ping to broker, in milliseconds
253255

254256
#define WS_MQTT_MAX_PAYLOAD_SIZE \
255257
512 ///< MAXIMUM expected payload size, in bytes
@@ -476,6 +478,8 @@ class Wippersnapper {
476478
ws_status_t _status = WS_IDLE; /*!< Adafruit IO connection status */
477479
uint32_t _last_mqtt_connect = 0; /*!< Previous time when client connected to
478480
Adafruit IO, in milliseconds. */
481+
uint16_t _brokerKeepAliveIntervalSeconds =
482+
0; /*!< Cached MQTT broker keepalive interval, in seconds. */
479483
uint32_t _prv_ping = 0; /*!< Previous time when client pinged Adafruit IO's
480484
MQTT broker, in milliseconds. */
481485
uint32_t _prvKATBlink = 0; /*!< Previous time when client pinged Adafruit IO's

0 commit comments

Comments
 (0)