43
43
#include < algorithm>
44
44
#include " cbor/CBOREncoder.h"
45
45
#include " utility/watchdog/Watchdog.h"
46
+ #include < typeinfo>
46
47
47
48
/* *****************************************************************************
48
49
LOCAL MODULE FUNCTIONS
@@ -76,8 +77,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
76
77
, _mqttClient{nullptr }
77
78
, _deviceTopicOut(" " )
78
79
, _deviceTopicIn(" " )
79
- , _shadowTopicOut(" " )
80
- , _shadowTopicIn(" " )
81
80
, _dataTopicOut(" " )
82
81
, _dataTopicIn(" " )
83
82
#if OTA_ENABLED
@@ -181,24 +180,22 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
181
180
_mqttClient.setUsernamePassword (getDeviceId (), _password);
182
181
}
183
182
#endif
183
+
184
184
_mqttClient.onMessage (ArduinoIoTCloudTCP::onMessage);
185
185
_mqttClient.setKeepAliveInterval (30 * 1000 );
186
186
_mqttClient.setConnectionTimeout (1500 );
187
187
_mqttClient.setId (getDeviceId ().c_str ());
188
188
189
189
_deviceTopicOut = getTopic_deviceout ();
190
190
_deviceTopicIn = getTopic_devicein ();
191
-
192
- Property* p;
193
- p = new CloudWrapperString (_lib_version);
194
- addPropertyToContainer (_device.getPropertyContainer (), *p, " LIB_VERSION" , Permission::Read, -1 );
195
- p = new CloudWrapperString (_thing_id);
196
- _thing_id_property = &addPropertyToContainer (_device.getPropertyContainer (), *p, " thing_id" , Permission::ReadWrite, -1 ).writeOnDemand ();
191
+ _messageTopicIn = getTopic_messagein ();
192
+ _messageTopicOut = getTopic_messageout ();
197
193
198
194
_thing.begin ();
199
195
_device.begin ();
200
196
201
197
#if OTA_ENABLED
198
+ Property* p;
202
199
p = new CloudWrapperBool (_ota_cap);
203
200
addPropertyToContainer (_device.getPropertyContainer (), *p, " OTA_CAP" , Permission::Read, -1 );
204
201
p = new CloudWrapperInt (_ota_error);
@@ -322,6 +319,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
322
319
{
323
320
if (_mqttClient.connect (_brokerAddress.c_str (), _brokerPort))
324
321
{
322
+ _mqttClient.subscribe (_messageTopicIn);
325
323
DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s connected to %s:%d" , __FUNCTION__, _brokerAddress.c_str (), _brokerPort);
326
324
/* Reconfigure timers for next state */
327
325
_connection_attempt.begin (AIOT_CONFIG_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms, AIOT_CONFIG_MAX_DEVICE_TOPIC_SUBSCRIBE_RETRY_DELAY_ms);
@@ -468,41 +466,61 @@ void ArduinoIoTCloudTCP::handleMessage(int length)
468
466
CBORDecoder::decode (_thing.getPropertyContainer (), (uint8_t *)bytes, length);
469
467
}
470
468
471
- /* Topic for sync Thing last values on connect */
472
- if (_shadowTopicIn == topic) {
473
- DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s [%d] last values received" , __FUNCTION__, millis ());
474
- /* Decode last values property array */
475
- CBORDecoder::decode (_thing.getPropertyContainer (), (uint8_t *)bytes, length, true );
476
- /* Unlock thing state machine waiting last values */
477
- Message message = { LastValuesUpdateCmdId };
478
- _thing.handleMessage (&message);
479
- /* Call ArduinoIoTCloud sync user callback*/
480
- execCloudEventCallback (ArduinoIoTCloudEvent::SYNC);
469
+ /* Topic for device commands */
470
+ if (_messageTopicIn == topic) {
471
+ CommandDown command;
472
+ DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s [%d] received %d bytes" , __FUNCTION__, millis (), length);
473
+ CBORMessageDecoder decoder;
474
+
475
+ size_t buffer_length = length;
476
+ if (decoder.decode ((Message*)&command, bytes, buffer_length) != Decoder::Status::Error) {
477
+ DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s [%d] received command id %d" , __FUNCTION__, millis (), command.c .id );
478
+ switch (command.c .id )
479
+ {
480
+ case CommandId::ThingUpdateCmdId:
481
+ {
482
+ _thing_id = String (command.thingBeginCmd .params .thing_id );
483
+ DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s [%d] device configuration received" , __FUNCTION__, millis ());
484
+ _device.handleMessage ((Message*)&command);
485
+ }
486
+ break ;
487
+
488
+ case CommandId::LastValuesUpdateCmdId:
489
+ {
490
+ DEBUG_VERBOSE (" ArduinoIoTCloudTCP::%s [%d] last values received" , __FUNCTION__, millis ());
491
+ CBORDecoder::decode (_thing.getPropertyContainer (),
492
+ (uint8_t *)command.lastValuesUpdateCmd .params .last_values ,
493
+ command.lastValuesUpdateCmd .params .length , true );
494
+ _thing.handleMessage ((Message*)&command);
495
+ execCloudEventCallback (ArduinoIoTCloudEvent::SYNC);
496
+
497
+ /*
498
+ * NOTE: in this current version properties are not properly integrated with the new paradigm of
499
+ * modeling the messages with C structs. The current CBOR library allocates an array in the heap
500
+ * thus we need to delete it after decoding it with the old CBORDecoder
501
+ */
502
+ free (command.lastValuesUpdateCmd .params .last_values );
503
+ }
504
+ break ;
505
+
506
+ default :
507
+ break ;
508
+ }
509
+ }
481
510
}
482
511
}
483
512
484
513
void ArduinoIoTCloudTCP::sendMessage (Message * msg)
485
514
{
486
- switch (msg->id )
487
- {
488
- case DeviceBeginCmdId:
489
- sendDevicePropertiesToCloud ();
490
- break ;
491
-
492
- case ThingBeginCmdId:
493
- requestThingId ();
494
- break ;
495
-
496
- case LastValuesBeginCmdId:
497
- requestLastValue ();
498
- break ;
499
-
500
- case PropertiesUpdateCmdId:
501
- sendThingPropertiesToCloud ();
502
- break ;
515
+ uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE];
516
+ size_t bytes_encoded = sizeof (data);
517
+ CBORMessageEncoder encoder;
503
518
504
- default :
505
- break ;
519
+ if (encoder.encode (msg, data, bytes_encoded) == Encoder::Status::Complete &&
520
+ bytes_encoded > 0 ) {
521
+ write (_messageTopicOut, data, bytes_encoded);
522
+ } else {
523
+ DEBUG_ERROR (" error encoding %d" , msg->id );
506
524
}
507
525
}
508
526
@@ -531,24 +549,6 @@ void ArduinoIoTCloudTCP::sendThingPropertiesToCloud()
531
549
sendPropertyContainerToCloud (_dataTopicOut, _thing.getPropertyContainer (), _thing.getPropertyContainerIndex ());
532
550
}
533
551
534
- void ArduinoIoTCloudTCP::sendDevicePropertiesToCloud ()
535
- {
536
- PropertyContainer ro_device_property_container;
537
- unsigned int last_device_property_index = 0 ;
538
-
539
- std::list<String> ro_device_property_list {" LIB_VERSION" , " OTA_CAP" , " OTA_ERROR" , " OTA_SHA256" };
540
- std::for_each (ro_device_property_list.begin (),
541
- ro_device_property_list.end (),
542
- [this , &ro_device_property_container ] (String const & name)
543
- {
544
- Property* p = getProperty (this ->_device .getPropertyContainer (), name);
545
- if (p != nullptr )
546
- addPropertyToContainer (ro_device_property_container, *p, p->name (), p->isWriteableByCloud () ? Permission::ReadWrite : Permission::Read);
547
- }
548
- );
549
- sendPropertyContainerToCloud (_deviceTopicOut, ro_device_property_container, last_device_property_index);
550
- }
551
-
552
552
#if OTA_ENABLED
553
553
void ArduinoIoTCloudTCP::sendDevicePropertyToCloud (String const name)
554
554
{
@@ -564,26 +564,6 @@ void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name)
564
564
}
565
565
#endif
566
566
567
- void ArduinoIoTCloudTCP::requestLastValue ()
568
- {
569
- // Send the getLastValues CBOR message to the cloud
570
- // [{0: "r:m", 3: "getLastValues"}] = 81 A2 00 63 72 3A 6D 03 6D 67 65 74 4C 61 73 74 56 61 6C 75 65 73
571
- // Use http://cbor.me to easily generate CBOR encoding
572
- const uint8_t CBOR_REQUEST_LAST_VALUE_MSG[] = { 0x81 , 0xA2 , 0x00 , 0x63 , 0x72 , 0x3A , 0x6D , 0x03 , 0x6D , 0x67 , 0x65 , 0x74 , 0x4C , 0x61 , 0x73 , 0x74 , 0x56 , 0x61 , 0x6C , 0x75 , 0x65 , 0x73 };
573
- write (_shadowTopicOut, CBOR_REQUEST_LAST_VALUE_MSG, sizeof (CBOR_REQUEST_LAST_VALUE_MSG));
574
- }
575
-
576
- void ArduinoIoTCloudTCP::requestThingId ()
577
- {
578
- if (!_mqttClient.subscribe (_deviceTopicIn))
579
- {
580
- /* If device_id is wrong the board can't connect to the broker so this condition
581
- * should never happen.
582
- */
583
- DEBUG_ERROR (" ArduinoIoTCloudTCP::%s could not subscribe to %s" , __FUNCTION__, _deviceTopicIn.c_str ());
584
- }
585
- }
586
-
587
567
void ArduinoIoTCloudTCP::attachThing ()
588
568
{
589
569
@@ -595,14 +575,6 @@ void ArduinoIoTCloudTCP::attachThing()
595
575
return ;
596
576
}
597
577
598
- _shadowTopicIn = getTopic_shadowin ();
599
- _shadowTopicOut = getTopic_shadowout ();
600
- if (!_mqttClient.subscribe (_shadowTopicIn)) {
601
- DEBUG_ERROR (" ArduinoIoTCloudTCP::%s could not subscribe to %s" , __FUNCTION__, _shadowTopicIn.c_str ());
602
- DEBUG_ERROR (" Check your thing configuration, and press the reset button on your board." );
603
- return ;
604
- }
605
-
606
578
DEBUG_INFO (" Connected to Arduino IoT Cloud" );
607
579
DEBUG_INFO (" Thing ID: %s" , getThingId ().c_str ());
608
580
execCloudEventCallback (ArduinoIoTCloudEvent::CONNECT);
@@ -615,11 +587,6 @@ void ArduinoIoTCloudTCP::detachThing()
615
587
return ;
616
588
}
617
589
618
- if (!_mqttClient.unsubscribe (_shadowTopicIn)) {
619
- DEBUG_ERROR (" ArduinoIoTCloudTCP::%s could not unsubscribe from %s" , __FUNCTION__, _shadowTopicIn.c_str ());
620
- return ;
621
- }
622
-
623
590
DEBUG_INFO (" Disconnected from Arduino IoT Cloud" );
624
591
execCloudEventCallback (ArduinoIoTCloudEvent::DISCONNECT);
625
592
}
0 commit comments