From f15b7d776b828cabec9a19d7ac4ddeb4c0b73e41 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 07:58:28 +0200 Subject: [PATCH 01/15] Replace checkCloudConnection and associated functions with an easier to read state machine --- src/ArduinoIoTCloudTCP.cpp | 141 ++++++++++++++++--------------------- src/ArduinoIoTCloudTCP.h | 18 ++++- 2 files changed, 77 insertions(+), 82 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f195c41ca..0330a81ef 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -74,7 +74,8 @@ extern "C" unsigned long getTime() ******************************************************************************/ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() -: _lastSyncRequestTickTime{0} +: _state{State::ConnectMqttBroker} +, _lastSyncRequestTickTime{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} , _mqtt_data_request_retransmit{false} @@ -186,7 +187,18 @@ void ArduinoIoTCloudTCP::update() #endif /* OTA_ENABLED */ if(checkPhyConnection() != NetworkConnectionState::CONNECTED) return; - if(checkCloudConnection() != ArduinoIoTConnectionStatus::CONNECTED) return; + + State next_state = _state; + switch (_state) + { + case State::ConnectMqttBroker: next_state = handle_ConnectMqttBroker(); break; + case State::SubscribeMqttTopics: next_state = handle_SubscribeMqttTopics(); break; + case State::Connected: next_state = handle_Connected(); break; + } + _state = next_state; + + /* For now exit here if we are not connected. */ + if (_state != State::Connected) return; /* Check if a primitive property wrapper is locally changed. * This function requires an existing time service which in @@ -250,44 +262,71 @@ void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) } #endif /* OTA_ENABLED */ -int ArduinoIoTCloudTCP::reconnect() -{ - if (_mqttClient.connected()) { - _mqttClient.stop(); - } - return connect(); -} - /****************************************************************************** - * PROTECTED MEMBER FUNCTIONS + * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ -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; + if (!_mqttClient.subscribe(_shadowTopicIn)) + { + DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); + return State::SubscribeMqttTopics; + } _syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES; _lastSyncRequestTickTime = 0; } - return CONNECT_SUCCESS; + DBG_VERBOSE("Connected to Arduino IoT Cloud"); + execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); + return State::Connected; } -void ArduinoIoTCloudTCP::disconnect() +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { + if (_mqttClient.connected()) + return State::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; } -/****************************************************************************** - * PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - void ArduinoIoTCloudTCP::onMessage(int length) { ArduinoCloud.handleMessage(length); @@ -345,62 +384,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..33f85f3ef 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -89,13 +89,22 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass protected: - virtual int connect () override; - virtual void disconnect () override; + virtual int connect () override { } + virtual void disconnect () override { } private: static const int MQTT_TRANSMIT_BUFFER_SIZE = 256; + enum class State + { + ConnectMqttBroker, + SubscribeMqttTopics, + Connected, + }; + + State _state; + int _lastSyncRequestTickTime; String _brokerAddress; uint16_t _brokerPort; @@ -138,11 +147,14 @@ 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_ConnectMqttBroker(); + State handle_SubscribeMqttTopics(); + 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); }; From 04d8fa62c5f2e4c2bd2ca35585fdf73fa0ac371a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 08:23:27 +0200 Subject: [PATCH 02/15] Simplifying synchronisation logic by making it a distinctive step in the connect procedure --- src/ArduinoIoTCloud.h | 7 ----- src/ArduinoIoTCloudTCP.cpp | 59 +++++++++++++++++++------------------- src/ArduinoIoTCloudTCP.h | 4 +-- 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index d60f5feac..2ad108afd 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -59,13 +59,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 diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0330a81ef..f2dbf69a5 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -86,7 +86,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _password("") #endif , _mqttClient{nullptr} -, _syncStatus{ArduinoIoTSynchronizationStatus::SYNC_STATUS_SYNCHRONIZED} , _stdinTopic("") , _stdoutTopic("") , _shadowTopicOut("") @@ -188,11 +187,17 @@ void ArduinoIoTCloudTCP::update() if(checkPhyConnection() != NetworkConnectionState::CONNECTED) return; + /* Retrieve the latest data from the MQTT Client. */ + if (_mqttClient.connected()) + _mqttClient.poll(); + + /* Run through the state machine. */ State next_state = _state; switch (_state) { 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; @@ -214,30 +219,7 @@ void ArduinoIoTCloudTCP::update() _mqtt_data_request_retransmit = false; } - // MTTQClient connected!, poll() used to retrieve data from MQTT broker - _mqttClient.poll(); - - switch (_syncStatus) - { - 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; - } + sendPropertiesToCloud(); } int ArduinoIoTCloudTCP::connected() @@ -302,13 +284,25 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() DBG_ERROR("ArduinoIoTCloudTCP::%s could not subscribe to %s", __FUNCTION__, _ota_topic_in.c_str()); return State::SubscribeMqttTopics; } - _syncStatus = ArduinoIoTSynchronizationStatus::SYNC_STATUS_WAIT_FOR_CLOUD_VALUES; - _lastSyncRequestTickTime = 0; } DBG_VERBOSE("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - return State::Connected; + return State::RequestLastValues; +} + +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() +{ + /* Check wether 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; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() @@ -345,11 +339,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); diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 33f85f3ef..da64ff442 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -100,6 +100,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass { ConnectMqttBroker, SubscribeMqttTopics, + RequestLastValues, Connected, }; @@ -122,8 +123,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; @@ -149,6 +148,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass State handle_ConnectMqttBroker(); State handle_SubscribeMqttTopics(); + State handle_RequestLastValues(); State handle_Connected(); static void onMessage(int length); From 500f416e291a035465dac3e7735ca67c92dd81fc Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 08:33:56 +0200 Subject: [PATCH 03/15] Moving all code that's handled in State::Connected into handle_Connected func. --- src/ArduinoIoTCloudTCP.cpp | 82 +++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index f2dbf69a5..a01a6822e 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -176,15 +176,6 @@ 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; /* Retrieve the latest data from the MQTT Client. */ @@ -201,25 +192,6 @@ void ArduinoIoTCloudTCP::update() case State::Connected: next_state = handle_Connected(); break; } _state = next_state; - - /* For now exit here if we are not connected. */ - if (_state != State::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; - } - - sendPropertiesToCloud(); } int ArduinoIoTCloudTCP::connected() @@ -307,18 +279,54 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected() { - if (_mqttClient.connected()) - return State::Connected; + if (!_mqttClient.connected()) + { + /* The last message was definitely lost, trigger a retransmit. */ + _mqtt_data_request_retransmit = true; - /* 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); - /* 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 */ - /* Forcefully disconnect MQTT client and trigger a reconnection. */ - _mqttClient.stop(); - return State::ConnectMqttBroker; + /* 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) From 5ca9a2fce3e79be16b3ccab4c8237f8207627f55 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 08:38:43 +0200 Subject: [PATCH 04/15] Add a state ConnectPhy where we are waiting for the connection to the phy layer to be established --- src/ArduinoIoTCloudTCP.cpp | 14 ++++++++++---- src/ArduinoIoTCloudTCP.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a01a6822e..93a2cd69b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -74,7 +74,7 @@ extern "C" unsigned long getTime() ******************************************************************************/ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() -: _state{State::ConnectMqttBroker} +: _state{State::ConnectPhy} , _lastSyncRequestTickTime{0} , _mqtt_data_buf{0} , _mqtt_data_len{0} @@ -116,7 +116,6 @@ int ArduinoIoTCloudTCP::begin(ConnectionHandler & connection, String brokerAddre int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) { - _brokerAddress = brokerAddress; _brokerPort = brokerPort; @@ -176,8 +175,6 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) void ArduinoIoTCloudTCP::update() { - if(checkPhyConnection() != NetworkConnectionState::CONNECTED) return; - /* Retrieve the latest data from the MQTT Client. */ if (_mqttClient.connected()) _mqttClient.poll(); @@ -186,6 +183,7 @@ void ArduinoIoTCloudTCP::update() State next_state = _state; switch (_state) { + case State::ConnectPhy: next_state = handle_ConnectPhy(); 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; @@ -220,6 +218,14 @@ void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) * PRIVATE MEMBER FUNCTIONS ******************************************************************************/ +ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() +{ + if (_connection->check() == NetworkConnectionState::CONNECTED) + return State::ConnectMqttBroker; + else + return State::ConnectPhy; +} + ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index da64ff442..8e4a16e4a 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -98,6 +98,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass enum class State { + ConnectPhy, ConnectMqttBroker, SubscribeMqttTopics, RequestLastValues, @@ -146,6 +147,7 @@ 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_ConnectMqttBroker(); State handle_SubscribeMqttTopics(); State handle_RequestLastValues(); From 6e9aaf061384c39f8b2c9a39381d6817355519c7 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 08:40:10 +0200 Subject: [PATCH 05/15] Deleting constants/func calls no longer needed --- src/ArduinoIoTCloudTCP.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 93a2cd69b..484cc137c 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -56,10 +56,6 @@ 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 ******************************************************************************/ @@ -160,8 +156,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 From 3bcb5e01e2019b25550085e869c8d9f24d56b8d5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 08:50:41 +0200 Subject: [PATCH 06/15] Adding explicit SyncTime step to make the necessity of synchronising the time more visible --- src/ArduinoIoTCloudTCP.cpp | 10 +++++++++- src/ArduinoIoTCloudTCP.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 484cc137c..fc569ad8b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -178,6 +178,7 @@ void ArduinoIoTCloudTCP::update() switch (_state) { 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; @@ -215,11 +216,18 @@ void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() { if (_connection->check() == NetworkConnectionState::CONNECTED) - return State::ConnectMqttBroker; + return State::SyncTime; else return State::ConnectPhy; } +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; +} + ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() { if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort)) diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 8e4a16e4a..fc1efd55f 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -99,6 +99,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass enum class State { ConnectPhy, + SyncTime, ConnectMqttBroker, SubscribeMqttTopics, RequestLastValues, @@ -148,6 +149,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass 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(); From 136f0bf0c1c309e429023cffc6bc645fd3cd5a3d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 09:00:32 +0200 Subject: [PATCH 07/15] Fixing spelling mistake --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index fc569ad8b..093929a41 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -273,7 +273,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() { - /* Check wether or not we need to send a new request. */ + /* Check whether or not we need to send a new request. */ unsigned long const now = millis(); if ((now - _lastSyncRequestTickTime) > TIMEOUT_FOR_LASTVALUES_SYNC) { From 6da1e21ff504fca99a247b4e5f4267c0d3f67fb1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 09:03:36 +0200 Subject: [PATCH 08/15] Deleting superfluos debug output --- src/utility/ota/FlashSHA256.cpp | 1 - 1 file changed, 1 deletion(-) 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; From bf01c01ee47c9881529fd9ea7de579aa7fd97041 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 09:08:59 +0200 Subject: [PATCH 09/15] Bugfix - directly transition to connected state if we don't need to perform any synchronisation due to no thing id being set --- src/ArduinoIoTCloudTCP.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 093929a41..83f20b0ba 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -268,7 +268,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() DBG_VERBOSE("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); - return State::RequestLastValues; + + if (_shadowTopicIn != "") + return State::RequestLastValues; + else + return State::Connected; } ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues() From 41700b1014c1ec87c5b5fb9975b714239d480586 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 09:16:49 +0200 Subject: [PATCH 10/15] Disable verbose debug output for production sketches (save RAM and flash) --- src/AIoTC_Config.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 83f20b0ba..b161fd53b 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -266,7 +266,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeMqttTopics() } } - DBG_VERBOSE("Connected to Arduino IoT Cloud"); + DBG_INFO("Connected to Arduino IoT Cloud"); execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT); if (_shadowTopicIn != "") From b33b5f96f970ebe4601de30974442e0e7220a7f1 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 11:09:31 +0200 Subject: [PATCH 11/15] Allow compilation of TimeService for LORA boards, just leave out the part that requires a UDP connection. Consequently the RTC will always be set to the EPOCH at compile time --- src/utility/time/TimeService.cpp | 10 +++++----- src/utility/time/TimeService.h | 5 ----- 2 files changed, 5 insertions(+), 10 deletions(-) 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_ */ From 91217597a7fc97b123d4a15d8402abf064bbabb7 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 11:12:47 +0200 Subject: [PATCH 12/15] Rewrite LORAWAN Arduino Cloud driver for better clarity --- src/ArduinoIoTCloud.cpp | 28 ---------- src/ArduinoIoTCloud.h | 15 ++--- src/ArduinoIoTCloudLPWAN.cpp | 104 +++++++++++++++++++++-------------- src/ArduinoIoTCloudLPWAN.h | 19 +++++-- 4 files changed, 81 insertions(+), 85 deletions(-) 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 2ad108afd..b569b73d5 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 ******************************************************************************/ @@ -91,6 +93,8 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } + inline unsigned long getTime() { return _time_service.getTime(); } + void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); #define addProperty( v, ...) addPropertyReal(v, #v, __VA_ARGS__) @@ -131,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..7f0532c5a 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.getTime(); +} + /****************************************************************************** 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,57 @@ 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); + 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() { 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); }; From 3e64a276da984e3e028709a3cb1ed6932c602e2d Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 11:18:04 +0200 Subject: [PATCH 13/15] Since TimeService is now a member variable available via ArduinoIoTCloud base class adjust the usage within ArduinoIoTCloudTCP --- src/ArduinoIoTCloud.h | 2 +- src/ArduinoIoTCloudTCP.cpp | 9 +++------ src/ArduinoIoTCloudTCP.h | 8 -------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/ArduinoIoTCloud.h b/src/ArduinoIoTCloud.h index b569b73d5..1be41e9e8 100644 --- a/src/ArduinoIoTCloud.h +++ b/src/ArduinoIoTCloud.h @@ -93,7 +93,7 @@ class ArduinoIoTCloudClass inline ConnectionHandler * getConnection() { return _connection; } - inline unsigned long getTime() { return _time_service.getTime(); } + inline unsigned long getInternalTime() { return _time_service.getTime(); } void addCallback(ArduinoIoTCloudEvent const event, OnCloudEventCallback callback); diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index b161fd53b..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 @@ -62,7 +59,7 @@ static const int TIMEOUT_FOR_LASTVALUES_SYNC = 10000; extern "C" unsigned long getTime() { - return time_service.getTime(); + return ArduinoCloud.getInternalTime(); } /****************************************************************************** @@ -106,7 +103,7 @@ 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); } @@ -223,7 +220,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy() ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime() { - unsigned long const internal_posix_time = time_service.getTime(); + 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; } diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index fc1efd55f..2e9200725 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -84,14 +84,6 @@ 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; From 7c213f648d5ff462e833c7a7f56d6b3edc737d4c Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 11:18:26 +0200 Subject: [PATCH 14/15] Lorawan also has a valid timekeeper now --- src/property/PropertyContainer.h | 4 ---- 1 file changed, 4 deletions(-) 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 From b673b59bbc4948a0fc2c4c764e6dfa54da8ef253 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Thu, 23 Jul 2020 11:18:53 +0200 Subject: [PATCH 15/15] Adding debug output to show when connected to gateway/cloud --- src/ArduinoIoTCloudLPWAN.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index 7f0532c5a..4a30d2424 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -39,7 +39,7 @@ static size_t const CBOR_LORA_MSG_MAX_SIZE = 255; extern "C" unsigned long getTime() { - return ArduinoCloud.getTime(); + return ArduinoCloud.getInternalTime(); } /****************************************************************************** @@ -107,6 +107,7 @@ ArduinoIoTCloudLPWAN::State ArduinoIoTCloudLPWAN::handle_SyncTime() { 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; } @@ -158,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++;