diff --git a/src/ArduinoIoTCloudNotecard.cpp b/src/ArduinoIoTCloudNotecard.cpp index 452e1dec..3dfc701e 100644 --- a/src/ArduinoIoTCloudNotecard.cpp +++ b/src/ArduinoIoTCloudNotecard.cpp @@ -42,9 +42,11 @@ * CONSTANTS ******************************************************************************/ +static size_t const BACKOFF_BASE_MS = 60000; // 1 minute +static uint32_t const BACKOFF_MAX_MS = 3600000; // 1 hour static size_t const CBOR_NOTE_MSG_MAX_SIZE = 255; -static size_t const DEFAULT_READ_INTERVAL_MS = 1000; -static size_t const FAILSAFE_READ_INTERVAL_MS = 10000; +static size_t const DEFAULT_READ_INTERVAL_MS = 1000; // 1 second +static size_t const FAILSAFE_READ_INTERVAL_MS = 10000; // 10 seconds /****************************************************************************** * LOCAL MODULE FUNCTIONS @@ -71,6 +73,8 @@ ArduinoIoTCloudNotecard::ArduinoIoTCloudNotecard() ,_message_stream(std::bind(&ArduinoIoTCloudNotecard::sendMessage, this, std::placeholders::_1)) ,_thing(&_message_stream) ,_device(&_message_stream) + ,_backoff_multiplier{1} + ,_last_failed_attach_request_ms{0} ,_notecard_last_read_ms{static_cast(-DEFAULT_READ_INTERVAL_MS)} ,_notecard_read_interval_ms{DEFAULT_READ_INTERVAL_MS} ,_interrupt_pin{-1} @@ -231,6 +235,18 @@ ArduinoIoTCloudNotecard::State ArduinoIoTCloudNotecard::handle_Connected() /* Poll Notecard for new messages */ pollNotecard(); + /* Respect backoff */ + if (_last_failed_attach_request_ms) { + const uint32_t backoff_ms = (BACKOFF_BASE_MS * _backoff_multiplier); + if ((::millis() - _last_failed_attach_request_ms) < backoff_ms) { + return State::Connected; + } else { + DEBUG_DEBUG("ArduinoIoTCloudNotecard::%s backoff expired.", __FUNCTION__); + _backoff_multiplier <<= (BACKOFF_MAX_MS > backoff_ms); + _last_failed_attach_request_ms = 0; + } + } + /* Call CloudDevice process to get configuration */ _device.update(); @@ -397,16 +413,26 @@ void ArduinoIoTCloudNotecard::processCommand(const uint8_t *buf, size_t len) String new_thing_id = String(command.thingUpdateCmd.params.thing_id); if (!new_thing_id.length()) { - /* Send message to device state machine to inform we have received a null thing-id */ + _last_failed_attach_request_ms = ::millis(); + DEBUG_DEBUG("ArduinoIoTCloudNotecard::%s received null Thing ID (current backoff %u minutes).", __FUNCTION__, _backoff_multiplier); _thing_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + + /* Send message to device state machine to inform we have received a null thing-id */ Message message; message = { DeviceRegisteredCmdId }; _device.handleMessage(&message); } else { + DEBUG_VERBOSE("ArduinoIoTCloudNotecard::%s Reseting backoff variables", __FUNCTION__); + /* Reset backoff variables */ + _backoff_multiplier = 1; + _last_failed_attach_request_ms = 0; + if (_device.isAttached() && _thing_id != new_thing_id) { + DEBUG_DEBUG("ArduinoIoTCloudNotecard::%s detaching Thing ID: %s", __FUNCTION__, _thing_id.c_str()); detachThing(); } if (!_device.isAttached()) { + DEBUG_DEBUG("ArduinoIoTCloudNotecard::%s attaching Thing ID: %s", __FUNCTION__, new_thing_id.c_str()); attachThing(new_thing_id); } } @@ -441,10 +467,11 @@ void ArduinoIoTCloudNotecard::processCommand(const uint8_t *buf, size_t len) execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); /* - * NOTE: in this current version properties are not properly integrated with the new paradigm of - * modeling the messages with C structs. The current CBOR library allocates an array in the heap - * thus we need to delete it after decoding it with the old CBORDecoder - */ + * NOTE: In this current version properties are not properly integrated + * with the new paradigm of modeling the messages with C structs. The + * current CBOR library allocates an array in the heap thus we need to + * delete it after decoding it with the old CBORDecoder + */ free(command.lastValuesUpdateCmd.params.last_values); } break; diff --git a/src/ArduinoIoTCloudNotecard.h b/src/ArduinoIoTCloudNotecard.h index becdcf1c..c3ffd47b 100644 --- a/src/ArduinoIoTCloudNotecard.h +++ b/src/ArduinoIoTCloudNotecard.h @@ -86,6 +86,8 @@ class ArduinoIoTCloudNotecard : public ArduinoIoTCloudClass ArduinoCloudDevice _device; // Notecard member variables + uint32_t _backoff_multiplier; + uint32_t _last_failed_attach_request_ms; uint32_t _notecard_last_read_ms; uint32_t _notecard_read_interval_ms; int _interrupt_pin;