diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index fec3efa64..825c7f36b 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -43,7 +43,7 @@ #endif #ifndef DBG_VERBOSE - #define DBG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) + #define DBG_VERBOSE(fmt, ...) //Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__) #endif /****************************************************************************** diff --git a/src/ArduinoIoTCloud.cpp b/src/ArduinoIoTCloud.cpp index 693fdc42f..cf7557e5a 100644 --- a/src/ArduinoIoTCloud.cpp +++ b/src/ArduinoIoTCloud.cpp @@ -172,21 +172,6 @@ Property& ArduinoIoTCloudClass::addPropertyReal(String& property, String name, i * PROTECTED MEMBER FUNCTIONS ******************************************************************************/ -NetworkConnectionState ArduinoIoTCloudClass::checkPhyConnection() -{ - NetworkConnectionState const connect_state = _connection->check(); - - if (_connection->check() != NetworkConnectionState::CONNECTED) - { - if (_iot_status == ArduinoIoTConnectionStatus::CONNECTED) - { - disconnect(); - } - } - - return connect_state; -} - void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const event) { OnCloudEventCallback callback = _cloud_event_callback[static_cast(event)]; @@ -194,16 +179,3 @@ void ArduinoIoTCloudClass::execCloudEventCallback(ArduinoIoTCloudEvent const eve (*callback)(); } } - -void ArduinoIoTCloudClass::printConnectionStatus(ArduinoIoTConnectionStatus status) -{ - switch (status) - { - case ArduinoIoTConnectionStatus::IDLE: DBG_INFO ("Arduino IoT Cloud Connection status: IDLE"); break; - case ArduinoIoTConnectionStatus::ERROR: DBG_ERROR("Arduino IoT Cloud Connection status: ERROR"); break; - case ArduinoIoTConnectionStatus::CONNECTING: DBG_INFO ("Arduino IoT Cloud Connection status: CONNECTING"); break; - case ArduinoIoTConnectionStatus::RECONNECTING: DBG_INFO ("Arduino IoT Cloud Connection status: RECONNECTING"); break; - case ArduinoIoTConnectionStatus::CONNECTED: DBG_INFO ("Arduino IoT Cloud Connection status: CONNECTED"); break; - case ArduinoIoTConnectionStatus::DISCONNECTED: DBG_ERROR("Arduino IoT Cloud Connection status: DISCONNECTED"); break; - } -} diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index d60f5feac..1be41e9e8 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -38,6 +38,8 @@ #include "property/types/CloudWrapperInt.h" #include "property/types/CloudWrapperString.h" +#include "utility/time/TimeService.h" + /****************************************************************************** TYPEDEF ******************************************************************************/ @@ -59,13 +61,6 @@ enum class ArduinoIoTConnectionStatus ERROR, }; -enum class ArduinoIoTSynchronizationStatus -{ - SYNC_STATUS_SYNCHRONIZED, - SYNC_STATUS_WAIT_FOR_CLOUD_VALUES, - SYNC_STATUS_VALUES_PROCESSED -}; - enum class ArduinoIoTCloudEvent : size_t { SYNC = 0, CONNECT = 1, DISCONNECT = 2 @@ -98,6 +93,8 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } + inline unsigned long getInternalTime() { return _time_service.getTime(); } + void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); #define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__) @@ -138,18 +135,11 @@ class ArduinoIoTCloudClass protected: - virtual int connect () = 0; - virtual void disconnect() = 0; - - inline ArduinoIoTConnectionStatus getIoTStatus() { return _iot_status; } - ConnectionHandler * _connection = nullptr; PropertyContainer _property_container; - ArduinoIoTConnectionStatus _iot_status = ArduinoIoTConnectionStatus::IDLE; + TimeService _time_service; - NetworkConnectionState checkPhyConnection(); - void execCloudEventCallback(ArduinoIoTCloudEvent const event); - static void printConnectionStatus(ArduinoIoTConnectionStatus status); + void execCloudEventCallback(ArduinoIoTCloudEvent const event); private: diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 4ab17b87a..4a30d2424 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -33,12 +33,22 @@ static size_t const CBOR_LORA_MSG_MAX_SIZE = 255; +/****************************************************************************** + LOCAL MODULE FUNCTIONS + ******************************************************************************/ + +extern "C" unsigned long getTime() +{ + return ArduinoCloud.getInternalTime(); +} + /****************************************************************************** CTOR/DTOR ******************************************************************************/ ArduinoIoTCloudLPWAN::ArduinoIoTCloudLPWAN() -: _retryEnable{false} +: _state{State::ConnectPhy} +, _retryEnable{false} , _maxNumRetry{5} , _intervalRetry{1000} { @@ -58,45 +68,21 @@ int ArduinoIoTCloudLPWAN::begin(ConnectionHandler& connection, bool retry) { _connection = &connection; _retryEnable = retry; + _time_service.begin(nullptr); return 1; } void ArduinoIoTCloudLPWAN::update() { - // Check if a primitive property wrapper is locally changed - updateTimestampOnLocallyChangedProperties(_property_container); - - ArduinoIoTConnectionStatus next_iot_status = _iot_status; - - /* Since we do not have a direct connection to the Arduino IoT Cloud servers - * there is no such thing is a 'cloud connection state' since the LoRa - * board connection state to the gateway is all the information we have. - */ - NetworkConnectionState const net_con_state = checkPhyConnection(); - if (net_con_state == NetworkConnectionState::CONNECTED) { next_iot_status = ArduinoIoTConnectionStatus::CONNECTED; execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); } - else if(net_con_state == NetworkConnectionState::CONNECTING) { next_iot_status = ArduinoIoTConnectionStatus::CONNECTING; } - else if(net_con_state == NetworkConnectionState::DISCONNECTED) { next_iot_status = ArduinoIoTConnectionStatus::DISCONNECTED; execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); } - - if(next_iot_status != _iot_status) + /* Run through the state machine. */ + State next_state = _state; + switch (_state) { - printConnectionStatus(next_iot_status); - _iot_status = next_iot_status; - } - - if(net_con_state != NetworkConnectionState::CONNECTED) return; - - if (_connection->available()) { - uint8_t msgBuf[CBOR_LORA_MSG_MAX_SIZE]; - uint8_t i = 0; - while (_connection->available()) { - msgBuf[i++] = _connection->read(); - } - - CBORDecoder::decode(_property_container, msgBuf, sizeof(msgBuf)); + case State::ConnectPhy: next_state = handle_ConnectPhy(); break; + case State::SyncTime: next_state = handle_SyncTime(); break; + case State::Connected: next_state = handle_Connected(); break; } - - sendPropertiesToCloud(); - execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); + _state = next_state; } void ArduinoIoTCloudLPWAN::printDebugInfo() @@ -106,23 +92,58 @@ void ArduinoIoTCloudLPWAN::printDebugInfo() } /****************************************************************************** - * PROTECTED MEMBER FUNCTIONS + * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ -int ArduinoIoTCloudLPWAN::connect() +ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_ConnectPhy() { - _connection->connect(); - return 1; + if (_connection->check() == NetworkConnectionState::CONNECTED) + return State::SyncTime; + else + return State::ConnectPhy; } -void ArduinoIoTCloudLPWAN::disconnect() +ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { - _connection->disconnect(); + unsigned long const internal_posix_time = _time_service.getTime(); + DBG_VERBOSE("ArduinoIoTCloudLPWAN::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); + DBG_INFO("Connected to Arduino IoT Cloud"); + return State::Connected; } -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ +ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_Connected() +{ + if (!connected()) + { + DBG_ERROR("ArduinoIoTCloudLPWAN::%s connection to gateway lost", __FUNCTION__); + return State::ConnectPhy; + } + + /* Check if a primitive property wrapper is locally changed. */ + updateTimestampOnLocallyChangedProperties(_property_container); + + /* Decode available data. */ + if (_connection->available()) + decodePropertiesFromCloud(); + + /* If properties need updating sent them to the cloud. */ + sendPropertiesToCloud(); + + return State::Connected; +} + +void ArduinoIoTCloudLPWAN::decodePropertiesFromCloud() +{ + uint8_t lora_msg_buf[CBOR_LORA_MSG_MAX_SIZE]; + size_t bytes_received; + for (bytes_received = 0; + _connection->available() && (bytes_received < CBOR_LORA_MSG_MAX_SIZE); + bytes_received++) + { + lora_msg_buf[bytes_received] = _connection->read(); + } + CBORDecoder::decode(_property_container, lora_msg_buf, bytes_received); +} void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() { @@ -138,7 +159,8 @@ int ArduinoIoTCloudLPWAN::writeProperties(const byte data[], int length) { int retcode = _connection->write(data, length); int i = 0; - while (_retryEnable && retcode < 0 && i < _maxNumRetry) { + while (_retryEnable && retcode < 0 && i < _maxNumRetry) + { delay(_intervalRetry); retcode = _connection->write(data, length); i++; diff --git a/src/ArduinoIoTCloudLPWAN.h b/src/ArduinoIoTCloudLPWAN.h index 2abe4ba01..8d1f42d28 100644 --- a/src/ArduinoIoTCloudLPWAN.h +++ b/src/ArduinoIoTCloudLPWAN.h @@ -50,18 +50,25 @@ class ArduinoIoTCloudLPWAN : public ArduinoIoTCloudClass inline void setIntervalRetry(long val) { _intervalRetry = val; } - protected: - - virtual int connect () override; - virtual void disconnect () override; - - private: + enum class State + { + ConnectPhy, + SyncTime, + Connected, + }; + + State _state; bool _retryEnable; int _maxNumRetry; long _intervalRetry; + State handle_ConnectPhy(); + State handle_SyncTime(); + State handle_Connected(); + + void decodePropertiesFromCloud(); void sendPropertiesToCloud(); int writeProperties(const byte data[], int length); }; diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f195c41ca..76d8e4fcc 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -23,7 +23,6 @@ #ifdef HAS_TCP #include -#include "utility/time/TimeService.h" #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" #include "tls/utility/CryptoUtil.h" @@ -40,8 +39,6 @@ GLOBAL VARIABLES ******************************************************************************/ -TimeService time_service; - #if OTA_STORAGE_SSU static OTAStorage_SSU ota_storage_ssu; #elif OTA_STORAGE_SFU @@ -56,17 +53,13 @@ TimeService time_service; static const int TIMEOUT_FOR_LASTVALUES_SYNC = 10000; -const static int CONNECT_SUCCESS = 1; -const static int CONNECT_FAILURE = 0; -const static int CONNECT_FAILURE_SUBSCRIBE = -1; - /****************************************************************************** LOCAL MODULE FUNCTIONS ******************************************************************************/ extern "C" unsigned long getTime() { - return time_service.getTime(); + return ArduinoCloud.getInternalTime(); } /****************************************************************************** @@ -74,7 +67,8 @@ extern "C" unsigned long getTime() ******************************************************************************/ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() -: _lastSyncRequestTickTime{0} +: _state{State::ConnectPhy} +, _lastSyncRequestTickTime{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -85,7 +79,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _password("") #endif , _mqttClient{nullptr} -, _syncStatus{ArduinoIoTSynchronizationStatus::SYNC_STATUS_SYNCHRONIZED} , _stdinTopic("") , _stdoutTopic("") , _shadowTopicOut("") @@ -110,13 +103,12 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, String brokerAddre _connection = &connection; _brokerAddress = brokerAddress; _brokerPort = brokerPort; - time_service.begin(&connection); + _time_service.begin(&connection); return begin(_brokerAddress, _brokerPort); } int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) { - _brokerAddress = brokerAddress; _brokerPort = brokerPort; @@ -161,8 +153,6 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _dataTopicIn = getTopic_datain(); _ota_topic_in = getTopic_ota_in(); - printConnectionStatus(_iot_status); - #if OTA_STORAGE_SSU setOTAStorage(ota_storage_ssu); #elif OTA_STORAGE_SFU @@ -176,56 +166,22 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) void ArduinoIoTCloudTCP::update() { -#if OTA_ENABLED - /* If a _ota_logic object has been instantiated then we are spinning its - * 'update' method here in order to process incoming data and generally - * to transition to the OTA logic update states. - */ - OTAError const err = _ota_logic.update(); - _ota_error = static_cast(err); -#endif /* OTA_ENABLED */ - - if(checkPhyConnection() != NetworkConnectionState::CONNECTED) return; - if(checkCloudConnection() != ArduinoIoTConnectionStatus::CONNECTED) return; - - /* Check if a primitive property wrapper is locally changed. - * This function requires an existing time service which in - * turn requires an established connection. Not having that - * leads to a wrong time set in the time service which inhibits - * the connection from being established due to a wrong data - * in the reconstructed certificate. - */ - updateTimestampOnLocallyChangedProperties(_property_container); - - if(_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { - write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); - _mqtt_data_request_retransmit = false; - } + /* Retrieve the latest data from the MQTT Client. */ + if (_mqttClient.connected()) + _mqttClient.poll(); - // MTTQClient connected!, poll() used to retrieve data from MQTT broker - _mqttClient.poll(); - - switch (_syncStatus) + /* Run through the state machine. */ + State next_state = _state; + switch (_state) { - case ArduinoIoTSynchronizationStatus::SYNC_STATUS_SYNCHRONIZED: sendPropertiesToCloud(); break; - - case ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES: - { - if (millis() - _lastSyncRequestTickTime > TIMEOUT_FOR_LASTVALUES_SYNC) - { - requestLastValue(); - _lastSyncRequestTickTime = millis(); - } - } - break; - - case ArduinoIoTSynchronizationStatus::SYNC_STATUS_VALUES_PROCESSED: - { - execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); - _syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_SYNCHRONIZED; - } - break; + case State::ConnectPhy: next_state = handle_ConnectPhy(); break; + case State::SyncTime: next_state = handle_SyncTime(); break; + case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; + case State::SubscribeMqttTopics: next_state = handle_SubscribeMqttTopics(); break; + case State::RequestLastValues: next_state = handle_RequestLastValues(); break; + case State::Connected: next_state = handle_Connected(); break; } + _state = next_state; } int ArduinoIoTCloudTCP::connected() @@ -250,43 +206,137 @@ void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) } #endif /* OTA_ENABLED */ -int ArduinoIoTCloudTCP::reconnect() +/****************************************************************************** + * PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() { - if (_mqttClient.connected()) { - _mqttClient.stop(); - } - return connect(); + if (_connection->check() == NetworkConnectionState::CONNECTED) + return State::SyncTime; + else + return State::ConnectPhy; } -/****************************************************************************** - * PROTECTED MEMBER FUNCTIONS - ******************************************************************************/ +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() +{ + unsigned long const internal_posix_time = _time_service.getTime(); + DBG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time); + return State::ConnectMqttBroker; +} -int ArduinoIoTCloudTCP::connect() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { - if (!_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) return CONNECT_FAILURE; - if (_mqttClient.subscribe(_stdinTopic) == 0) return CONNECT_FAILURE_SUBSCRIBE; - if (_mqttClient.subscribe(_dataTopicIn) == 0) return CONNECT_FAILURE_SUBSCRIBE; - if (_mqttClient.subscribe(_ota_topic_in) == 0) return CONNECT_FAILURE_SUBSCRIBE; + if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) + return State::SubscribeMqttTopics; + + DBG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort); + return State::ConnectMqttBroker; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() +{ + if (!_mqttClient.subscribe(_stdinTopic)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _stdinTopic.c_str()); + return State::SubscribeMqttTopics; + } + + if (!_mqttClient.subscribe(_dataTopicIn)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _dataTopicIn.c_str()); + return State::SubscribeMqttTopics; + } + + if (!_mqttClient.subscribe(_ota_topic_in)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); + return State::SubscribeMqttTopics; + } if (_shadowTopicIn != "") { - if (_mqttClient.subscribe(_shadowTopicIn) == 0) return CONNECT_FAILURE_SUBSCRIBE; - _syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES; - _lastSyncRequestTickTime = 0; + if (!_mqttClient.subscribe(_shadowTopicIn)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); + return State::SubscribeMqttTopics; + } } - return CONNECT_SUCCESS; + DBG_INFO("Connected to Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + + if (_shadowTopicIn != "") + return State::RequestLastValues; + else + return State::Connected; } -void ArduinoIoTCloudTCP::disconnect() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { - _mqttClient.stop(); + /* Check whether or not we need to send a new request. */ + unsigned long const now = millis(); + if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) + { + DBG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, now); + requestLastValue(); + _lastSyncRequestTickTime = now; + } + + return State::RequestLastValues; } -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() +{ + if (!_mqttClient.connected()) + { + /* The last message was definitely lost, trigger a retransmit. */ + _mqtt_data_request_retransmit = true; + + /* We are not connected anymore, trigger the callback for a disconnected event. */ + execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); + + /* Forcefully disconnect MQTT client and trigger a reconnection. */ + _mqttClient.stop(); + return State::ConnectMqttBroker; + } + /* We are connected so let's to our stuff here. */ + else + { +#if OTA_ENABLED + /* If a _ota_logic object has been instantiated then we are spinning its + * 'update' method here in order to process incoming data and generally + * to transition to the OTA logic update states. + */ + OTAError const err = _ota_logic.update(); + _ota_error = static_cast(err); +#endif /* OTA_ENABLED */ + + /* Check if a primitive property wrapper is locally changed. + * This function requires an existing time service which in + * turn requires an established connection. Not having that + * leads to a wrong time set in the time service which inhibits + * the connection from being established due to a wrong data + * in the reconstructed certificate. + */ + updateTimestampOnLocallyChangedProperties(_property_container); + + /* Retransmit data in case there was a lost transaction due + * to phy layer or MQTT connectivity loss. + */ + if(_mqtt_data_request_retransmit && (_mqtt_data_len > 0)) { + write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); + _mqtt_data_request_retransmit = false; + } + + /* Check if any properties need encoding and send them to + * the cloud if necessary. + */ + sendPropertiesToCloud(); + + return State::Connected; + } +} void ArduinoIoTCloudTCP::onMessage(int length) { @@ -306,11 +356,16 @@ void ArduinoIoTCloudTCP::handleMessage(int length) if (_dataTopicIn == topic) { CBORDecoder::decode(_property_container, (uint8_t*)bytes, length); } - if ((_shadowTopicIn == topic) && _syncStatus == ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES) { + + if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues)) + { + DBG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis()); CBORDecoder::decode(_property_container, (uint8_t*)bytes, length, true); sendPropertiesToCloud(); - _syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_VALUES_PROCESSED; + execCloudEventCallback(ArduinoIoTCloudEvent::SYNC); + _state = State::Connected; } + #if OTA_ENABLED if (_ota_topic_in == topic) { _ota_logic.onOTADataReceived(bytes, length); @@ -345,62 +400,6 @@ void ArduinoIoTCloudTCP::requestLastValue() write(_shadowTopicOut, CBOR_REQUEST_LAST_VALUE_MSG, sizeof(CBOR_REQUEST_LAST_VALUE_MSG)); } -ArduinoIoTConnectionStatus ArduinoIoTCloudTCP::checkCloudConnection() -{ - ArduinoIoTConnectionStatus next_iot_status = _iot_status; - - switch (_iot_status) - { - case ArduinoIoTConnectionStatus::IDLE: next_iot_status = ArduinoIoTConnectionStatus::CONNECTING; break; - case ArduinoIoTConnectionStatus::ERROR: next_iot_status = ArduinoIoTConnectionStatus::RECONNECTING; break; - case ArduinoIoTConnectionStatus::DISCONNECTED: next_iot_status = ArduinoIoTConnectionStatus::RECONNECTING; break; - case ArduinoIoTConnectionStatus::CONNECTING: - { - DBG_INFO("Arduino IoT Cloud connecting ..."); - int const ret = connect(); - if (ret == CONNECT_SUCCESS) - { - next_iot_status = ArduinoIoTConnectionStatus::CONNECTED; - } - else if (ret == CONNECT_FAILURE_SUBSCRIBE) - { - DBG_ERROR("ERROR - Please verify your THING ID"); - } - } - break; - - case ArduinoIoTConnectionStatus::RECONNECTING: - { - DBG_INFO("Arduino IoT Cloud reconnecting ..."); - if (reconnect() == CONNECT_SUCCESS) - { - next_iot_status = ArduinoIoTConnectionStatus::CONNECTED; - } - } - break; - - case ArduinoIoTConnectionStatus::CONNECTED: - { - if (!_mqttClient.connected()) - { - next_iot_status = ArduinoIoTConnectionStatus::DISCONNECTED; - _mqtt_data_request_retransmit = true; - } - } - break; - } - - if(next_iot_status != _iot_status) - { - printConnectionStatus(next_iot_status); - if (next_iot_status == ArduinoIoTConnectionStatus::DISCONNECTED) execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT); - else if(next_iot_status == ArduinoIoTConnectionStatus::CONNECTED) execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - _iot_status = next_iot_status; - } - - return _iot_status; -} - int ArduinoIoTCloudTCP::write(String const topic, byte const data[], int const length) { if (_mqttClient.beginMessage(topic, length, false, 0)) { diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 2006ee7de..2e9200725 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -84,18 +84,22 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass void setOTAStorage(OTAStorage & ota_storage); #endif /* OTA_ENABLED */ - // Clean up existing Mqtt connection, create a new one and initialize it - int reconnect(); - - protected: - - virtual int connect () override; - virtual void disconnect () override; - private: static const int MQTT_TRANSMIT_BUFFER_SIZE = 256; + enum class State + { + ConnectPhy, + SyncTime, + ConnectMqttBroker, + SubscribeMqttTopics, + RequestLastValues, + Connected, + }; + + State _state; + int _lastSyncRequestTickTime; String _brokerAddress; uint16_t _brokerPort; @@ -113,8 +117,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass MqttClient _mqttClient; - ArduinoIoTSynchronizationStatus _syncStatus; - // Class attribute to define MTTQ topics 2 for stdIn/out and 2 for data, in order to avoid getting previous pupblished payload String _stdinTopic; String _stdoutTopic; @@ -138,11 +140,17 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("/a/d/" + getDeviceId() + "/e/i") : String("/a/t/" + getThingId() + "/e/i"); } inline String getTopic_ota_in () { return String("/a/d/" + getDeviceId() + "/ota/i"); } + State handle_ConnectPhy(); + State handle_SyncTime(); + State handle_ConnectMqttBroker(); + State handle_SubscribeMqttTopics(); + State handle_RequestLastValues(); + State handle_Connected(); + static void onMessage(int length); void handleMessage(int length); void sendPropertiesToCloud(); void requestLastValue(); - ArduinoIoTConnectionStatus checkCloudConnection(); int write(String const topic, byte const data[], int const length); }; diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index f18ff8019..f54028c49 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -50,11 +50,7 @@ DECLARATION OF getTime ******************************************************************************/ -#ifdef HAS_LORA -static unsigned long constexpr getTime() { return 0; } -#else extern "C" unsigned long getTime(); -#endif /****************************************************************************** TYPEDEF diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp index 6c3173774..9f908a8c8 100644 --- a/src/utility/ota/FlashSHA256.cpp +++ b/src/utility/ota/FlashSHA256.cpp @@ -73,7 +73,6 @@ String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_siz if (chunk[valid_bytes_in_chunk-1] != 0xFF) break; } - DBG_VERBOSE("FlashSHA256::calc: end of firmware, %d valid bytes in last read chunk", valid_bytes_in_chunk); /* Update with the remaining bytes. */ sha256.update(chunk, valid_bytes_in_chunk); break; diff --git a/src/utility/time/TimeService.cpp b/src/utility/time/TimeService.cpp index bec1bd2d2..b5e35dcd7 100644 --- a/src/utility/time/TimeService.cpp +++ b/src/utility/time/TimeService.cpp @@ -19,9 +19,6 @@ * INCLUDE **************************************************************************************/ -#include "../../AIoTC_Config.h" -#ifndef HAS_LORA - #include "TimeService.h" #include @@ -93,6 +90,9 @@ unsigned long TimeService::getTime() unsigned long TimeService::getRemoteTime() { +#include "../../AIoTC_Config.h" +#ifndef HAS_LORA + if(_con_hdl == nullptr) return EPOCH_AT_COMPILE_TIME; @@ -113,6 +113,8 @@ unsigned long TimeService::getRemoteTime() return ntp_time; } +#endif /* ifndef HAS_LORA */ + /* Return the epoch timestamp at compile time as a last * line of defense. Otherwise the certificate expiration * date is wrong and we'll be unable to establish a connection @@ -159,5 +161,3 @@ time_t cvt_time(char const * time) return mktime(&t); } - -#endif /* #ifndef HAS_LORA */ diff --git a/src/utility/time/TimeService.h b/src/utility/time/TimeService.h index 183438ae7..b6a4bb43a 100644 --- a/src/utility/time/TimeService.h +++ b/src/utility/time/TimeService.h @@ -22,9 +22,6 @@ * INCLUDE **************************************************************************************/ -#include "../../AIoTC_Config.h" -#ifndef HAS_LORA - #include #ifdef ARDUINO_ARCH_SAMD @@ -58,6 +55,4 @@ class TimeService }; -#endif /* #ifndef HAS_LORA */ - #endif /* ARDUINO_IOT_CLOUD_TIME_SERVICE_H_ */