Skip to content

Commit 281c1f8

Browse files
pennamandreagilardoni
authored andcommitted
ArduinoIoTCloudTCP: switch to messages
1 parent a7903d5 commit 281c1f8

File tree

2 files changed

+65
-96
lines changed

2 files changed

+65
-96
lines changed

src/ArduinoIoTCloudTCP.cpp

+55-88
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <algorithm>
4444
#include "cbor/CBOREncoder.h"
4545
#include "utility/watchdog/Watchdog.h"
46+
#include <typeinfo>
4647

4748
/******************************************************************************
4849
LOCAL MODULE FUNCTIONS
@@ -76,8 +77,6 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP()
7677
, _mqttClient{nullptr}
7778
, _deviceTopicOut("")
7879
, _deviceTopicIn("")
79-
, _shadowTopicOut("")
80-
, _shadowTopicIn("")
8180
, _dataTopicOut("")
8281
, _dataTopicIn("")
8382
#if OTA_ENABLED
@@ -181,24 +180,22 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress,
181180
_mqttClient.setUsernamePassword(getDeviceId(), _password);
182181
}
183182
#endif
183+
184184
_mqttClient.onMessage(ArduinoIoTCloudTCP::onMessage);
185185
_mqttClient.setKeepAliveInterval(30 * 1000);
186186
_mqttClient.setConnectionTimeout(1500);
187187
_mqttClient.setId(getDeviceId().c_str());
188188

189189
_deviceTopicOut = getTopic_deviceout();
190190
_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();
197193

198194
_thing.begin();
199195
_device.begin();
200196

201197
#if OTA_ENABLED
198+
Property* p;
202199
p = new CloudWrapperBool(_ota_cap);
203200
addPropertyToContainer(_device.getPropertyContainer(), *p, "OTA_CAP", Permission::Read, -1);
204201
p = new CloudWrapperInt(_ota_error);
@@ -322,6 +319,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker()
322319
{
323320
if (_mqttClient.connect(_brokerAddress.c_str(), _brokerPort))
324321
{
322+
_mqttClient.subscribe(_messageTopicIn);
325323
DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s connected to %s:%d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort);
326324
/* Reconfigure timers for next state */
327325
_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)
468466
CBORDecoder::decode(_thing.getPropertyContainer(), (uint8_t*)bytes, length);
469467
}
470468

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+
}
481510
}
482511
}
483512

484513
void ArduinoIoTCloudTCP::sendMessage(Message * msg)
485514
{
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;
503518

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);
506524
}
507525
}
508526

@@ -531,24 +549,6 @@ void ArduinoIoTCloudTCP::sendThingPropertiesToCloud()
531549
sendPropertyContainerToCloud(_dataTopicOut, _thing.getPropertyContainer(), _thing.getPropertyContainerIndex());
532550
}
533551

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-
552552
#if OTA_ENABLED
553553
void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name)
554554
{
@@ -564,26 +564,6 @@ void ArduinoIoTCloudTCP::sendDevicePropertyToCloud(String const name)
564564
}
565565
#endif
566566

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-
587567
void ArduinoIoTCloudTCP::attachThing()
588568
{
589569

@@ -595,14 +575,6 @@ void ArduinoIoTCloudTCP::attachThing()
595575
return;
596576
}
597577

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-
606578
DEBUG_INFO("Connected to Arduino IoT Cloud");
607579
DEBUG_INFO("Thing ID: %s", getThingId().c_str());
608580
execCloudEventCallback(ArduinoIoTCloudEvent::CONNECT);
@@ -615,11 +587,6 @@ void ArduinoIoTCloudTCP::detachThing()
615587
return;
616588
}
617589

618-
if (!_mqttClient.unsubscribe(_shadowTopicIn)) {
619-
DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not unsubscribe from %s", __FUNCTION__, _shadowTopicIn.c_str());
620-
return;
621-
}
622-
623590
DEBUG_INFO("Disconnected from Arduino IoT Cloud");
624591
execCloudEventCallback(ArduinoIoTCloudEvent::DISCONNECT);
625592
}

src/ArduinoIoTCloudTCP.h

+10-8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
#include <utility/ota/OTA.h>
5757
#endif
5858

59+
#include "cbor/MessageDecoder.h"
60+
#include "cbor/MessageEncoder.h"
61+
5962
/******************************************************************************
6063
CONSTANTS
6164
******************************************************************************/
@@ -165,8 +168,8 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
165168

166169
String _deviceTopicOut;
167170
String _deviceTopicIn;
168-
String _shadowTopicOut;
169-
String _shadowTopicIn;
171+
String _messageTopicOut;
172+
String _messageTopicIn;
170173
String _dataTopicOut;
171174
String _dataTopicIn;
172175

@@ -182,8 +185,10 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
182185

183186
inline String getTopic_deviceout() { return String("/a/d/" + getDeviceId() + "/e/o");}
184187
inline String getTopic_devicein () { return String("/a/d/" + getDeviceId() + "/e/i");}
185-
inline String getTopic_shadowout() { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/o"); }
186-
inline String getTopic_shadowin () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/shadow/i"); }
188+
189+
inline String getTopic_messageout() { return String("/a/d/" + getDeviceId() + "/c/up");}
190+
inline String getTopic_messagein () { return String("/a/d/" + getDeviceId() + "/c/dw");}
191+
187192
inline String getTopic_dataout () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/o"); }
188193
inline String getTopic_datain () { return ( getThingId().length() == 0) ? String("") : String("/a/t/" + getThingId() + "/e/i"); }
189194

@@ -198,17 +203,14 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass
198203
void sendMessage(Message * msg);
199204
void sendPropertyContainerToCloud(String const topic, PropertyContainer & property_container, unsigned int & current_property_index);
200205
void sendThingPropertiesToCloud();
201-
void sendDevicePropertiesToCloud();
202-
void requestLastValue();
203-
void requestThingId();
206+
204207
void attachThing();
205208
void detachThing();
206209
int write(String const topic, byte const data[], int const length);
207210

208211
#if OTA_ENABLED
209212
void sendDevicePropertyToCloud(String const name);
210213
#endif
211-
212214
};
213215

214216
/******************************************************************************

0 commit comments

Comments
 (0)