diff --git a/extras/test/src/test_encode.cpp b/extras/test/src/test_encode.cpp index 063a97daa..24df1f0ac 100644 --- a/extras/test/src/test_encode.cpp +++ b/extras/test/src/test_encode.cpp @@ -20,7 +20,7 @@ TEST CODE **************************************************************************************/ -SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") { +SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode-1]") { /************************************************************************************/ WHEN("A 'bool' property is added") { @@ -381,4 +381,59 @@ SCENARIO("Arduino Cloud Properties are encoded", "[ArduinoCloudThing::encode]") } /************************************************************************************/ + + WHEN("The size of the encoded properties is exceeding the CBOR buffer size") { + GIVEN("CloudProtocol::V2") { + PropertyContainer property_container; + + CloudString str_0; str_0 = "This string is 30 bytes long."; + CloudString str_1; str_1 = "This string is 30 bytes long."; + CloudString str_2; str_2 = "This string is 30 bytes long."; + CloudString str_3; str_3 = "This string is 30 bytes long."; + CloudString str_4; str_4 = "This string is 30 bytes long."; + CloudString str_5; str_5 = "This string is 30 bytes long."; + CloudString str_6; str_6 = "This string is 30 bytes long."; + CloudString str_7; str_7 = "This string is 30 bytes long."; + CloudString str_8; str_8 = "This string is 30 bytes long."; + CloudString str_9; str_9 = "This string is 30 bytes long."; + + addPropertyToContainer(property_container, str_0, "str_0", Permission::ReadWrite); + addPropertyToContainer(property_container, str_1, "str_1", Permission::ReadWrite); + addPropertyToContainer(property_container, str_2, "str_2", Permission::ReadWrite); + addPropertyToContainer(property_container, str_3, "str_3", Permission::ReadWrite); + addPropertyToContainer(property_container, str_4, "str_4", Permission::ReadWrite); + addPropertyToContainer(property_container, str_5, "str_5", Permission::ReadWrite); + addPropertyToContainer(property_container, str_6, "str_6", Permission::ReadWrite); + addPropertyToContainer(property_container, str_7, "str_7", Permission::ReadWrite); + addPropertyToContainer(property_container, str_8, "str_8", Permission::ReadWrite); + addPropertyToContainer(property_container, str_9, "str_9", Permission::ReadWrite); + + /* Due to the size if the encoded properties exceeding 256 bytes if encoded all at + * once they are encoded in subsequent calls to CBOREncoder::encode. + */ + + /* [{0: "str_0", 3: "This string is 30 bytes long."}, {0: "str_1", 3: "This string is 30 bytes long."}, {0: "str_2", 3: "This string is 30 bytes long."}, {0: "str_3", 3: "This string is 30 bytes long."}] + * = 9F A2 00 65 73 74 72 5F 30 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 31 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 32 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 33 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF + */ + std::vector const expected_1 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x30, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x31, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x32, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x33, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; + std::vector const actual_1 = cbor::encode(property_container); + REQUIRE(actual_1 == expected_1); + + /* [{0: "str_4", 3: "This string is 30 bytes long."}, {0: "str_5", 3: "This string is 30 bytes long."}, {0: "str_6", 3: "This string is 30 bytes long."}, {0: "str_7", 3: "This string is 30 bytes long."}] + * = 9F A2 00 65 73 74 72 5F 34 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 35 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 36 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 37 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF + */ + std::vector const expected_2 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x34, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x35, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x36, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x37, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; + std::vector const actual_2 = cbor::encode(property_container); + REQUIRE(actual_2 == expected_2); + + /* [{0: "str_8", 3: "This string is 30 bytes long."}, {0: "str_9", 3: "This string is 30 bytes long."}] + * = 9F A2 00 65 73 74 72 5F 38 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E A2 00 65 73 74 72 5F 39 03 78 1D 54 68 69 73 20 73 74 72 69 6E 67 20 69 73 20 33 30 20 62 79 74 65 73 20 6C 6F 6E 67 2E FF + */ + std::vector const expected_3 = {0x9F, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x38, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xA2, 0x00, 0x65, 0x73, 0x74, 0x72, 0x5F, 0x39, 0x03, 0x78, 0x1D, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x20, 0x69, 0x73, 0x20, 0x33, 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x2E, 0xFF}; + std::vector const actual_3 = cbor::encode(property_container); + REQUIRE(actual_3 == expected_3); + } + } + + /************************************************************************************/ } diff --git a/extras/test/src/util/CBORTestUtil.cpp b/extras/test/src/util/CBORTestUtil.cpp index b2bd1f751..04ad7b3f0 100644 --- a/extras/test/src/util/CBORTestUtil.cpp +++ b/extras/test/src/util/CBORTestUtil.cpp @@ -25,13 +25,13 @@ namespace cbor **************************************************************************************/ std::vector encode(PropertyContainer & property_container, bool lightPayload) { + int bytes_encoded = 0; uint8_t buf[200] = {0}; - int const bytes_buf = CBOREncoder::encode(property_container, buf, 200, lightPayload); - if (bytes_buf == -1) { + + if (CBOREncoder::encode(property_container, buf, 200, bytes_encoded, lightPayload) == CborNoError) + return std::vector(buf, buf + bytes_encoded); + else return std::vector(); - } else { - return std::vector(buf, buf + bytes_buf); - } } void print(std::vector const & vect) { diff --git a/src/ArduinoIoTCloudLPWAN.cpp b/src/ArduinoIoTCloudLPWAN.cpp index acf840ef4..0858193aa 100644 --- a/src/ArduinoIoTCloudLPWAN.cpp +++ b/src/ArduinoIoTCloudLPWAN.cpp @@ -126,11 +126,12 @@ void ArduinoIoTCloudLPWAN::disconnect() void ArduinoIoTCloudLPWAN::sendPropertiesToCloud() { + int bytes_encoded = 0; uint8_t data[CBOR_LORA_MSG_MAX_SIZE]; - int const length = CBOREncoder::encode(_property_container, data, sizeof(data), true); - if (length > 0) { - writeProperties(data, length); - } + + if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, true) == CborNoError) + if (bytes_encoded > 0) + writeProperties(data, bytes_encoded); } int ArduinoIoTCloudLPWAN::writeProperties(const byte data[], int length) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 0a075156a..f8adfdcc5 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -283,18 +283,20 @@ void ArduinoIoTCloudTCP::handleMessage(int length) void ArduinoIoTCloudTCP::sendPropertiesToCloud() { + int bytes_encoded = 0; uint8_t data[MQTT_TRANSMIT_BUFFER_SIZE]; - int const length = CBOREncoder::encode(_property_container, data, sizeof(data)); - if (length > 0) - { - /* If properties have been encoded store them in the back-up buffer - * in order to allow retransmission in case of failure. - */ - _mqtt_data_len = length; - memcpy(_mqtt_data_buf, data, _mqtt_data_len); - /* Transmit the properties to the MQTT broker */ - write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); - } + + if (CBOREncoder::encode(_property_container, data, sizeof(data), bytes_encoded, false) == CborNoError) + if (bytes_encoded > 0) + { + /* If properties have been encoded store them in the back-up buffer + * in order to allow retransmission in case of failure. + */ + _mqtt_data_len = bytes_encoded; + memcpy(_mqtt_data_buf, data, _mqtt_data_len); + /* Transmit the properties to the MQTT broker */ + write(_dataTopicOut, _mqtt_data_buf, _mqtt_data_len); + } } void ArduinoIoTCloudTCP::requestLastValue() diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index 6de4d487d..399d521fa 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -21,31 +21,53 @@ #include "CBOREncoder.h" +#undef max +#undef min +#include + #include "lib/tinycbor/cbor-lib.h" /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ -int CBOREncoder::encode(PropertyContainer & property_container, uint8_t * data, size_t const size, bool lightPayload) +CborError CBOREncoder::encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, bool lightPayload) { CborEncoder encoder, arrayEncoder; cbor_encoder_init(&encoder, data, size, 0); - if (cbor_encoder_create_array(&encoder, &arrayEncoder, CborIndefiniteLength) != CborNoError) - return -1; + CHECK_CBOR(cbor_encoder_create_array(&encoder, &arrayEncoder, CborIndefiniteLength)); /* Check if backing storage and cloud has diverged * time interval may be elapsed or property may be changed * and if that's the case encode the property into the CBOR. */ - if (appendChangedProperties(property_container, &arrayEncoder, lightPayload) < 1) - return -1; + CborError error = CborNoError; + int num_encoded_properties = 0; + std::for_each(property_container.begin(), + property_container.end(), + [lightPayload, &arrayEncoder, &error, &num_encoded_properties](Property * p) + { + if (p->shouldBeUpdated() && p->isReadableByCloud()) + { + error = p->append(&arrayEncoder, lightPayload); + if(error == CborNoError) + num_encoded_properties++; + else + return; + } + }); + if ((CborNoError != error) && + (CborErrorOutOfMemory != error)) + return error; + + CHECK_CBOR(cbor_encoder_close_container(&encoder, &arrayEncoder)); - if (cbor_encoder_close_container(&encoder, &arrayEncoder) != CborNoError) - return -1; + if (num_encoded_properties > 0) + bytes_encoded = cbor_encoder_get_buffer_size(&encoder, data); + else + bytes_encoded = 0; - int const bytes_encoded = cbor_encoder_get_buffer_size(&encoder, data); - return bytes_encoded; + return CborNoError; } diff --git a/src/cbor/CBOREncoder.h b/src/cbor/CBOREncoder.h index 90aff85c9..abaa9d4b7 100644 --- a/src/cbor/CBOREncoder.h +++ b/src/cbor/CBOREncoder.h @@ -35,7 +35,7 @@ class CBOREncoder /* 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*/ - static int encode(PropertyContainer & property_container, uint8_t * data, size_t const size, bool lightPayload = false); + static CborError encode(PropertyContainer & property_container, uint8_t * data, size_t const size, int & bytes_encoded, bool lightPayload = false); private: diff --git a/src/cbor/lib/tinycbor/cbor-lib.h b/src/cbor/lib/tinycbor/cbor-lib.h index 0ac58a17d..d66553bf8 100644 --- a/src/cbor/lib/tinycbor/cbor-lib.h +++ b/src/cbor/lib/tinycbor/cbor-lib.h @@ -1,6 +1,24 @@ #ifndef CBOR_LIB_H #define CBOR_LIB_H +/****************************************************************************** + INCLUDE + ******************************************************************************/ + #include "src/cbor.h" +/****************************************************************************** + * DEFINE + ******************************************************************************/ + +#ifndef CHECK_CBOR + #define CHECK_CBOR(expr) \ + do { \ + CborError error = CborNoError; \ + error = (expr); \ + if (CborNoError != error) \ + return error; \ + } while(0); +#endif /* CHECK_CBOR */ + #endif \ No newline at end of file diff --git a/src/property/Property.cpp b/src/property/Property.cpp index 9c4203c4d..bccbae1b8 100644 --- a/src/property/Property.cpp +++ b/src/property/Property.cpp @@ -142,78 +142,92 @@ void Property::execCallbackOnSync() { } } -void Property::append(CborEncoder *encoder, bool lightPayload) { +CborError Property::append(CborEncoder *encoder, bool lightPayload) { _lightPayload = lightPayload; _attributeIdentifier = 0; - appendAttributesToCloudReal(encoder); + CHECK_CBOR(appendAttributesToCloudReal(encoder)); fromLocalToCloud(); _has_been_updated_once = true; _update_requested = false; _last_updated_millis = millis(); + return CborNoError; } -void Property::appendAttributeReal(bool value, String attributeName, CborEncoder *encoder) { - appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { - cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::BooleanValue)); - cbor_encode_boolean(&mapEncoder, value); +CborError Property::appendAttributeReal(bool value, String attributeName, CborEncoder *encoder) { + return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) + { + CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::BooleanValue))); + CHECK_CBOR(cbor_encode_boolean(&mapEncoder, value)); + return CborNoError; }, encoder); } -void Property::appendAttributeReal(int value, String attributeName, CborEncoder *encoder) { - appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { - cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value)); - cbor_encode_int(&mapEncoder, value); +CborError Property::appendAttributeReal(int value, String attributeName, CborEncoder *encoder) { + return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) + { + CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); + CHECK_CBOR(cbor_encode_int(&mapEncoder, value)); + return CborNoError; }, encoder); } -void Property::appendAttributeReal(float value, String attributeName, CborEncoder *encoder) { - appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { - cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value)); - cbor_encode_float(&mapEncoder, value); +CborError Property::appendAttributeReal(float value, String attributeName, CborEncoder *encoder) { + return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) + { + CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Value))); + CHECK_CBOR(cbor_encode_float(&mapEncoder, value)); + return CborNoError; }, encoder); } -void Property::appendAttributeReal(String value, String attributeName, CborEncoder *encoder) { - appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) { - cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::StringValue)); - cbor_encode_text_stringz(&mapEncoder, value.c_str()); +CborError Property::appendAttributeReal(String value, String attributeName, CborEncoder *encoder) { + return appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) + { + CHECK_CBOR(cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::StringValue))); + CHECK_CBOR(cbor_encode_text_stringz(&mapEncoder, value.c_str())); + return CborNoError; }, encoder); } -void Property::appendAttributeName(String attributeName, std::functionappendValue, CborEncoder *encoder) { +CborError Property::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; unsigned int num_map_properties = _encode_timestamp ? 3 : 2; - cbor_encoder_create_map(encoder, &mapEncoder, num_map_properties); - cbor_encode_int(&mapEncoder, static_cast(CborIntegerMapKey::Name)); + CHECK_CBOR(cbor_encoder_create_map(encoder, &mapEncoder, num_map_properties)); + CHECK_CBOR(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) { + 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 { + CHECK_CBOR(cbor_encode_int(&mapEncoder, completeIdentifier)); + } + else + { String completeName = _name; if (attributeName != "") { completeName += ":" + attributeName; } - cbor_encode_text_stringz(&mapEncoder, completeName.c_str()); + CHECK_CBOR(cbor_encode_text_stringz(&mapEncoder, completeName.c_str())); } /* Encode the value */ - appendValue(mapEncoder); + CHECK_CBOR(appendValue(mapEncoder)); + /* Encode the timestamp if that has been required. */ if(_encode_timestamp) { - cbor_encode_int (&mapEncoder, static_cast(CborIntegerMapKey::Time)); - cbor_encode_uint(&mapEncoder, _timestamp); + CHECK_CBOR(cbor_encode_int (&mapEncoder, static_cast(CborIntegerMapKey::Time))); + CHECK_CBOR(cbor_encode_uint(&mapEncoder, _timestamp)); } /* Close the container */ - cbor_encoder_close_container(encoder, &mapEncoder); + CHECK_CBOR(cbor_encoder_close_container(encoder, &mapEncoder)); + return CborNoError; } void Property::setAttributesFromCloud(std::list * map_data_list) { diff --git a/src/property/Property.h b/src/property/Property.h index 8eb643668..4b5900782 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -36,6 +36,10 @@ #include "../cbor/lib/tinycbor/cbor-lib.h" +/****************************************************************************** + DEFINE + ******************************************************************************/ + #define appendAttributesToCloud() appendAttributesToCloudReal(CborEncoder *encoder) #define appendAttribute(x) appendAttributeReal(x, getAttributeName(#x, '.'), encoder) #define setAttribute(x) setAttributeReal(x, getAttributeName(#x, '.')) @@ -168,12 +172,12 @@ class Property void setIdentifier(int identifier); void updateLocalTimestamp(); - 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); - void appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); - void appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); + CborError append(CborEncoder * encoder, bool lightPayload); + CborError appendAttributeReal(bool value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttributeReal(String value, String attributeName = "", CborEncoder *encoder = nullptr); + CborError appendAttributeName(String attributeName, std::functionf, CborEncoder *encoder); void setAttributesFromCloud(std::list * map_data_list); void setAttributeReal(bool& value, String attributeName = ""); void setAttributeReal(int& value, String attributeName = ""); @@ -185,7 +189,7 @@ class Property virtual bool isDifferentFromCloud() = 0; virtual void fromCloudToLocal() = 0; virtual void fromLocalToCloud() = 0; - virtual void appendAttributesToCloudReal(CborEncoder *encoder) = 0; + virtual CborError appendAttributesToCloudReal(CborEncoder *encoder) = 0; virtual void setAttributesFromCloud() = 0; virtual bool isPrimitive() { return false; diff --git a/src/property/PropertyContainer.cpp b/src/property/PropertyContainer.cpp index b545378ad..7a699ee97 100644 --- a/src/property/PropertyContainer.cpp +++ b/src/property/PropertyContainer.cpp @@ -83,22 +83,6 @@ Property * getProperty(PropertyContainer & prop_cont, int const identifier) return (*iter); } -int appendChangedProperties(PropertyContainer & prop_cont, CborEncoder * arrayEncoder, bool lightPayload) -{ - int appendedProperties = 0; - std::for_each(prop_cont.begin(), - prop_cont.end(), - [arrayEncoder, lightPayload, &appendedProperties](Property * p) - { - if (p->shouldBeUpdated() && p->isReadableByCloud()) - { - p->append(arrayEncoder, lightPayload); - appendedProperties++; - } - }); - return appendedProperties; -} - void requestUpdateForAllProperties(PropertyContainer & prop_cont) { std::for_each(prop_cont.begin(), diff --git a/src/property/PropertyContainer.h b/src/property/PropertyContainer.h index abc9d7a79..f18ff8019 100644 --- a/src/property/PropertyContainer.h +++ b/src/property/PropertyContainer.h @@ -78,7 +78,6 @@ Property * getProperty(PropertyContainer & prop_cont, String const & name); Property * getProperty(PropertyContainer & prop_cont, int const identifier); -int appendChangedProperties(PropertyContainer & prop_cont, CborEncoder * arrayEncoder, bool lightPayload); void updateTimestampOnLocallyChangedProperties(PropertyContainer & prop_cont); void requestUpdateForAllProperties(PropertyContainer & prop_cont); void updateProperty(PropertyContainer & prop_cont, String propertyName, unsigned long cloudChangeEventTime, bool const is_sync_message, std::list * map_data_list); diff --git a/src/property/types/CloudBool.h b/src/property/types/CloudBool.h index 2ac989629..e0b9f1f30 100644 --- a/src/property/types/CloudBool.h +++ b/src/property/types/CloudBool.h @@ -52,8 +52,8 @@ class CloudBool : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudColor.h b/src/property/types/CloudColor.h index ea126122a..205423165 100644 --- a/src/property/types/CloudColor.h +++ b/src/property/types/CloudColor.h @@ -188,10 +188,11 @@ class CloudColor : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value.hue); - appendAttribute(_value.sat); - appendAttribute(_value.bri); + virtual CborError appendAttributesToCloud() { + CHECK_CBOR(appendAttribute(_value.hue)); + CHECK_CBOR(appendAttribute(_value.sat)); + CHECK_CBOR(appendAttribute(_value.bri)); + return CborNoError; } virtual void setAttributesFromCloud() { setAttribute(_cloud_value.hue); diff --git a/src/property/types/CloudFloat.h b/src/property/types/CloudFloat.h index 33860f9c3..b68fe70fe 100644 --- a/src/property/types/CloudFloat.h +++ b/src/property/types/CloudFloat.h @@ -54,8 +54,8 @@ class CloudFloat : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudInt.h b/src/property/types/CloudInt.h index 97a3c6a15..0ce65777a 100644 --- a/src/property/types/CloudInt.h +++ b/src/property/types/CloudInt.h @@ -52,8 +52,8 @@ class CloudInt : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudLocation.h b/src/property/types/CloudLocation.h index cbb74754a..0968fea3d 100644 --- a/src/property/types/CloudLocation.h +++ b/src/property/types/CloudLocation.h @@ -89,9 +89,10 @@ class CloudLocation : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value.lat); - appendAttribute(_value.lon); + virtual CborError appendAttributesToCloud() { + CHECK_CBOR(appendAttribute(_value.lat)); + CHECK_CBOR(appendAttribute(_value.lon)); + return CborNoError; } virtual void setAttributesFromCloud() { setAttribute(_cloud_value.lat); diff --git a/src/property/types/CloudString.h b/src/property/types/CloudString.h index b2fd447ef..027179411 100644 --- a/src/property/types/CloudString.h +++ b/src/property/types/CloudString.h @@ -55,8 +55,8 @@ class CloudString : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudWrapperBool.h b/src/property/types/CloudWrapperBool.h index 483cefc99..701e7c87d 100644 --- a/src/property/types/CloudWrapperBool.h +++ b/src/property/types/CloudWrapperBool.h @@ -45,8 +45,8 @@ class CloudWrapperBool : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual void appendAttributesToCloud() { - appendAttribute(_primitive_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_primitive_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudWrapperFloat.h b/src/property/types/CloudWrapperFloat.h index d30b1d86c..db0f640cf 100644 --- a/src/property/types/CloudWrapperFloat.h +++ b/src/property/types/CloudWrapperFloat.h @@ -47,8 +47,8 @@ class CloudWrapperFloat : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual void appendAttributesToCloud() { - appendAttribute(_primitive_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_primitive_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudWrapperInt.h b/src/property/types/CloudWrapperInt.h index db83ab1db..261c72d46 100644 --- a/src/property/types/CloudWrapperInt.h +++ b/src/property/types/CloudWrapperInt.h @@ -45,8 +45,8 @@ class CloudWrapperInt : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual void appendAttributesToCloud() { - appendAttribute(_primitive_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_primitive_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/CloudWrapperString.h b/src/property/types/CloudWrapperString.h index e384365ad..3e1c0a3e3 100644 --- a/src/property/types/CloudWrapperString.h +++ b/src/property/types/CloudWrapperString.h @@ -49,8 +49,8 @@ class CloudWrapperString : public CloudWrapperBase { virtual void fromLocalToCloud() { _cloud_value = _primitive_value; } - virtual void appendAttributesToCloud() { - appendAttribute(_primitive_value); + virtual CborError appendAttributesToCloud() { + return appendAttribute(_primitive_value); } virtual void setAttributesFromCloud() { setAttribute(_cloud_value); diff --git a/src/property/types/automation/CloudColoredLight.h b/src/property/types/automation/CloudColoredLight.h index d5e380118..8d8c0519b 100644 --- a/src/property/types/automation/CloudColoredLight.h +++ b/src/property/types/automation/CloudColoredLight.h @@ -118,11 +118,12 @@ class CloudColoredLight : public CloudColor { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value.swi); - appendAttribute(_value.hue); - appendAttribute(_value.sat); - appendAttribute(_value.bri); + virtual CborError appendAttributesToCloud() { + CHECK_CBOR(appendAttribute(_value.swi)); + CHECK_CBOR(appendAttribute(_value.hue)); + CHECK_CBOR(appendAttribute(_value.sat)); + CHECK_CBOR(appendAttribute(_value.bri)); + return CborNoError; } virtual void setAttributesFromCloud() { setAttribute(_cloud_value.swi); diff --git a/src/property/types/automation/CloudDimmedLight.h b/src/property/types/automation/CloudDimmedLight.h index ecb9a6d92..1a8f78eef 100644 --- a/src/property/types/automation/CloudDimmedLight.h +++ b/src/property/types/automation/CloudDimmedLight.h @@ -98,18 +98,19 @@ class CloudDimmedLight : public Property { _cloud_value = _value; } - virtual void appendAttributesToCloud() { + virtual CborError appendAttributesToCloud() { appendAttribute(_value.swi); // To allow visualization through color widget // Start float hue = 0; float sat = 0; - appendAttributeReal(hue, getAttributeName(".hue", '.'), encoder); - appendAttributeReal(sat, getAttributeName(".sat", '.'), encoder); - appendAttribute(_value.bri); + CHECK_CBOR(appendAttributeReal(hue, getAttributeName(".hue", '.'), encoder)); + CHECK_CBOR(appendAttributeReal(sat, getAttributeName(".sat", '.'), encoder)); + CHECK_CBOR(appendAttribute(_value.bri)); // should be only: // appendAttribute(_value.bri); // end + return CborNoError; } virtual void setAttributesFromCloud() { diff --git a/src/property/types/automation/CloudTelevision.h b/src/property/types/automation/CloudTelevision.h index c96a49e45..1d4ecd2dd 100644 --- a/src/property/types/automation/CloudTelevision.h +++ b/src/property/types/automation/CloudTelevision.h @@ -213,13 +213,14 @@ class CloudTelevision : public Property { virtual void fromLocalToCloud() { _cloud_value = _value; } - virtual void appendAttributesToCloud() { - appendAttribute(_value.swi); - appendAttribute(_value.vol); - appendAttribute(_value.mut); - appendAttribute((int)_value.pbc); - appendAttribute((int)_value.inp); - appendAttribute(_value.cha); + virtual CborError appendAttributesToCloud() { + CHECK_CBOR(appendAttribute(_value.swi)); + CHECK_CBOR(appendAttribute(_value.vol)); + CHECK_CBOR(appendAttribute(_value.mut)); + CHECK_CBOR(appendAttribute((int)_value.pbc)); + CHECK_CBOR(appendAttribute((int)_value.inp)); + CHECK_CBOR(appendAttribute(_value.cha)); + return CborNoError; } virtual void setAttributesFromCloud() { setAttribute(_cloud_value.swi);