From aa976939d6ea8d3808910dafcf494241f1ce461f Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Fri, 6 Dec 2019 12:02:58 +0100 Subject: [PATCH 1/9] First version of LoRa adapter --- src/ArduinoCloudProperty.cpp | 31 ++++++++++++------- src/ArduinoCloudProperty.h | 10 ++++++ src/ArduinoCloudThing.cpp | 59 +++++++++++++++++++++++++++++++++++- src/ArduinoCloudThing.h | 6 +++- src/types/CloudColor.h | 11 +++++++ src/types/CloudLocation.h | 9 ++++++ 6 files changed, 113 insertions(+), 13 deletions(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index 2b8031c..673ca1d 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -23,12 +23,7 @@ #endif static unsigned long getTimestamp() { - #ifdef ARDUINO_ARCH_SAMD - return rtc.getEpoch(); - #else -#pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ." - return 0; - #endif + return 0; } /****************************************************************************** @@ -47,6 +42,7 @@ ArduinoCloudProperty::ArduinoCloudProperty() _update_interval_millis(0), _last_local_change_timestamp(0), _last_cloud_change_timestamp(0), + _position(0), _map_data_list(nullptr) { } @@ -151,14 +147,23 @@ void ArduinoCloudProperty::appendAttributeReal(String value, String attributeNam } void ArduinoCloudProperty::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { + CborEncoder mapEncoder; cbor_encoder_create_map(encoder, &mapEncoder, 2); cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Name)); - String completeName = _name; - if (attributeName != "") { - completeName += ":" + attributeName; - } - cbor_encode_text_stringz(&mapEncoder, completeName.c_str()); + + #ifdef SerialLoRa + Serial.println("I'm a lora device!"); + cbor_encode_int(&mapEncoder, _position); + #else + Serial.println("I'm NOT a lora device!"); + String completeName = _name; + if (attributeName != "") { + completeName += ":" + attributeName; + } + cbor_encode_text_stringz(&mapEncoder, completeName.c_str()); + #endif + appendValue(mapEncoder); cbor_encoder_close_container(encoder, &mapEncoder); } @@ -233,3 +238,7 @@ unsigned long ArduinoCloudProperty::getLastCloudChangeTimestamp() { unsigned long ArduinoCloudProperty::getLastLocalChangeTimestamp() { return _last_local_change_timestamp; } + +void ArduinoCloudProperty::setPosition(int pos) { + _position = pos; +} diff --git a/src/ArduinoCloudProperty.h b/src/ArduinoCloudProperty.h index 57f92ab..15b2b76 100644 --- a/src/ArduinoCloudProperty.h +++ b/src/ArduinoCloudProperty.h @@ -99,6 +99,7 @@ class CborMapData { MapEntry base_time; MapEntry name; MapEntry attribute_name; + MapEntry property_position; MapEntry val; MapEntry str_val; MapEntry bool_val; @@ -138,6 +139,9 @@ class ArduinoCloudProperty { inline String name() const { return _name; } + inline int position() const { + return _position; + } inline bool isReadableByCloud() const { return (_permission == Permission::Read) || (_permission == Permission::ReadWrite); } @@ -152,6 +156,7 @@ class ArduinoCloudProperty { void setLastLocalChangeTimestamp(unsigned long localChangeTime); unsigned long getLastCloudChangeTimestamp(); unsigned long getLastLocalChangeTimestamp(); + void setPosition(int pos); void updateLocalTimestamp(); void append(CborEncoder * encoder); @@ -173,6 +178,9 @@ class ArduinoCloudProperty { virtual void fromLocalToCloud() = 0; virtual void appendAttributesToCloudReal(CborEncoder *encoder) = 0; virtual void setAttributesFromCloud() = 0; + virtual String getAttributeNameByPosition(int position) { + return ""; + }; virtual bool isPrimitive() { return false; }; @@ -197,6 +205,8 @@ class ArduinoCloudProperty { unsigned long _last_local_change_timestamp; unsigned long _last_cloud_change_timestamp; LinkedList * _map_data_list; + /* Store the position of the property in the array list */ + int _position; }; /****************************************************************************** diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index 1cdb8b6..062345a 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -45,6 +45,7 @@ void PrintFreeRam(void) { ArduinoCloudThing::ArduinoCloudThing() : _numPrimitivesProperties(0), + _numProperties(0), _isSyncMessage(false), _currentPropertyName(""), _currentPropertyBaseTime(0), @@ -92,9 +93,11 @@ ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & if (property.isPrimitive()) { _numPrimitivesProperties++; } + _numProperties++; addProperty(&property); return (property); } + } void ArduinoCloudThing::decode(uint8_t const * const payload, size_t const length, bool isSyncMessage) { @@ -180,6 +183,19 @@ ArduinoCloudProperty * ArduinoCloudThing::getProperty(String const & name) { return NULL; } +ArduinoCloudProperty * ArduinoCloudThing::getProperty(int const & pos) { + // The alternative to evaluate is simply: + // return _property_list.get(pos-1); + // to be verified if the position in the list is ALWAYS the id of the property + for (int i = 0; i < _property_list.size(); i++) { + ArduinoCloudProperty * p = _property_list.get(i); + if (p->position() == pos) { + return p; + } + } + return NULL; +} + // this function updates the timestamps on the primitive properties that have been modified locally since last cloud synchronization void ArduinoCloudThing::updateTimestampOnLocallyChangedProperties() { if (_numPrimitivesProperties == 0) { @@ -326,8 +342,32 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val map_data->attribute_name.set(attribute_name); next_state = MapParserState::MapKey; } + } else if (cbor_value_is_integer(value_iter)) { + int val = 0; + if (cbor_value_get_int(value_iter, &val) == CborNoError) { + Serial.print("Position to search is: "); + Serial.println(val); + String name = getPropertyNameByPosition(val); + Serial.print("Name of the property: "); + Serial.println(name); + map_data->name.set(name); + int colonPos = name.indexOf(":"); + String attribute_name = ""; + if (colonPos != -1) { + attribute_name = name.substring(colonPos + 1); + } + Serial.print("Name of the attribute: "); + Serial.println(name); + map_data->attribute_name.set(attribute_name); + + if (cbor_value_advance(value_iter) == CborNoError) { + next_state = MapParserState::MapKey; + } + } } + + return next_state; } @@ -404,7 +444,6 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_LeaveMap(CborValue * } if (_currentPropertyName != "" && propertyName != _currentPropertyName) { - /* Update the property containers depending on the parsed data */ updateProperty(_currentPropertyName, _currentPropertyBaseTime + _currentPropertyTime); /* Reset current property data */ @@ -461,6 +500,24 @@ void ArduinoCloudThing::updateProperty(String propertyName, unsigned long cloudC } } } + +String ArduinoCloudThing::getPropertyNameByPosition(int propertyPosition) { + if(propertyPosition>255) { + Serial.print("Position is: "); + Serial.println(propertyPosition & 255); + Serial.print("Sub-Position is: "); + Serial.println(propertyPosition >> 8); + ArduinoCloudProperty* property = getProperty(propertyPosition & 255); + String attributeName = property->getAttributeNameByPosition(propertyPosition >> 8); + return property->name() + ":" + attributeName; + } else { + Serial.print("Position is: "); + Serial.println(propertyPosition & 255); + ArduinoCloudProperty* property = getProperty(propertyPosition); + return property->name(); + } +} + bool ArduinoCloudThing::ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val) { if (cbor_value_is_integer(value_iter)) { diff --git a/src/ArduinoCloudThing.h b/src/ArduinoCloudThing.h index 9919573..d5e41a5 100644 --- a/src/ArduinoCloudThing.h +++ b/src/ArduinoCloudThing.h @@ -89,11 +89,13 @@ class ArduinoCloudThing { int appendChangedProperties(CborEncoder * arrayEncoder); void updateTimestampOnLocallyChangedProperties(); void updateProperty(String propertyName, unsigned long cloudChangeEventTime); + String getPropertyNameByPosition(int propertyPosition); private: LinkedList _property_list; /* Keep track of the number of primitive properties in the Thing. If 0 it allows the early exit in updateTimestampOnLocallyChangedProperties() */ int _numPrimitivesProperties; + int _numProperties; /* Indicates the if the message received to be decoded is a response to the getLastValues inquiry */ bool _isSyncMessage; /* List of map data that will hold all the attributes of a property */ @@ -135,11 +137,13 @@ class ArduinoCloudThing { static bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val); static double convertCborHalfFloatToDouble(uint16_t const half_val); - void freeMapDataList(LinkedList *map_data_list); + void freeMapDataList(LinkedList * map_data_list); inline void addProperty(ArduinoCloudProperty * property_obj) { + property_obj->setPosition(_numProperties); _property_list.add(property_obj); } ArduinoCloudProperty * getProperty(String const & name); + ArduinoCloudProperty * getProperty(int const & position); }; diff --git a/src/types/CloudColor.h b/src/types/CloudColor.h index cddc697..1c45efd 100644 --- a/src/types/CloudColor.h +++ b/src/types/CloudColor.h @@ -198,6 +198,17 @@ class CloudColor : public ArduinoCloudProperty { setAttribute(_cloud_value.sat); setAttribute(_cloud_value.bri); } + virtual String getAttributeNameByPosition(int position) { + if(position == 1) { + return "hue"; + } else if (position == 2) { + return "sat"; + } else if (position == 3) { + return "bri"; + } else { + return ""; + } + }; }; #endif /* CLOUDCOLOR_H_ */ \ No newline at end of file diff --git a/src/types/CloudLocation.h b/src/types/CloudLocation.h index b673d6f..1aa4b71 100644 --- a/src/types/CloudLocation.h +++ b/src/types/CloudLocation.h @@ -98,6 +98,15 @@ class CloudLocation : public ArduinoCloudProperty { setAttribute(_cloud_value.lat); setAttribute(_cloud_value.lon); } + virtual String getAttributeNameByPosition(int position) { + if(position == 1) { + return "lat"; + } else if (position == 2) { + return "lon"; + } else { + return ""; + } + }; }; #endif /* CLOUDLOCATION_H_ */ From 55fe5e52651da16992b785ff801e2003dcbdb80b Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Fri, 6 Dec 2019 17:24:11 +0100 Subject: [PATCH 2/9] Fix encoding of property identifier --- src/ArduinoCloudProperty.cpp | 4 +++- src/ArduinoCloudProperty.h | 3 +++ src/ArduinoCloudThing.cpp | 2 +- src/types/CloudLocation.h | 9 +++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index 673ca1d..d7bc1cf 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -154,7 +154,9 @@ void ArduinoCloudProperty::appendAttributeName(String attributeName, std::functi #ifdef SerialLoRa Serial.println("I'm a lora device!"); - cbor_encode_int(&mapEncoder, _position); + int completePosition = getPostionByAttributeName(attributeName) * 256; + completePosition += _position; + cbor_encode_int(&mapEncoder, completePosition); #else Serial.println("I'm NOT a lora device!"); String completeName = _name; diff --git a/src/ArduinoCloudProperty.h b/src/ArduinoCloudProperty.h index 15b2b76..8a56d99 100644 --- a/src/ArduinoCloudProperty.h +++ b/src/ArduinoCloudProperty.h @@ -181,6 +181,9 @@ class ArduinoCloudProperty { virtual String getAttributeNameByPosition(int position) { return ""; }; + virtual int getPostionByAttributeName(String attributeName) { + return 0; + }; virtual bool isPrimitive() { return false; }; diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index 062345a..3185a4d 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -357,7 +357,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val attribute_name = name.substring(colonPos + 1); } Serial.print("Name of the attribute: "); - Serial.println(name); + Serial.println(attribute_name); map_data->attribute_name.set(attribute_name); if (cbor_value_advance(value_iter) == CborNoError) { diff --git a/src/types/CloudLocation.h b/src/types/CloudLocation.h index 1aa4b71..a3fc78f 100644 --- a/src/types/CloudLocation.h +++ b/src/types/CloudLocation.h @@ -107,6 +107,15 @@ class CloudLocation : public ArduinoCloudProperty { return ""; } }; + virtual int getPostionByAttributeName(String attributeName) { + if(attributeName == "lat") { + return 1; + } else if (attributeName == "lon") { + return 2; + } else { + return 0; + } + }; }; #endif /* CLOUDLOCATION_H_ */ From fcc5419068e5d01eaa5f9227203f96d821254bc8 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Mon, 9 Dec 2019 11:46:09 +0100 Subject: [PATCH 3/9] Light payload management --- src/ArduinoCloudProperty.cpp | 52 ++++++++++++++++++++++------------ src/ArduinoCloudProperty.h | 26 ++++++++--------- src/ArduinoCloudThing.cpp | 55 ++++++++++++++---------------------- src/ArduinoCloudThing.h | 10 +++---- src/types/CloudColor.h | 11 -------- src/types/CloudLocation.h | 19 ------------- 6 files changed, 73 insertions(+), 100 deletions(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index d7bc1cf..027d20f 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -42,7 +42,9 @@ ArduinoCloudProperty::ArduinoCloudProperty() _update_interval_millis(0), _last_local_change_timestamp(0), _last_cloud_change_timestamp(0), - _position(0), + _identifier(0), + _lightPayload(false), + _attributeIdentifier(0), _map_data_list(nullptr) { } @@ -111,7 +113,9 @@ void ArduinoCloudProperty::execCallbackOnSync() { } } -void ArduinoCloudProperty::append(CborEncoder *encoder) { +void ArduinoCloudProperty::append(CborEncoder *encoder, bool lightPayload) { + _lightPayload = lightPayload; + _attributeIdentifier = 0; appendAttributesToCloudReal(encoder); fromLocalToCloud(); _has_been_updated_once = true; @@ -147,31 +151,31 @@ void ArduinoCloudProperty::appendAttributeReal(String value, String attributeNam } void ArduinoCloudProperty::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { - + if(attributeName != ""){ + _attributeIdentifier++; + } CborEncoder mapEncoder; cbor_encoder_create_map(encoder, &mapEncoder, 2); cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Name)); - #ifdef SerialLoRa - Serial.println("I'm a lora device!"); - int completePosition = getPostionByAttributeName(attributeName) * 256; - completePosition += _position; - cbor_encode_int(&mapEncoder, completePosition); - #else - Serial.println("I'm NOT a lora device!"); + if(_lightPayload) { + int completeIdentifier = _attributeIdentifier * 256; + completeIdentifier += _identifier; + cbor_encode_int(&mapEncoder, completeIdentifier); + } else { String completeName = _name; if (attributeName != "") { completeName += ":" + attributeName; } cbor_encode_text_stringz(&mapEncoder, completeName.c_str()); - #endif - + } appendValue(mapEncoder); cbor_encoder_close_container(encoder, &mapEncoder); } void ArduinoCloudProperty::setAttributesFromCloud(LinkedList *map_data_list) { _map_data_list = map_data_list; + _attributeIdentifier = 0; setAttributesFromCloud(); } @@ -200,16 +204,28 @@ void ArduinoCloudProperty::setAttributeReal(String& value, String attributeName) } void ArduinoCloudProperty::setAttributeReal(String attributeName, std::functionsetValue) { + if(attributeName != ""){ + _attributeIdentifier++; + } for (int i = 0; i < _map_data_list->size(); i++) { CborMapData *map = _map_data_list->get(i); if (map != nullptr) { - String an = map->attribute_name.get(); - if (an == attributeName) { - setValue(map); - break; + if(map->light_payload.isSet() && map->light_payload.get()) { + int attid = map->attribute_identifier.get(); + if (attid == _attributeIdentifier) { + setValue(map); + break; + } + } else { + String an = map->attribute_name.get(); + if (an == attributeName) { + setValue(map); + break; + } } } } + } String ArduinoCloudProperty::getAttributeName(String propertyName, char separator) { @@ -241,6 +257,6 @@ unsigned long ArduinoCloudProperty::getLastLocalChangeTimestamp() { return _last_local_change_timestamp; } -void ArduinoCloudProperty::setPosition(int pos) { - _position = pos; +void ArduinoCloudProperty::setIdentifier(int identifier) { + _identifier = identifier; } diff --git a/src/ArduinoCloudProperty.h b/src/ArduinoCloudProperty.h index 8a56d99..d2c1991 100644 --- a/src/ArduinoCloudProperty.h +++ b/src/ArduinoCloudProperty.h @@ -98,8 +98,11 @@ class CborMapData { MapEntry base_name; MapEntry base_time; MapEntry name; + MapEntry name_identifier; + MapEntry light_payload; MapEntry attribute_name; - MapEntry property_position; + MapEntry attribute_identifier; + MapEntry property_identifier; MapEntry val; MapEntry str_val; MapEntry bool_val; @@ -139,8 +142,8 @@ class ArduinoCloudProperty { inline String name() const { return _name; } - inline int position() const { - return _position; + inline int identifier() const { + return _identifier; } inline bool isReadableByCloud() const { return (_permission == Permission::Read) || (_permission == Permission::ReadWrite); @@ -156,10 +159,10 @@ class ArduinoCloudProperty { void setLastLocalChangeTimestamp(unsigned long localChangeTime); unsigned long getLastCloudChangeTimestamp(); unsigned long getLastLocalChangeTimestamp(); - void setPosition(int pos); + void setIdentifier(int identifier); void updateLocalTimestamp(); - void append(CborEncoder * encoder); + void append(CborEncoder * encoder, bool lightPayload); void appendAttributeReal(bool value, String attributeName = "", CborEncoder *encoder = nullptr); void appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); void appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); @@ -178,12 +181,6 @@ class ArduinoCloudProperty { virtual void fromLocalToCloud() = 0; virtual void appendAttributesToCloudReal(CborEncoder *encoder) = 0; virtual void setAttributesFromCloud() = 0; - virtual String getAttributeNameByPosition(int position) { - return ""; - }; - virtual int getPostionByAttributeName(String attributeName) { - return 0; - }; virtual bool isPrimitive() { return false; }; @@ -208,8 +205,11 @@ class ArduinoCloudProperty { unsigned long _last_local_change_timestamp; unsigned long _last_cloud_change_timestamp; LinkedList * _map_data_list; - /* Store the position of the property in the array list */ - int _position; + /* Store the identifier of the property in the array list */ + int _identifier; + int _attributeIdentifier; + /* Indicates if the property shall be encoded using the identifier instead of the name */ + bool _lightPayload; }; /****************************************************************************** diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index 3185a4d..da2e65a 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -59,7 +59,8 @@ ArduinoCloudThing::ArduinoCloudThing() : void ArduinoCloudThing::begin() { } -int ArduinoCloudThing::encode(uint8_t * data, size_t const size) { +int ArduinoCloudThing::encode(uint8_t * data, size_t const size, bool lightPayload) { + // check if backing storage and cloud has diverged // time interval may be elapsed or property may be changed CborEncoder encoder, arrayEncoder; @@ -70,7 +71,7 @@ int ArduinoCloudThing::encode(uint8_t * data, size_t const size) { return -1; } - if (appendChangedProperties(&arrayEncoder) < 1) { + if (appendChangedProperties(&arrayEncoder, lightPayload) < 1) { return -1; } @@ -161,18 +162,19 @@ bool ArduinoCloudThing::isPropertyInContainer(String const & name) { return false; } -int ArduinoCloudThing::appendChangedProperties(CborEncoder * arrayEncoder) { +int ArduinoCloudThing::appendChangedProperties(CborEncoder * arrayEncoder, bool lightPayload) { int appendedProperties = 0; for (int i = 0; i < _property_list.size(); i++) { ArduinoCloudProperty * p = _property_list.get(i); if (p->shouldBeUpdated() && p->isReadableByCloud()) { - p->append(arrayEncoder); + p->append(arrayEncoder, lightPayload); appendedProperties++; } } return appendedProperties; } +//retrieve property by name ArduinoCloudProperty * ArduinoCloudThing::getProperty(String const & name) { for (int i = 0; i < _property_list.size(); i++) { ArduinoCloudProperty * p = _property_list.get(i); @@ -183,13 +185,11 @@ ArduinoCloudProperty * ArduinoCloudThing::getProperty(String const & name) { return NULL; } +//retrieve property by identifier ArduinoCloudProperty * ArduinoCloudThing::getProperty(int const & pos) { - // The alternative to evaluate is simply: - // return _property_list.get(pos-1); - // to be verified if the position in the list is ALWAYS the id of the property for (int i = 0; i < _property_list.size(); i++) { ArduinoCloudProperty * p = _property_list.get(i); - if (p->position() == pos) { + if (p->identifier() == pos) { return p; } } @@ -345,20 +345,13 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val } else if (cbor_value_is_integer(value_iter)) { int val = 0; if (cbor_value_get_int(value_iter, &val) == CborNoError) { - Serial.print("Position to search is: "); - Serial.println(val); - String name = getPropertyNameByPosition(val); - Serial.print("Name of the property: "); - Serial.println(name); + map_data->light_payload.set(true); + map_data->name_identifier.set(val&255); + map_data->attribute_identifier.set(val>>8); + map_data->light_payload.set(true); + String name = getPropertyNameByIdentifier(val); map_data->name.set(name); - int colonPos = name.indexOf(":"); - String attribute_name = ""; - if (colonPos != -1) { - attribute_name = name.substring(colonPos + 1); - } - Serial.print("Name of the attribute: "); - Serial.println(attribute_name); - map_data->attribute_name.set(attribute_name); + if (cbor_value_advance(value_iter) == CborNoError) { next_state = MapParserState::MapKey; @@ -501,21 +494,15 @@ void ArduinoCloudThing::updateProperty(String propertyName, unsigned long cloudC } } -String ArduinoCloudThing::getPropertyNameByPosition(int propertyPosition) { - if(propertyPosition>255) { - Serial.print("Position is: "); - Serial.println(propertyPosition & 255); - Serial.print("Sub-Position is: "); - Serial.println(propertyPosition >> 8); - ArduinoCloudProperty* property = getProperty(propertyPosition & 255); - String attributeName = property->getAttributeNameByPosition(propertyPosition >> 8); - return property->name() + ":" + attributeName; +// retrieve the property name by the identifier +String ArduinoCloudThing::getPropertyNameByIdentifier(int propertyIdentifier) { + ArduinoCloudProperty* property; + if(propertyIdentifier>255) { + property = getProperty(propertyIdentifier & 255); } else { - Serial.print("Position is: "); - Serial.println(propertyPosition & 255); - ArduinoCloudProperty* property = getProperty(propertyPosition); - return property->name(); + property = getProperty(propertyIdentifier); } + return property->name(); } bool ArduinoCloudThing::ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val) { diff --git a/src/ArduinoCloudThing.h b/src/ArduinoCloudThing.h index d5e41a5..6eb54c9 100644 --- a/src/ArduinoCloudThing.h +++ b/src/ArduinoCloudThing.h @@ -81,15 +81,15 @@ class ArduinoCloudThing { ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission); /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ - int encode(uint8_t * data, size_t const size); + int encode(uint8_t * data, size_t const size, bool lightPayload = false); /* decode a CBOR payload received from the cloud */ void decode(uint8_t const * const payload, size_t const length, bool isSyncMessage = false); bool isPropertyInContainer(String const & name); - int appendChangedProperties(CborEncoder * arrayEncoder); + int appendChangedProperties(CborEncoder * arrayEncoder, bool lightPayload); void updateTimestampOnLocallyChangedProperties(); void updateProperty(String propertyName, unsigned long cloudChangeEventTime); - String getPropertyNameByPosition(int propertyPosition); + String getPropertyNameByIdentifier(int propertyIdentifier); private: LinkedList _property_list; @@ -139,11 +139,11 @@ class ArduinoCloudThing { static double convertCborHalfFloatToDouble(uint16_t const half_val); void freeMapDataList(LinkedList * map_data_list); inline void addProperty(ArduinoCloudProperty * property_obj) { - property_obj->setPosition(_numProperties); + property_obj->setIdentifier(_numProperties); _property_list.add(property_obj); } ArduinoCloudProperty * getProperty(String const & name); - ArduinoCloudProperty * getProperty(int const & position); + ArduinoCloudProperty * getProperty(int const & identifier); }; diff --git a/src/types/CloudColor.h b/src/types/CloudColor.h index 1c45efd..cddc697 100644 --- a/src/types/CloudColor.h +++ b/src/types/CloudColor.h @@ -198,17 +198,6 @@ class CloudColor : public ArduinoCloudProperty { setAttribute(_cloud_value.sat); setAttribute(_cloud_value.bri); } - virtual String getAttributeNameByPosition(int position) { - if(position == 1) { - return "hue"; - } else if (position == 2) { - return "sat"; - } else if (position == 3) { - return "bri"; - } else { - return ""; - } - }; }; #endif /* CLOUDCOLOR_H_ */ \ No newline at end of file diff --git a/src/types/CloudLocation.h b/src/types/CloudLocation.h index a3fc78f..79d6554 100644 --- a/src/types/CloudLocation.h +++ b/src/types/CloudLocation.h @@ -83,7 +83,6 @@ class CloudLocation : public ArduinoCloudProperty { return _value; } - virtual void fromCloudToLocal() { _value = _cloud_value; } @@ -98,24 +97,6 @@ class CloudLocation : public ArduinoCloudProperty { setAttribute(_cloud_value.lat); setAttribute(_cloud_value.lon); } - virtual String getAttributeNameByPosition(int position) { - if(position == 1) { - return "lat"; - } else if (position == 2) { - return "lon"; - } else { - return ""; - } - }; - virtual int getPostionByAttributeName(String attributeName) { - if(attributeName == "lat") { - return 1; - } else if (attributeName == "lon") { - return 2; - } else { - return 0; - } - }; }; #endif /* CLOUDLOCATION_H_ */ From 4beff8241e3c00b52996af58f8f92fd111e0c675 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Mon, 9 Dec 2019 14:10:35 +0100 Subject: [PATCH 4/9] Unit test updated --- src/ArduinoCloudProperty.cpp | 4 ++-- test/include/TestUtil.h | 2 +- test/src/TestUtil.cpp | 4 ++-- test/src/test_decode.cpp | 44 ++++++++++++++++++++++++++++++++++++ test/src/test_encode.cpp | 36 +++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index 027d20f..d6f8e9a 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -42,10 +42,10 @@ ArduinoCloudProperty::ArduinoCloudProperty() _update_interval_millis(0), _last_local_change_timestamp(0), _last_cloud_change_timestamp(0), + _map_data_list(nullptr), _identifier(0), - _lightPayload(false), _attributeIdentifier(0), - _map_data_list(nullptr) { + _lightPayload(false) { } /****************************************************************************** diff --git a/test/include/TestUtil.h b/test/include/TestUtil.h index beb6a09..ea5e588 100644 --- a/test/include/TestUtil.h +++ b/test/include/TestUtil.h @@ -17,7 +17,7 @@ PROTOTYPES **************************************************************************************/ -std::vector encode(ArduinoCloudThing & thing); +std::vector encode(ArduinoCloudThing & thing, bool lightPayload = false); void print(std::vector const & vect); #endif /* INCLUDE_TESTUTIL_H_ */ diff --git a/test/src/TestUtil.cpp b/test/src/TestUtil.cpp index ab54c00..b372388 100644 --- a/test/src/TestUtil.cpp +++ b/test/src/TestUtil.cpp @@ -15,9 +15,9 @@ PUBLIC FUNCTIONS **************************************************************************************/ -std::vector encode(ArduinoCloudThing & thing) { +std::vector encode(ArduinoCloudThing & thing, bool lightPayload) { uint8_t buf[200] = {0}; - int const bytes_buf = thing.encode(buf, 200); + int const bytes_buf = thing.encode(buf, 200, lightPayload); if (bytes_buf == -1) { return std::vector(); } else { diff --git a/test/src/test_decode.cpp b/test/src/test_decode.cpp index 3fff8a4..df5fda5 100644 --- a/test/src/test_decode.cpp +++ b/test/src/test_decode.cpp @@ -50,6 +50,25 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") /************************************************************************************/ + WHEN("A boolean property is changed via CBOR message - light payload") { + GIVEN("CloudProtocol::V2") { + ArduinoCloudThing thing; + thing.begin(); + + CloudBool test = true; + thing.addPropertyReal(test, "test", Permission::ReadWrite); + + /* [{0: "test", 4: false}] = 81 A2 00 01 04 F4 */ + uint8_t const payload[] = {0x81, 0xA2, 0x00, 0x01, 0x04, 0xF4}; + int const payload_length = sizeof(payload) / sizeof(uint8_t); + thing.decode(payload, payload_length); + + REQUIRE(test == false); + } + } + + /************************************************************************************/ + WHEN("A int property is changed via CBOR message") { GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; @@ -164,6 +183,31 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") } } + /************************************************************************************/ + + WHEN("A Color property is changed via CBOR message - light payload") { + GIVEN("CloudProtocol::V2") { + ArduinoCloudThing thing; + thing.begin(); + + CloudColor color_test = CloudColor(0.0, 0.0, 0.0); + + thing.addPropertyReal(color_test, "test", Permission::ReadWrite); + + /* [{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 83 A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 */ + uint8_t const payload[] = {0x83, 0xA2, 0x00, 0x19, 0x01, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x02, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x03, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00 }; + thing.decode(payload, sizeof(payload) / sizeof(uint8_t)); + + Color color_compare = Color(2.0, 2.0, 2.0); + Color value_color_test = color_test.getValue(); + bool verify = (value_color_test == color_compare); + REQUIRE(verify); + REQUIRE(value_color_test.hue == color_compare.hue); + REQUIRE(value_color_test.sat == color_compare.sat); + REQUIRE(value_color_test.bri == color_compare.bri); + } + } + /************************************************************************************/ WHEN("A ColoredLight property is changed via CBOR message") { diff --git a/test/src/test_encode.cpp b/test/src/test_encode.cpp index 9640224..b9ff70d 100644 --- a/test/src/test_encode.cpp +++ b/test/src/test_encode.cpp @@ -40,6 +40,24 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") /************************************************************************************/ + WHEN("A 'bool' property is added - light payload") { + GIVEN("CloudProtocol::V2") { + ArduinoCloudThing thing; + thing.begin(); + encode(thing); + + CloudBool test = true; + thing.addPropertyReal(test, "test", Permission::ReadWrite); + + /* [{0: "test", 4: true}] = 9F A2 00 01 04 F5 FF*/ + std::vector const expected = {0x9F, 0xA2, 0x00, 0x01, 0x04, 0xF5, 0xFF}; + std::vector const actual = encode(thing, true); + REQUIRE(actual == expected); + } + } + + /************************************************************************************/ + WHEN("A 'int' property is added") { GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; @@ -131,6 +149,24 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") /************************************************************************************/ + WHEN("A 'Color' property is added - light payload") { + GIVEN("CloudProtocol::V2") { + ArduinoCloudThing thing; + thing.begin(); + encode(thing); + + CloudColor color_test = CloudColor(2.0, 2.0, 2.0); + thing.addPropertyReal(color_test, "test", Permission::ReadWrite); + + /* [{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 9F A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 FF*/ + std::vector const expected = {0x9F, 0xA2, 0x00, 0x19, 0x01, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x02, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x03, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; + std::vector const actual = encode(thing, true); + REQUIRE(actual == expected); + } + } + + /************************************************************************************/ + WHEN("A 'ColoredLight' property is added") { GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; From 081a5f6d773861c013238dfd37ddcbac27841ad3 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Mon, 9 Dec 2019 17:11:38 +0100 Subject: [PATCH 5/9] Added property identifier to addPropertyReal method --- src/ArduinoCloudThing.cpp | 4 ++-- src/ArduinoCloudThing.h | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index da2e65a..f679796 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -86,7 +86,7 @@ int ArduinoCloudThing::encode(uint8_t * data, size_t const size, bool lightPaylo return bytes_encoded; } -ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission) { +ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier) { property.init(name, permission); if (isPropertyInContainer(name)) { return (*getProperty(name)); @@ -95,7 +95,7 @@ ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & _numPrimitivesProperties++; } _numProperties++; - addProperty(&property); + addProperty(&property, propertyIdentifier); return (property); } diff --git a/src/ArduinoCloudThing.h b/src/ArduinoCloudThing.h index 6eb54c9..1d4c0c8 100644 --- a/src/ArduinoCloudThing.h +++ b/src/ArduinoCloudThing.h @@ -78,7 +78,7 @@ class ArduinoCloudThing { void begin(); - ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission); + ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier); /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ int encode(uint8_t * data, size_t const size, bool lightPayload = false); @@ -138,8 +138,12 @@ class ArduinoCloudThing { static bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val); static double convertCborHalfFloatToDouble(uint16_t const half_val); void freeMapDataList(LinkedList * map_data_list); - inline void addProperty(ArduinoCloudProperty * property_obj) { - property_obj->setIdentifier(_numProperties); + inline void addProperty(ArduinoCloudProperty * property_obj, int propertyIdentifier) { + if(propertyIdentifier != -1) { + property_obj->setIdentifier(propertyIdentifier); + } else { + property_obj->setIdentifier(_numProperties); + } _property_list.add(property_obj); } ArduinoCloudProperty * getProperty(String const & name); From 7fbfe1fd37698f722feba54d4634d981016d3140 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Tue, 10 Dec 2019 16:51:43 +0100 Subject: [PATCH 6/9] Fix Astyle formatting --- src/ArduinoCloudProperty.cpp | 14 +++++++------- src/ArduinoCloudThing.cpp | 12 ++++++------ src/ArduinoCloudThing.h | 4 ++-- test/src/test_decode.cpp | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index d6f8e9a..91860b5 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -23,7 +23,7 @@ #endif static unsigned long getTimestamp() { - return 0; + return 0; } /****************************************************************************** @@ -151,16 +151,16 @@ void ArduinoCloudProperty::appendAttributeReal(String value, String attributeNam } void ArduinoCloudProperty::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { - if(attributeName != ""){ + if (attributeName != "") { _attributeIdentifier++; } CborEncoder mapEncoder; cbor_encoder_create_map(encoder, &mapEncoder, 2); cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Name)); - if(_lightPayload) { + if (_lightPayload) { int completeIdentifier = _attributeIdentifier * 256; - completeIdentifier += _identifier; + completeIdentifier += _identifier; cbor_encode_int(&mapEncoder, completeIdentifier); } else { String completeName = _name; @@ -204,13 +204,13 @@ void ArduinoCloudProperty::setAttributeReal(String& value, String attributeName) } void ArduinoCloudProperty::setAttributeReal(String attributeName, std::functionsetValue) { - if(attributeName != ""){ + if (attributeName != "") { _attributeIdentifier++; } for (int i = 0; i < _map_data_list->size(); i++) { CborMapData *map = _map_data_list->get(i); if (map != nullptr) { - if(map->light_payload.isSet() && map->light_payload.get()) { + if (map->light_payload.isSet() && map->light_payload.get()) { int attid = map->attribute_identifier.get(); if (attid == _attributeIdentifier) { setValue(map); @@ -225,7 +225,7 @@ void ArduinoCloudProperty::setAttributeReal(String attributeName, std::function< } } } - + } String ArduinoCloudProperty::getAttributeName(String propertyName, char separator) { diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index f679796..cc43283 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -98,7 +98,7 @@ ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & addProperty(&property, propertyIdentifier); return (property); } - + } void ArduinoCloudThing::decode(uint8_t const * const payload, size_t const length, bool isSyncMessage) { @@ -346,12 +346,12 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val int val = 0; if (cbor_value_get_int(value_iter, &val) == CborNoError) { map_data->light_payload.set(true); - map_data->name_identifier.set(val&255); - map_data->attribute_identifier.set(val>>8); + map_data->name_identifier.set(val & 255); + map_data->attribute_identifier.set(val >> 8); map_data->light_payload.set(true); String name = getPropertyNameByIdentifier(val); map_data->name.set(name); - + if (cbor_value_advance(value_iter) == CborNoError) { next_state = MapParserState::MapKey; @@ -359,7 +359,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val } } - + return next_state; } @@ -497,7 +497,7 @@ void ArduinoCloudThing::updateProperty(String propertyName, unsigned long cloudC // retrieve the property name by the identifier String ArduinoCloudThing::getPropertyNameByIdentifier(int propertyIdentifier) { ArduinoCloudProperty* property; - if(propertyIdentifier>255) { + if (propertyIdentifier > 255) { property = getProperty(propertyIdentifier & 255); } else { property = getProperty(propertyIdentifier); diff --git a/src/ArduinoCloudThing.h b/src/ArduinoCloudThing.h index 1d4c0c8..f2508bb 100644 --- a/src/ArduinoCloudThing.h +++ b/src/ArduinoCloudThing.h @@ -78,7 +78,7 @@ class ArduinoCloudThing { void begin(); - ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier); + ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier = -1); /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ int encode(uint8_t * data, size_t const size, bool lightPayload = false); @@ -139,7 +139,7 @@ class ArduinoCloudThing { static double convertCborHalfFloatToDouble(uint16_t const half_val); void freeMapDataList(LinkedList * map_data_list); inline void addProperty(ArduinoCloudProperty * property_obj, int propertyIdentifier) { - if(propertyIdentifier != -1) { + if (propertyIdentifier != -1) { property_obj->setIdentifier(propertyIdentifier); } else { property_obj->setIdentifier(_numProperties); diff --git a/test/src/test_decode.cpp b/test/src/test_decode.cpp index df5fda5..d5e9f36 100644 --- a/test/src/test_decode.cpp +++ b/test/src/test_decode.cpp @@ -183,7 +183,7 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") } } - /************************************************************************************/ + /************************************************************************************/ WHEN("A Color property is changed via CBOR message - light payload") { GIVEN("CloudProtocol::V2") { From 2b84cd16e53e89c1fe9db860667bedd63d985bc4 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Tue, 10 Dec 2019 17:37:23 +0100 Subject: [PATCH 7/9] Fix unit tests --- test/src/test_decode.cpp | 8 ++++---- test/src/test_encode.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/src/test_decode.cpp b/test/src/test_decode.cpp index d5e9f36..83fae10 100644 --- a/test/src/test_decode.cpp +++ b/test/src/test_decode.cpp @@ -56,9 +56,9 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") thing.begin(); CloudBool test = true; - thing.addPropertyReal(test, "test", Permission::ReadWrite); + thing.addPropertyReal(test, "test", Permission::ReadWrite, 1); - /* [{0: "test", 4: false}] = 81 A2 00 01 04 F4 */ + /* [{0: 1, 4: false}] = 81 A2 00 01 04 F4 */ uint8_t const payload[] = {0x81, 0xA2, 0x00, 0x01, 0x04, 0xF4}; int const payload_length = sizeof(payload) / sizeof(uint8_t); thing.decode(payload, payload_length); @@ -192,9 +192,9 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") CloudColor color_test = CloudColor(0.0, 0.0, 0.0); - thing.addPropertyReal(color_test, "test", Permission::ReadWrite); + thing.addPropertyReal(color_test, "test", Permission::ReadWrite, 1); - /* [{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 83 A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 */ + /* [{0: 257, 2: 2.0},{0: 513, 2: 2.0},{0: 769, 2: 2.0}] = 83 A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 */ uint8_t const payload[] = {0x83, 0xA2, 0x00, 0x19, 0x01, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x02, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x03, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00 }; thing.decode(payload, sizeof(payload) / sizeof(uint8_t)); diff --git a/test/src/test_encode.cpp b/test/src/test_encode.cpp index b9ff70d..da61eb0 100644 --- a/test/src/test_encode.cpp +++ b/test/src/test_encode.cpp @@ -47,9 +47,9 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") encode(thing); CloudBool test = true; - thing.addPropertyReal(test, "test", Permission::ReadWrite); + thing.addPropertyReal(test, "test", Permission::ReadWrite, 1); - /* [{0: "test", 4: true}] = 9F A2 00 01 04 F5 FF*/ + /* [{0: 1, 4: true}] = 9F A2 00 01 04 F5 FF*/ std::vector const expected = {0x9F, 0xA2, 0x00, 0x01, 0x04, 0xF5, 0xFF}; std::vector const actual = encode(thing, true); REQUIRE(actual == expected); @@ -156,9 +156,9 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") encode(thing); CloudColor color_test = CloudColor(2.0, 2.0, 2.0); - thing.addPropertyReal(color_test, "test", Permission::ReadWrite); + thing.addPropertyReal(color_test, "test", Permission::ReadWrite, 1); - /* [{0: "test:hue", 2: 2.0},{0: "test:sat", 2: 2.0},{0: "test:bri", 2: 2.0}] = 9F A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 FF*/ + /* [{0: 257, 2: 2.0},{0: 513, 2: 2.0},{0: 769, 2: 2.0}] = 9F A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 FF*/ std::vector const expected = {0x9F, 0xA2, 0x00, 0x19, 0x01, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x02, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x19, 0x03, 0x01, 0x02, 0xFA, 0x40, 0x00, 0x00, 0x00, 0xFF }; std::vector const actual = encode(thing, true); REQUIRE(actual == expected); From e4140c308a62da247e1657470405f85db73f94de Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Wed, 11 Dec 2019 13:44:39 +0100 Subject: [PATCH 8/9] Added comments to the code --- src/ArduinoCloudProperty.cpp | 6 ++++++ src/ArduinoCloudThing.cpp | 2 ++ src/ArduinoCloudThing.h | 4 +++- test/src/test_decode.cpp | 4 ++++ test/src/test_encode.cpp | 4 ++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index 91860b5..8a75e29 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -152,14 +152,18 @@ void ArduinoCloudProperty::appendAttributeReal(String value, String attributeNam void ArduinoCloudProperty::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { if (attributeName != "") { + // when the attribute name string is not empty, the attribute identifier is incremented in order to be encoded in the message if the _lightPayload flag is set _attributeIdentifier++; } CborEncoder mapEncoder; cbor_encoder_create_map(encoder, &mapEncoder, 2); cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Name)); + // if _lightPayload is true, the property and attribute identifiers will be encoded instead of the property name if (_lightPayload) { + // the most significant byte of the identifier to be encoded represent the property identifier int completeIdentifier = _attributeIdentifier * 256; + // the least significant byte of the identifier to be encoded represent the attribute identifier completeIdentifier += _identifier; cbor_encode_int(&mapEncoder, completeIdentifier); } else { @@ -211,12 +215,14 @@ void ArduinoCloudProperty::setAttributeReal(String attributeName, std::function< CborMapData *map = _map_data_list->get(i); if (map != nullptr) { if (map->light_payload.isSet() && map->light_payload.get()) { + // if a light payload is detected, the attribute identifier is retrieved from the cbor map and the corresponding attribute is updated int attid = map->attribute_identifier.get(); if (attid == _attributeIdentifier) { setValue(map); break; } } else { + // if a normal payload is detected, the name of the attribute to be updated is extracted directly from the cbor map String an = map->attribute_name.get(); if (an == attributeName) { setValue(map); diff --git a/src/ArduinoCloudThing.cpp b/src/ArduinoCloudThing.cpp index cc43283..32dd596 100644 --- a/src/ArduinoCloudThing.cpp +++ b/src/ArduinoCloudThing.cpp @@ -328,6 +328,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val MapParserState next_state = MapParserState::Error; if (cbor_value_is_text_string(value_iter)) { + // if the value in the cbor message is a string, it corresponds to the name of the property to be updated (int the form [property_name]:[attribute_name]) char * val = nullptr; size_t val_size = 0; if (cbor_value_dup_text_string(value_iter, &val, &val_size, value_iter) == CborNoError) { @@ -343,6 +344,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val next_state = MapParserState::MapKey; } } else if (cbor_value_is_integer(value_iter)) { + // if the value in the cbor message is an integer, a light payload has been used and an integer identifier should be decode in order to retrieve the corresponding property and attribute name to be updated int val = 0; if (cbor_value_get_int(value_iter, &val) == CborNoError) { map_data->light_payload.set(true); diff --git a/src/ArduinoCloudThing.h b/src/ArduinoCloudThing.h index f2508bb..c44eea6 100644 --- a/src/ArduinoCloudThing.h +++ b/src/ArduinoCloudThing.h @@ -77,10 +77,11 @@ class ArduinoCloudThing { ArduinoCloudThing(); void begin(); - + //if propertyIdentifier is different from -1, an integer identifier is associated to the added property to be use instead of the property name when the parameter lightPayload is true in the encode method ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier = -1); /* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */ + /* if lightPayload is true the integer identifier of the property will be encoded in the message instead of the property name in order to reduce the size of the message payload*/ int encode(uint8_t * data, size_t const size, bool lightPayload = false); /* decode a CBOR payload received from the cloud */ void decode(uint8_t const * const payload, size_t const length, bool isSyncMessage = false); @@ -142,6 +143,7 @@ class ArduinoCloudThing { if (propertyIdentifier != -1) { property_obj->setIdentifier(propertyIdentifier); } else { + // if property identifier is -1, an incremental value will be assigned as identifier. property_obj->setIdentifier(_numProperties); } _property_list.add(property_obj); diff --git a/test/src/test_decode.cpp b/test/src/test_decode.cpp index 83fae10..5f521f9 100644 --- a/test/src/test_decode.cpp +++ b/test/src/test_decode.cpp @@ -51,11 +51,13 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") /************************************************************************************/ WHEN("A boolean property is changed via CBOR message - light payload") { + /*An integer identifier has been encoded instead of the name of the property in order to have a shorter payload*/ GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; thing.begin(); CloudBool test = true; + /*The property is added with identifier 1 that will be used instead of the string "test" as property identifier*/ thing.addPropertyReal(test, "test", Permission::ReadWrite, 1); /* [{0: 1, 4: false}] = 81 A2 00 01 04 F4 */ @@ -186,12 +188,14 @@ SCENARIO("Arduino Cloud Properties are decoded", "[ArduinoCloudThing::decode]") /************************************************************************************/ WHEN("A Color property is changed via CBOR message - light payload") { + /*An integer identifier has been encoded instead of the name of the property in order to have a shorter payload*/ GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; thing.begin(); CloudColor color_test = CloudColor(0.0, 0.0, 0.0); + /*The property is added with identifier 1 that will be used instead of the string "test" as property identifier*/ thing.addPropertyReal(color_test, "test", Permission::ReadWrite, 1); /* [{0: 257, 2: 2.0},{0: 513, 2: 2.0},{0: 769, 2: 2.0}] = 83 A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 */ diff --git a/test/src/test_encode.cpp b/test/src/test_encode.cpp index da61eb0..a9a5c5e 100644 --- a/test/src/test_encode.cpp +++ b/test/src/test_encode.cpp @@ -41,12 +41,14 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") /************************************************************************************/ WHEN("A 'bool' property is added - light payload") { + /*An integer identifier must be instead of the name of the property in order to have a shorter payload*/ GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; thing.begin(); encode(thing); CloudBool test = true; + /*The property is added with identifier 1 that will be used instead of the string "test" as property identifier*/ thing.addPropertyReal(test, "test", Permission::ReadWrite, 1); /* [{0: 1, 4: true}] = 9F A2 00 01 04 F5 FF*/ @@ -150,12 +152,14 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") /************************************************************************************/ WHEN("A 'Color' property is added - light payload") { + /*An integer identifier must be encoded instead of the name of the property in order to have a shorter payload*/ GIVEN("CloudProtocol::V2") { ArduinoCloudThing thing; thing.begin(); encode(thing); CloudColor color_test = CloudColor(2.0, 2.0, 2.0); + /*The property is added with identifier 1 that will be used instead of the string "name" as property identifier */ thing.addPropertyReal(color_test, "test", Permission::ReadWrite, 1); /* [{0: 257, 2: 2.0},{0: 513, 2: 2.0},{0: 769, 2: 2.0}] = 9F A2 00 19 01 01 02 FA 40 00 00 00 A2 00 19 02 01 02 FA 40 00 00 00 A2 00 19 03 01 02 FA 40 00 00 00 FF*/ From f0839713bf89f82d0f933f8f9202e8b044937f65 Mon Sep 17 00:00:00 2001 From: mirkokurt Date: Wed, 11 Dec 2019 16:08:00 +0100 Subject: [PATCH 9/9] Restored the code of getTimestamp() method --- src/ArduinoCloudProperty.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ArduinoCloudProperty.cpp b/src/ArduinoCloudProperty.cpp index 8a75e29..64f9279 100644 --- a/src/ArduinoCloudProperty.cpp +++ b/src/ArduinoCloudProperty.cpp @@ -23,7 +23,12 @@ #endif static unsigned long getTimestamp() { + #ifdef ARDUINO_ARCH_SAMD + return rtc.getEpoch(); + #else +#pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ." return 0; + #endif } /******************************************************************************