Skip to content

Commit d017d4a

Browse files
authored
Merge pull request #444 from arduino-libraries/new-thing-process
New thing process
2 parents 4b9aa49 + 3130afa commit d017d4a

7 files changed

+300
-99
lines changed

src/ArduinoIoTCloud.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ ArduinoIoTCloudClass::ArduinoIoTCloudClass()
2929
: _connection{nullptr}
3030
, _time_service(TimeService)
3131
, _thing_id{""}
32-
, _thing_id_property{nullptr}
3332
, _lib_version{AIOT_CONFIG_LIB_VERSION}
3433
, _device_id{""}
3534
, _cloud_event_callback{nullptr}

src/ArduinoIoTCloud.h

-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ class ArduinoIoTCloudClass
148148
ConnectionHandler * _connection;
149149
TimeServiceClass & _time_service;
150150
String _thing_id;
151-
Property * _thing_id_property;
152151
String _lib_version;
153152

154153
void execCloudEventCallback(ArduinoIoTCloudEvent const event);

src/ArduinoIoTCloudTCP.cpp

+51-84
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,10 @@ unsigned long getTime()
6060
ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
6161
: _state{State::ConnectPhy}
6262
, _connection_attempt(0,0)
63+
, _message_stream(std::bind(&ArduinoIoTCloudTCP::sendMessage, this, std::placeholders::_1))
64+
, _thing(&_message_stream)
65+
, _thing_id_property{nullptr}
6366
, _device_property_container{0}
64-
, _thing_property_container{0}
65-
, _last_checked_property_index{0}
66-
, _tz_offset{0}
67-
, _tz_offset_property{nullptr}
68-
, _tz_dst_until{0}
69-
, _tz_dst_until_property{nullptr}
7067
, _mqtt_data_buf{0}
7168
, _mqtt_data_len{0}
7269
, _mqtt_data_request_retransmit{false}
@@ -214,10 +211,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
214211
#endif /* OTA_ENABLED */
215212
p = new CloudWrapperString(_thing_id);
216213
_thing_id_property = &addPropertyToContainer(_device_property_container, *p, "thing_id", Permission::ReadWrite, -1).writeOnDemand();
217-
p = new CloudWrapperInt(_tz_offset);
218-
_tz_offset_property = &addPropertyToContainer(_thing_property_container, *p, "tz_offset", Permission::ReadWrite, -1).writeOnDemand();
219-
p = new CloudWrapperUnsignedInt(_tz_dst_until);
220-
_tz_dst_until_property = &addPropertyToContainer(_thing_property_container, *p, "tz_dst_until", Permission::ReadWrite, -1).writeOnDemand();
214+
215+
_thing.begin();
221216

222217
#if OTA_ENABLED
223218
_ota_cap = OTA::isCapable();
@@ -274,7 +269,6 @@ void ArduinoIoTCloudTCP::update()
274269
case State::SubscribeDeviceTopic: next_state = handle_SubscribeDeviceTopic(); break;
275270
case State::CheckDeviceConfig: next_state = handle_CheckDeviceConfig(); break;
276271
case State::SubscribeThingTopics: next_state = handle_SubscribeThingTopics(); break;
277-
case State::RequestLastValues: next_state = handle_RequestLastValues(); break;
278272
case State::Connected: next_state = handle_Connected(); break;
279273
case State::Disconnect: next_state = handle_Disconnect(); break;
280274
}
@@ -328,12 +322,13 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectPhy()
328322

329323
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SyncTime()
330324
{
331-
#pragma GCC diagnostic push
332-
#pragma GCC diagnostic ignored "-Wunused-variable"
333-
unsigned long const internal_posix_time = _time_service.getTime();
334-
#pragma GCC diagnostic pop
335-
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, internal_posix_time);
336-
return State::ConnectMqttBroker;
325+
if (TimeServiceClass::isTimeValid(getTime()))
326+
{
327+
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s internal clock configured to posix timestamp %d", __FUNCTION__, getTime());
328+
return State::ConnectMqttBroker;
329+
}
330+
331+
return State::ConnectPhy;
337332
}
338333

339334
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
@@ -477,38 +472,12 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_SubscribeThingTopics()
477472

478473
/* Successfully subscribed to thing topics, reconfigure timers for next state and go on */
479474
_connection_attempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms);
480-
return State::RequestLastValues;
481-
}
482-
483-
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_RequestLastValues()
484-
{
485-
if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud())
486-
{
487-
return State::Disconnect;
488-
}
489-
490-
/* Check whether or not we need to send a new request. */
491-
if (_connection_attempt.isRetry() && !_connection_attempt.isExpired())
492-
return State::RequestLastValues;
493-
494-
/* Track the number of times a get-last-values request was sent to the cloud.
495-
* If no data is received within a certain number of retry-requests it's a better
496-
* strategy to disconnect and re-establish connection from the ground up.
497-
*/
498-
if (_connection_attempt.getRetryCount() > AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT)
499-
{
500-
return State::Disconnect;
501-
}
502-
503-
_connection_attempt.retry();
504-
requestLastValue();
505-
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values requested", __FUNCTION__, _time_service.getTime());
506-
return State::RequestLastValues;
475+
return State::Connected;
507476
}
508477

509478
ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected()
510479
{
511-
if (!_mqttClient.connected())
480+
if (!_mqttClient.connected() || _thing_id_property->isDifferentFromCloud() || !_thing.connected())
512481
{
513482
/* The last message was definitely lost, trigger a retransmit. */
514483
_mqtt_data_request_retransmit = true;
@@ -517,20 +486,6 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected()
517486
/* We are connected so let's to our stuff here. */
518487
else
519488
{
520-
if (_thing_id_property->isDifferentFromCloud())
521-
{
522-
return State::Disconnect;
523-
}
524-
525-
/* Check if a primitive property wrapper is locally changed.
526-
* This function requires an existing time service which in
527-
* turn requires an established connection. Not having that
528-
* leads to a wrong time set in the time service which inhibits
529-
* the connection from being established due to a wrong data
530-
* in the reconstructed certificate.
531-
*/
532-
updateTimestampOnLocallyChangedProperties(_thing_property_container);
533-
534489
/* Retransmit data in case there was a lost transaction due
535490
* to phy layer or MQTT connectivity loss.
536491
*/
@@ -539,27 +494,11 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Connected()
539494
_mqtt_data_request_retransmit = false;
540495
}
541496

542-
/* Configure Time service with timezone data:
543-
* _tz_offset [offset + dst]
544-
* _tz_dst_until [posix timestamp until _tz_offset is valid]
545-
*/
546-
if (_tz_offset_property->isDifferentFromCloud() || _tz_dst_until_property->isDifferentFromCloud()) {
547-
_tz_offset_property->fromCloudToLocal();
548-
_tz_dst_until_property->fromCloudToLocal();
549-
_time_service.setTimeZoneData(_tz_offset, _tz_dst_until);
550-
}
497+
/* Call CloudThing process to synchronize properties */
498+
_thing.update();
551499

552-
/* Check if any properties need encoding and send them to
553-
* the cloud if necessary.
554-
*/
555-
sendThingPropertiesToCloud();
500+
return State::Connected;
556501

557-
unsigned long const internal_posix_time = _time_service.getTime();
558-
if (internal_posix_time < _tz_dst_until) {
559-
return State::Connected;
560-
} else {
561-
return State::RequestLastValues;
562-
}
563502
}
564503
}
565504

@@ -604,9 +543,15 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_Disconnect()
604543
/* TODO add device topic */
605544
_mqttClient.stop();
606545
}
546+
547+
Message message = { ResetCmdId };
548+
_thing.handleMessage(&message);
549+
607550
DEBUG_INFO("Disconnected from Arduino IoT Cloud");
608551
execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT);
609552

553+
updateThingTopics();
554+
610555
/* Setup timer for broker connection and restart */
611556
_connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms);
612557
return State::ConnectPhy;
@@ -630,25 +575,47 @@ void ArduinoIoTCloudTCP::handleMessage(int length)
630575
/* Topic for OTA properties and device configuration */
631576
if (_deviceTopicIn == topic) {
632577
CBORDecoder::decode(_device_property_container, (uint8_t*)bytes, length);
633-
_state = State::CheckDeviceConfig;
578+
if (_thing_id_property->isDifferentFromCloud() && (_thing_id.length() != 0)) {
579+
_state = State::Disconnect;
580+
} else {
581+
_state = State::CheckDeviceConfig;
582+
}
634583
}
635584

636585
/* Topic for user input data */
637586
if (_dataTopicIn == topic) {
638-
CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length);
587+
CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length);
639588
}
640589

641590
/* Topic for sync Thing last values on connect */
642-
if ((_shadowTopicIn == topic) && (_state == State::RequestLastValues))
591+
if (_shadowTopicIn == topic)
643592
{
644593
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] last values received", __FUNCTION__, millis());
645-
CBORDecoder::decode(_thing_property_container, (uint8_t*)bytes, length, true);
646-
_time_service.setTimeZoneData(_tz_offset, _tz_dst_until);
594+
CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length, true);
595+
Message message = { LastValuesUpdateCmdId };
596+
_thing.handleMessage(&message);
647597
execCloudEventCallback(ArduinoIoTCloudEvent::SYNC);
648598
_state = State::Connected;
649599
}
650600
}
651601

602+
void ArduinoIoTCloudTCP::sendMessage(Message * msg)
603+
{
604+
switch (msg->id)
605+
{
606+
case PropertiesUpdateCmdId:
607+
sendThingPropertiesToCloud();
608+
break;
609+
610+
case LastValuesBeginCmdId:
611+
requestLastValue();
612+
break;
613+
614+
default:
615+
break;
616+
}
617+
}
618+
652619
void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index)
653620
{
654621
int bytes_encoded = 0;
@@ -669,7 +636,7 @@ void ArduinoIoTCloudTCP::sendPropertyContainerToCloud(String const topic, Proper
669636

670637
void ArduinoIoTCloudTCP::sendThingPropertiesToCloud()
671638
{
672-
sendPropertyContainerToCloud(_dataTopicOut, _thing_property_container, _last_checked_property_index);
639+
sendPropertyContainerToCloud(_dataTopicOut, _thing.getPropertyContainer(), _thing.getPropertyContainerIndex());
673640
}
674641

675642
void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud()

src/ArduinoIoTCloudTCP.h

+6-12
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include <AIoTC_Config.h>
2626
#include <ArduinoIoTCloud.h>
2727
#include <ArduinoMqttClient.h>
28-
#include <utility/time/TimedAttempt.h>
28+
#include <ArduinoIoTCloudThing.h>
2929

3030
#if defined(BOARD_HAS_SECURE_ELEMENT)
3131
#include <Arduino_SecureElement.h>
@@ -75,7 +75,6 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
7575
ArduinoIoTCloudTCP();
7676
virtual ~ArduinoIoTCloudTCP() { }
7777

78-
7978
virtual void update () override;
8079
virtual int connected () override;
8180
virtual void printDebugInfo() override;
@@ -91,7 +90,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
9190
inline String getBrokerAddress() const { return _brokerAddress; }
9291
inline uint16_t getBrokerPort () const { return _brokerPort; }
9392

94-
inline PropertyContainer &getThingPropertyContainer() { return _thing_property_container; }
93+
inline PropertyContainer &getThingPropertyContainer() { return _thing.getPropertyContainer(); }
9594

9695
#if OTA_ENABLED
9796
/* The callback is triggered when the OTA is initiated and it gets executed until _ota_req flag is cleared.
@@ -118,21 +117,16 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
118117
SubscribeDeviceTopic,
119118
CheckDeviceConfig,
120119
SubscribeThingTopics,
121-
RequestLastValues,
122120
Connected,
123121
Disconnect,
124122
};
125123

126124
State _state;
127125
TimedAttempt _connection_attempt;
126+
MessageStream _message_stream;
127+
ArduinoCloudThing _thing;
128+
Property * _thing_id_property;
128129
PropertyContainer _device_property_container;
129-
PropertyContainer _thing_property_container;
130-
unsigned int _last_checked_property_index;
131-
132-
int _tz_offset;
133-
Property * _tz_offset_property;
134-
unsigned int _tz_dst_until;
135-
Property * _tz_dst_until_property;
136130

137131
String _brokerAddress;
138132
uint16_t _brokerPort;
@@ -200,12 +194,12 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
200194
State handle_CheckDeviceConfig();
201195
State handle_SubscribeDeviceTopic();
202196
State handle_SubscribeThingTopics();
203-
State handle_RequestLastValues();
204197
State handle_Connected();
205198
State handle_Disconnect();
206199

207200
static void onMessage(int length);
208201
void handleMessage(int length);
202+
void sendMessage(Message * msg);
209203
void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index);
210204
void sendThingPropertiesToCloud();
211205
void sendDevicePropertiesToCloud();

0 commit comments

Comments
 (0)