From 7d75e69c315da3a897d1ea37692ee3975d67221a Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Tue, 15 Nov 2022 16:21:11 +0000 Subject: [PATCH 01/29] Add commands for bridge-generated dynamic clusters --- examples/dynamic-bridge-app/linux/BUILD.gn | 2 +- .../dynamic-bridge-app/linux/UserInputBackend.cpp | 2 +- .../linux/include/GeneratedClusters.h | 9 +++++++++ .../idl/generators/bridge/BridgeClustersCpp.jinja | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/BUILD.gn b/examples/dynamic-bridge-app/linux/BUILD.gn index 1f4bda053ce30f..d415578394df0a 100644 --- a/examples/dynamic-bridge-app/linux/BUILD.gn +++ b/examples/dynamic-bridge-app/linux/BUILD.gn @@ -29,7 +29,7 @@ if (chip_enable_pw_rpc) { assert(chip_build_tools) chip_codegen("chip-bridge-codegen") { - input = "${chip_root}/examples/bridge-app/bridge-common/bridge-app.matter" + input = "${chip_root}/examples/dynamic-bridge-app/bridge-common/bridge-app.matter" generator = "bridge" outputs = [ diff --git a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp index 9bdf4b8e689710..ccd7f9524bc056 100644 --- a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp +++ b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp @@ -120,7 +120,7 @@ void AddCluster(const std::vector & tokens) auto c = CreateCluster(cluster_name.c_str()); if (c) { - g_pending->AddCluster(std::make_unique(std::move(c))); + g_pending->AddCluster(std::make_unique(std::move(c), c->GetIncomingCommandList(), c->GetOutgoingCommandList())); } else { diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 99f1c5e06bc98b..3f92bed6b02b35 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -24,4 +24,13 @@ class GeneratedCluster virtual chip::ClusterId GetClusterId() = 0; // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; + + virtual chip::CommandId * GetIncomingCommandList() + { + return nullptr; + } + virtual chip::CommandId * GetOutgoingCommandList() + { + return nullptr; + }; }; diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 62c1f41e77ac26..3e829ba627972c 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -59,6 +59,20 @@ struct {{cluster.name}}Cluster : public GeneratedCluster }); } + {%- if cluster.commands | length > 0 %} + chip::CommandId incomingCommandList[{{cluster.commands | length + 1}}] = { + {%- for command in cluster.commands %} + {{command.code}}, + {%- endfor %} + chip::kInvalidCommandId + }; + + chip::CommandId * GetIncomingCommandList() override + { + return incomingCommandList; + } + {%- endif %} + {% for attr in cluster.attributes %} {{"List" if attr.definition.is_list}}Attribute<{{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}; {%- endfor %} From ccb4bb9a0b652233344fe701607140ca784b173c Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Fri, 18 Nov 2022 19:39:21 +0000 Subject: [PATCH 02/29] Allow reads and writes to externally stored OnOff cluster attribute --- .../dynamic-bridge-app/linux/include/main.h | 2 + examples/dynamic-bridge-app/linux/main.cpp | 102 ++++++++++++++++++ .../generators/bridge/BridgeClustersCpp.jinja | 2 +- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/examples/dynamic-bridge-app/linux/include/main.h b/examples/dynamic-bridge-app/linux/include/main.h index 30df5ae0248f9c..d11982d85fbc55 100644 --- a/examples/dynamic-bridge-app/linux/include/main.h +++ b/examples/dynamic-bridge-app/linux/include/main.h @@ -62,3 +62,5 @@ chip::Span GetActionListInfo(chip::EndpointId parentId); chip::Optional LookupClusterByName(const char * name); std::unique_ptr CreateCluster(const char * name); std::unique_ptr CreateCluster(chip::ClusterId id); +EmberAfStatus HandleReadOnOffAttribute(Attribute * attribute, uint8_t * buffer, uint16_t maxReadLength); +EmberAfStatus HandleWriteOnOffAttribute(Attribute * attribute, uint8_t * buffer); diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index efb339582e3085..6ce4b0f45742e2 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -185,6 +185,108 @@ bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj return true; } +EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, + uint16_t maxReadLength) +{ + uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); + + EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; + + if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != nullptr)) + { + DynamicDevice * dev = g_device_impls[endpointIndex].get(); + CommonCluster * cluster = nullptr; + const std::vector clusters = dev->clusters(); + int clusters_count = (int) clusters.size(); + for (int cluster_index = 0; cluster_index < clusters_count; cluster_index++) + { + if (clusters[cluster_index]->GetClusterId() == clusterId) + { + cluster = clusters[cluster_index]; + break; + } + } + + if (cluster == nullptr) return ret; + + AttributeInterface * attribute = cluster->FindAttribute(attributeMetadata->attributeId); + + if (clusterId == ZCL_ON_OFF_CLUSTER_ID) + { + ret = HandleReadOnOffAttribute(static_cast *>(attribute), buffer, maxReadLength); + } + } + + return ret; +} + +EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, + const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer) +{ + uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); + + EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; + + if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != nullptr)) + { + DynamicDevice * dev = g_device_impls[endpointIndex].get(); + CommonCluster * cluster = nullptr; + const std::vector clusters = dev->clusters(); + int clusters_count = (int) clusters.size(); + for (int cluster_index = 0; cluster_index < clusters_count; cluster_index++) + { + if (clusters[cluster_index]->GetClusterId() == clusterId) + { + cluster = clusters[cluster_index]; + break; + } + } + + if (cluster == nullptr) return ret; + + AttributeInterface * attribute = cluster->FindAttribute(attributeMetadata->attributeId); + + if (clusterId == ZCL_ON_OFF_CLUSTER_ID) + { + ret = HandleWriteOnOffAttribute(static_cast *>(attribute), buffer); + } + } + + return ret; +} + +EmberAfStatus HandleReadOnOffAttribute(Attribute * attribute, uint8_t * buffer, uint16_t maxReadLength) +{ + if ((attribute->GetId() == ZCL_ON_OFF_ATTRIBUTE_ID) && (maxReadLength == 1)) + { + *buffer = attribute->Peek() ? 1 : 0; + } + else if ((attribute->GetId() == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) + { + *buffer = (uint16_t) ZCL_ON_OFF_CLUSTER_REVISION; + } + else + { + return EMBER_ZCL_STATUS_FAILURE; + } + + return EMBER_ZCL_STATUS_SUCCESS; +} + +EmberAfStatus HandleWriteOnOffAttribute(Attribute * attribute, uint8_t * buffer) +{ + if (attribute->GetId() == ZCL_ON_OFF_ATTRIBUTE_ID) + { + *attribute = (*buffer) == 1; + } + else + { + return EMBER_ZCL_STATUS_FAILURE; + } + return EMBER_ZCL_STATUS_SUCCESS; +} + Device * FindDeviceEndpoint(chip::EndpointId id) { for (auto dev : gDevices) diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 3e829ba627972c..7d1e283f3a81bd 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -42,7 +42,7 @@ struct {{cluster.name}}Cluster : public GeneratedCluster {{cluster.name}}Cluster() : {%- for attr in cluster.attributes %} - m{{attr.definition.name | capitalcase}}(chip::CharSpan("{{attr.definition.name}}"), {{attr.definition.code}}, {{attr | getMask(cluster, idl)}}, {{attr | getRawSizeAndType(cluster, idl)}}{{attr | getInit(cluster, idl)}}){{"," if not loop.last}} + m{{attr.definition.name | capitalcase}}(chip::CharSpan("{{attr.definition.name}}"), {{attr.definition.code}}, {{attr | getMask(cluster, idl)}} | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), {{attr | getRawSizeAndType(cluster, idl)}}{{attr | getInit(cluster, idl)}}){{"," if not loop.last}} {%- endfor %} { } From 7311e554df0fe7ba8d713c7cdbcd3f6d984b73cf Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Fri, 25 Nov 2022 21:59:11 +0000 Subject: [PATCH 03/29] dynamic-bridge-app: implement generic read and write callbacks for externally stored attributes --- .../linux/include/data-model/Attribute.h | 18 ++ examples/dynamic-bridge-app/linux/main.cpp | 239 ++++++++++++------ 2 files changed, 181 insertions(+), 76 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index 66d4388df6d565..a34749b215b295 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -27,6 +27,8 @@ class AttributeInterface // Read the contents of the attribute. virtual CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) = 0; + + virtual CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer) = 0; }; // This is the base type for implementing an attribute @@ -52,6 +54,22 @@ struct Attribute : public AttributeInterface return chip::app::DataModel::Encode(aPath, aEncoder, mData); } + template>::value, bool> = true> + CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + template>::value, bool> = true> + CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) + { + return chip::app::DataModel::Encode(writer, chip::TLV::Tag(), value); + } + + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer) override + { + return ReadValue(aPath, writer, mData); + } + void operator=(const Type & value) { mData = value; } const Type & Peek() const { return mData; } diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 6ce4b0f45742e2..a684faf40d3f77 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -86,8 +86,10 @@ struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterfa CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override; CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override; - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; + CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, TLV::TLVWriter & writer); + + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath); + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful); }; CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) @@ -125,6 +127,18 @@ CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAt return c->ForwardWriteToBridge(aPath, aDecoder); } +CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, + chip::TLV::TLVWriter & writer) +{ + CommonCluster * c = FindCluster(aPath); + if (!c) + return CHIP_ERROR_NOT_IMPLEMENTED; + AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); + if (!a) + return CHIP_ERROR_NOT_IMPLEMENTED; + return a->Read(aPath, writer); +} + void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) { CommonCluster * c = FindCluster(aPath); @@ -177,6 +191,117 @@ std::unique_ptr CreateCluster(chip::ClusterId id) return nullptr; } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) { wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) { wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) { wr.Put(chip::TLV::Tag(), (float) atof(buffer)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) { wr.Put(chip::TLV::Tag(), atof(buffer)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) { wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) { wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) { wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); } + +template +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) { wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } + +void WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) +{ + if (maxReadLength == 1) + *buffer = value ? 1 : 0; +} + +template +void WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxReadLength) +{ + size_t value_size = sizeof(value); + if (maxReadLength >= value_size) + { + memcpy(buffer, &value, value_size); + } +} + +template +void WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const uint16_t & maxReadLength) +{ + T v; + chip::app::DataModel::Decode(reader, v); + WriteValueToBuffer(v, buffer, maxReadLength); +} + +// if `read` is true, read from `buffer`, and write to `data` +// otherwise, read from `data`, and write to `buffer` +template +void ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t maxReadLength, bool read) +{ + if (read) + { + chip::TLV::TLVWriter wr; + wr.Init(data->data(), data->size()); + ReadValueFromBuffer(wr, (char *)buffer, (const T *) nullptr); + wr.Finalize(); + data->resize(wr.GetLengthWritten()); + } + else + { + chip::TLV::TLVReader rd; + rd.Init(data->data(), data->size()); + rd.Next(); + WriteValueToBuffer(rd, buffer, maxReadLength); + } +} + +void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, bool read) +{ + switch (type) + { + case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: + case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: + ReadOrWriteBuffer>(data, buffer, maxReadLength, read); + break; + case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: + case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + case ZCL_STRUCT_ATTRIBUTE_TYPE: + // structs not supported yet + break; + case ZCL_SINGLE_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + case ZCL_DOUBLE_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + case ZCL_INT8S_ATTRIBUTE_TYPE: + case ZCL_INT16S_ATTRIBUTE_TYPE: + case ZCL_INT24S_ATTRIBUTE_TYPE: + case ZCL_INT32S_ATTRIBUTE_TYPE: + case ZCL_INT40S_ATTRIBUTE_TYPE: + case ZCL_INT48S_ATTRIBUTE_TYPE: + case ZCL_INT56S_ATTRIBUTE_TYPE: + case ZCL_INT64S_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + + case ZCL_INT8U_ATTRIBUTE_TYPE: + case ZCL_INT16U_ATTRIBUTE_TYPE: + case ZCL_INT24U_ATTRIBUTE_TYPE: + case ZCL_INT32U_ATTRIBUTE_TYPE: + case ZCL_INT40U_ATTRIBUTE_TYPE: + case ZCL_INT48U_ATTRIBUTE_TYPE: + case ZCL_INT56U_ATTRIBUTE_TYPE: + case ZCL_INT64U_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + + case ZCL_BOOLEAN_ATTRIBUTE_TYPE: + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + default: + // Assume integer + ReadOrWriteBuffer(data, buffer, maxReadLength, read); + break; + } +} + + bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Actions::Commands::InstantAction::DecodableType & commandData) { @@ -191,34 +316,32 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI { uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); - EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; + if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr)) + return EMBER_ZCL_STATUS_FAILURE; - if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != nullptr)) - { - DynamicDevice * dev = g_device_impls[endpointIndex].get(); - CommonCluster * cluster = nullptr; - const std::vector clusters = dev->clusters(); - int clusters_count = (int) clusters.size(); - for (int cluster_index = 0; cluster_index < clusters_count; cluster_index++) - { - if (clusters[cluster_index]->GetClusterId() == clusterId) - { - cluster = clusters[cluster_index]; - break; - } - } + chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId); - if (cluster == nullptr) return ret; + if (accessInterface == nullptr) + return EMBER_ZCL_STATUS_FAILURE; - AttributeInterface * attribute = cluster->FindAttribute(attributeMetadata->attributeId); + std::vector data(attributeMetadata->size + 64); - if (clusterId == ZCL_ON_OFF_CLUSTER_ID) - { - ret = HandleReadOnOffAttribute(static_cast *>(attribute), buffer, maxReadLength); - } - } + // read the attribute and write it to `data` + chip::TLV::TLVWriter writer; + writer.Init(data.data(), data.size()); + CHIP_ERROR err = static_cast(accessInterface)->Read( + chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), + writer + ); + if (err != CHIP_NO_ERROR) + return EMBER_ZCL_STATUS_FAILURE; + writer.Finalize(); + data.resize(writer.GetLengthWritten()); - return ret; + // read from `data` and write to `buffer` + ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, maxReadLength, false); + + return EMBER_ZCL_STATUS_SUCCESS; } EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, @@ -226,67 +349,31 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster { uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); - EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; - - if ((endpointIndex < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) && (gDevices[endpointIndex] != nullptr)) - { - DynamicDevice * dev = g_device_impls[endpointIndex].get(); - CommonCluster * cluster = nullptr; - const std::vector clusters = dev->clusters(); - int clusters_count = (int) clusters.size(); - for (int cluster_index = 0; cluster_index < clusters_count; cluster_index++) - { - if (clusters[cluster_index]->GetClusterId() == clusterId) - { - cluster = clusters[cluster_index]; - break; - } - } + if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr)) + return EMBER_ZCL_STATUS_FAILURE; - if (cluster == nullptr) return ret; + chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId); - AttributeInterface * attribute = cluster->FindAttribute(attributeMetadata->attributeId); + if (accessInterface == nullptr) + return EMBER_ZCL_STATUS_FAILURE; - if (clusterId == ZCL_ON_OFF_CLUSTER_ID) - { - ret = HandleWriteOnOffAttribute(static_cast *>(attribute), buffer); - } - } + std::vector data(attributeMetadata->size + 64); - return ret; -} + // read from `buffer` and write to `data` + ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, 0, true); -EmberAfStatus HandleReadOnOffAttribute(Attribute * attribute, uint8_t * buffer, uint16_t maxReadLength) -{ - if ((attribute->GetId() == ZCL_ON_OFF_ATTRIBUTE_ID) && (maxReadLength == 1)) - { - *buffer = attribute->Peek() ? 1 : 0; - } - else if ((attribute->GetId() == ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID) && (maxReadLength == 2)) - { - *buffer = (uint16_t) ZCL_ON_OFF_CLUSTER_REVISION; - } - else - { + // read from `data` and write to attribute + chip::TLV::TLVReader reader; + reader.Init(data.data(), data.size()); + reader.Next(); + chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); + CHIP_ERROR err = accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); + if (err != CHIP_NO_ERROR) return EMBER_ZCL_STATUS_FAILURE; - } return EMBER_ZCL_STATUS_SUCCESS; } -EmberAfStatus HandleWriteOnOffAttribute(Attribute * attribute, uint8_t * buffer) -{ - if (attribute->GetId() == ZCL_ON_OFF_ATTRIBUTE_ID) - { - *attribute = (*buffer) == 1; - } - else - { - return EMBER_ZCL_STATUS_FAILURE; - } - return EMBER_ZCL_STATUS_SUCCESS; -} - Device * FindDeviceEndpoint(chip::EndpointId id) { for (auto dev : gDevices) From e0ac5a32337c34a68cd8edac71411036499e34bb Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Thu, 1 Dec 2022 16:00:05 +0000 Subject: [PATCH 04/29] Update bridge idl tests to include external storage flags --- .../cluster_struct_attribute/bridge/DemoClusterServer.h | 4 ++-- .../global_struct_attribute/bridge/DemoClusterServer.h | 4 ++-- .../idl/tests/outputs/several_clusters/bridge/FirstServer.h | 2 +- .../idl/tests/outputs/several_clusters/bridge/SecondServer.h | 2 +- scripts/idl/tests/outputs/several_clusters/bridge/Third.h | 4 ++-- .../idl/tests/outputs/several_clusters/bridge/ThirdServer.h | 4 ++-- .../tests/outputs/simple_attribute/bridge/MyClusterServer.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h index bdf2488396763a..0350cb8e9bc9f4 100644 --- a/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h +++ b/scripts/idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h @@ -8,8 +8,8 @@ struct DemoClusterCluster : public GeneratedCluster { DemoClusterCluster() : - mSingleFailSafe(chip::CharSpan("singleFailSafe"), 5, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)), - mArmFailsafes(chip::CharSpan("armFailsafes"), 100, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)) + mSingleFailSafe(chip::CharSpan("singleFailSafe"), 5, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)), + mArmFailsafes(chip::CharSpan("armFailsafes"), 100, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(ArmFailSafeRequest)) { } diff --git a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h index 78f7e89c33aaf9..f0cf41365f3fa2 100644 --- a/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h +++ b/scripts/idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h @@ -8,8 +8,8 @@ struct DemoClusterCluster : public GeneratedCluster { DemoClusterCluster() : - mSingleLabel(chip::CharSpan("singleLabel"), 32, ATTRIBUTE_MASK_WRITABLE, ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct)), - mSomeLabels(chip::CharSpan("someLabels"), 33, ATTRIBUTE_MASK_WRITABLE, ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct)) + mSingleLabel(chip::CharSpan("singleLabel"), 32, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_STRUCT_ATTRIBUTE_TYPE, sizeof(LabelStruct)), + mSomeLabels(chip::CharSpan("someLabels"), 33, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_ARRAY_ATTRIBUTE_TYPE, sizeof(LabelStruct)) { } diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/FirstServer.h b/scripts/idl/tests/outputs/several_clusters/bridge/FirstServer.h index c5d0ede099ddec..6d90a693779dfa 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/FirstServer.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/FirstServer.h @@ -8,7 +8,7 @@ struct FirstCluster : public GeneratedCluster { FirstCluster() : - mSomeInteger(chip::CharSpan("someInteger"), 1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2) + mSomeInteger(chip::CharSpan("someInteger"), 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2) { } diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/SecondServer.h b/scripts/idl/tests/outputs/several_clusters/bridge/SecondServer.h index e80573cf55b5cc..41f7f74660945b 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/SecondServer.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/SecondServer.h @@ -8,7 +8,7 @@ struct SecondCluster : public GeneratedCluster { SecondCluster() : - mSomeBytes(chip::CharSpan("someBytes"), 123, 0, ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32) + mSomeBytes(chip::CharSpan("someBytes"), 123, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_OCTET_STRING_ATTRIBUTE_TYPE, 32) { } diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h index 48e8c4537e4799..47f4551754277b 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/Third.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/Third.h @@ -8,8 +8,8 @@ struct ThirdCluster : public GeneratedCluster { ThirdCluster() : - mSomeEnum(chip::CharSpan("someEnum"), 10, ATTRIBUTE_MASK_WRITABLE, ZCL_ENUM8_ATTRIBUTE_TYPE, 1), - mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0, ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_THIRD_CLUSTER_REVISION) + mSomeEnum(chip::CharSpan("someEnum"), 10, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_ENUM8_ATTRIBUTE_TYPE, 1), + mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_THIRD_CLUSTER_REVISION) { } diff --git a/scripts/idl/tests/outputs/several_clusters/bridge/ThirdServer.h b/scripts/idl/tests/outputs/several_clusters/bridge/ThirdServer.h index 6f52806e477a89..bdc0cce18066f8 100644 --- a/scripts/idl/tests/outputs/several_clusters/bridge/ThirdServer.h +++ b/scripts/idl/tests/outputs/several_clusters/bridge/ThirdServer.h @@ -8,8 +8,8 @@ struct ThirdCluster : public GeneratedCluster { ThirdCluster() : - mSomeEnum(chip::CharSpan("someEnum"), 10, ATTRIBUTE_MASK_WRITABLE, ZCL_ENUM8_ATTRIBUTE_TYPE, 1), - mOptions(chip::CharSpan("options"), 20, ATTRIBUTE_MASK_WRITABLE, ZCL_BITMAP8_ATTRIBUTE_TYPE, 1) + mSomeEnum(chip::CharSpan("someEnum"), 10, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_ENUM8_ATTRIBUTE_TYPE, 1), + mOptions(chip::CharSpan("options"), 20, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP8_ATTRIBUTE_TYPE, 1) { } diff --git a/scripts/idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h b/scripts/idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h index 96c233b1a356de..0c9fd7abb4a93f 100644 --- a/scripts/idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h +++ b/scripts/idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h @@ -8,7 +8,7 @@ struct MyClusterCluster : public GeneratedCluster { MyClusterCluster() : - mClusterAttr(chip::CharSpan("clusterAttr"), 1, ATTRIBUTE_MASK_WRITABLE, ZCL_INT16U_ATTRIBUTE_TYPE, 2) + mClusterAttr(chip::CharSpan("clusterAttr"), 1, ATTRIBUTE_MASK_WRITABLE | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2) { } From 046d372e120fabdc7df8b7cc7ad47c29d7bddfc4 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Thu, 1 Dec 2022 16:05:12 +0000 Subject: [PATCH 05/29] Restyled by clang-format --- .../linux/UserInputBackend.cpp | 3 +- .../linux/include/GeneratedClusters.h | 10 +-- .../linux/include/data-model/Attribute.h | 4 +- examples/dynamic-bridge-app/linux/main.cpp | 68 ++++++++++++------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp index ccd7f9524bc056..03d6023d5f8864 100644 --- a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp +++ b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp @@ -120,7 +120,8 @@ void AddCluster(const std::vector & tokens) auto c = CreateCluster(cluster_name.c_str()); if (c) { - g_pending->AddCluster(std::make_unique(std::move(c), c->GetIncomingCommandList(), c->GetOutgoingCommandList())); + g_pending->AddCluster( + std::make_unique(std::move(c), c->GetIncomingCommandList(), c->GetOutgoingCommandList())); } else { diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 3f92bed6b02b35..b0116086f669ae 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -25,12 +25,6 @@ class GeneratedCluster // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; - virtual chip::CommandId * GetIncomingCommandList() - { - return nullptr; - } - virtual chip::CommandId * GetOutgoingCommandList() - { - return nullptr; - }; + virtual chip::CommandId * GetIncomingCommandList() { return nullptr; } + virtual chip::CommandId * GetOutgoingCommandList() { return nullptr; }; }; diff --git a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index a34749b215b295..4238162c1bd810 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -54,12 +54,12 @@ struct Attribute : public AttributeInterface return chip::app::DataModel::Encode(aPath, aEncoder, mData); } - template>::value, bool> = true> + template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { return CHIP_ERROR_NOT_IMPLEMENTED; } - template>::value, bool> = true> + template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { return chip::app::DataModel::Encode(writer, chip::TLV::Tag(), value); diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 63651eca34ba05..84db6904a344ed 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -126,8 +126,7 @@ CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAt return c->ForwardWriteToBridge(aPath, aDecoder); } -CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, - chip::TLV::TLVWriter & writer) +CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer) { CommonCluster * c = FindCluster(aPath); if (!c) @@ -190,16 +189,40 @@ std::unique_ptr CreateCluster(chip::ClusterId id) return nullptr; } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) { wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) { wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) { wr.Put(chip::TLV::Tag(), (float) atof(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) { wr.Put(chip::TLV::Tag(), atof(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) { wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) { wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) { wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); } +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) +{ + wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) +{ + wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) +{ + wr.Put(chip::TLV::Tag(), (float) atof(buffer)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) +{ + wr.Put(chip::TLV::Tag(), atof(buffer)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) +{ + wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) +{ + wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); +} +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) +{ + wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); +} -template -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) { wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } +template +void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) +{ + wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); +} void WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) { @@ -207,7 +230,7 @@ void WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & m *buffer = value ? 1 : 0; } -template +template void WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxReadLength) { size_t value_size = sizeof(value); @@ -217,7 +240,7 @@ void WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxR } } -template +template void WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const uint16_t & maxReadLength) { T v; @@ -227,14 +250,14 @@ void WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const u // if `read` is true, read from `buffer`, and write to `data` // otherwise, read from `data`, and write to `buffer` -template +template void ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t maxReadLength, bool read) { if (read) { chip::TLV::TLVWriter wr; wr.Init(data->data(), data->size()); - ReadValueFromBuffer(wr, (char *)buffer, (const T *) nullptr); + ReadValueFromBuffer(wr, (char *) buffer, (const T *) nullptr); wr.Finalize(); data->resize(wr.GetLengthWritten()); } @@ -247,7 +270,8 @@ void ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t m } } -void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, bool read) +void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, + bool read) { switch (type) { @@ -300,7 +324,6 @@ void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, Emb } } - bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Actions::Commands::InstantAction::DecodableType & commandData) { @@ -328,10 +351,8 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI // read the attribute and write it to `data` chip::TLV::TLVWriter writer; writer.Init(data.data(), data.size()); - CHIP_ERROR err = static_cast(accessInterface)->Read( - chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), - writer - ); + CHIP_ERROR err = static_cast(accessInterface) + ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer); if (err != CHIP_NO_ERROR) return EMBER_ZCL_STATUS_FAILURE; writer.Finalize(); @@ -344,7 +365,7 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI } EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, - const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer) + const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer) { uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); @@ -366,7 +387,8 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster reader.Init(data.data(), data.size()); reader.Next(); chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); - CHIP_ERROR err = accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); + CHIP_ERROR err = + accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); if (err != CHIP_NO_ERROR) return EMBER_ZCL_STATUS_FAILURE; From c67e2a5b05b8a5d8e64aa31253ce31d91dd3b2ea Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 12 Dec 2022 17:39:15 +0000 Subject: [PATCH 06/29] Document the data buffer padding size used when reading/writing external attributes --- examples/dynamic-bridge-app/linux/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 84db6904a344ed..953a3aaa5aea6e 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -346,6 +346,8 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI if (accessInterface == nullptr) return EMBER_ZCL_STATUS_FAILURE; + // adding 64 bytes as padding to include the staging buffer used by + // TLVWriter, which is 17 bytes std::vector data(attributeMetadata->size + 64); // read the attribute and write it to `data` @@ -377,6 +379,8 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster if (accessInterface == nullptr) return EMBER_ZCL_STATUS_FAILURE; + // adding 64 bytes as padding to include the staging buffer used by + // TLVWriter, which is 17 bytes std::vector data(attributeMetadata->size + 64); // read from `buffer` and write to `data` From 37ff98112ffb2b2d0dd795ad089f2311d6a417ab Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 12 Dec 2022 23:34:51 +0000 Subject: [PATCH 07/29] Add better error handling for attribute read/write overrides in dynamic-bridge-app --- examples/dynamic-bridge-app/linux/main.cpp | 159 +++++++++++++-------- 1 file changed, 102 insertions(+), 57 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 953a3aaa5aea6e..c51ec7873a3482 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -110,10 +110,10 @@ CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAtt { CommonCluster * c = FindCluster(aPath); if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; + return CHIP_ERROR_NOT_FOUND; AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (!a) - return CHIP_ERROR_NOT_IMPLEMENTED; + return CHIP_ERROR_NOT_FOUND; return a->Read(aPath, aEncoder); } @@ -122,7 +122,7 @@ CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAt { CommonCluster * c = FindCluster(aPath); if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; + return CHIP_ERROR_NOT_FOUND; return c->ForwardWriteToBridge(aPath, aDecoder); } @@ -130,10 +130,10 @@ CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAtt { CommonCluster * c = FindCluster(aPath); if (!c) - return CHIP_ERROR_NOT_IMPLEMENTED; + return CHIP_ERROR_NOT_FOUND; AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (!a) - return CHIP_ERROR_NOT_IMPLEMENTED; + return CHIP_ERROR_NOT_FOUND; return a->Read(aPath, writer); } @@ -189,75 +189,86 @@ std::unique_ptr CreateCluster(chip::ClusterId id) return nullptr; } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) { - wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); + return wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) { - wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); + return wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) { - wr.Put(chip::TLV::Tag(), (float) atof(buffer)); + return wr.Put(chip::TLV::Tag(), (float) atof(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) { - wr.Put(chip::TLV::Tag(), atof(buffer)); + return wr.Put(chip::TLV::Tag(), atof(buffer)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) { - wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); + return wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) { - wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); + return wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); } -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) { - wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); + return wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); } template -void ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) { - wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); + return wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } -void WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) { - if (maxReadLength == 1) - *buffer = value ? 1 : 0; + if (maxReadLength != 1) + { + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + *buffer = value ? 1 : 0; + return CHIP_NO_ERROR; } template -void WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxReadLength) { size_t value_size = sizeof(value); - if (maxReadLength >= value_size) + if (maxReadLength < value_size) { - memcpy(buffer, &value, value_size); + return CHIP_ERROR_BUFFER_TOO_SMALL; } + memcpy(buffer, &value, value_size); + return CHIP_NO_ERROR; } template -void WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const uint16_t & maxReadLength) { T v; - chip::app::DataModel::Decode(reader, v); - WriteValueToBuffer(v, buffer, maxReadLength); + CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); + if (err != CHIP_NO_ERROR) + { + return err; + } + return WriteValueToBuffer(v, buffer, maxReadLength); } // if `read` is true, read from `buffer`, and write to `data` // otherwise, read from `data`, and write to `buffer` template -void ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t maxReadLength, bool read) +CHIP_ERROR ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t maxReadLength, bool read) { + CHIP_ERROR err; if (read) { chip::TLV::TLVWriter wr; wr.Init(data->data(), data->size()); - ReadValueFromBuffer(wr, (char *) buffer, (const T *) nullptr); + err = ReadValueFromBuffer(wr, (char *) buffer, (const T *) nullptr); wr.Finalize(); data->resize(wr.GetLengthWritten()); } @@ -266,32 +277,29 @@ void ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t m chip::TLV::TLVReader rd; rd.Init(data->data(), data->size()); rd.Next(); - WriteValueToBuffer(rd, buffer, maxReadLength); + err = WriteValueToBuffer(rd, buffer, maxReadLength); } + return err; } -void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, +CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, bool read) { switch (type) { case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: - ReadOrWriteBuffer>(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer>(data, buffer, maxReadLength, read); case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_STRUCT_ATTRIBUTE_TYPE: // structs not supported yet - break; + return CHIP_ERROR_NOT_IMPLEMENTED; case ZCL_SINGLE_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_DOUBLE_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_INT8S_ATTRIBUTE_TYPE: case ZCL_INT16S_ATTRIBUTE_TYPE: case ZCL_INT24S_ATTRIBUTE_TYPE: @@ -300,9 +308,7 @@ void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, Emb case ZCL_INT48S_ATTRIBUTE_TYPE: case ZCL_INT56S_ATTRIBUTE_TYPE: case ZCL_INT64S_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; - + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_INT8U_ATTRIBUTE_TYPE: case ZCL_INT16U_ATTRIBUTE_TYPE: case ZCL_INT24U_ATTRIBUTE_TYPE: @@ -311,16 +317,12 @@ void ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, Emb case ZCL_INT48U_ATTRIBUTE_TYPE: case ZCL_INT56U_ATTRIBUTE_TYPE: case ZCL_INT64U_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; - + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_BOOLEAN_ATTRIBUTE_TYPE: - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); default: // Assume integer - ReadOrWriteBuffer(data, buffer, maxReadLength, read); - break; + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); } } @@ -332,6 +334,17 @@ bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj return true; } +void printChipError(CHIP_ERROR err) +{ + char errorStr[160]; + bool errorStrFound = FormatCHIPError(errorStr, sizeof(errorStr), err); + if (!errorStrFound) + { + errorStr[0] = 0; + } + ChipLogError(DeviceLayer, "%s", errorStr); +} + EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, uint16_t maxReadLength) @@ -339,12 +352,18 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr)) - return EMBER_ZCL_STATUS_FAILURE; + { + ChipLogError(DeviceLayer, "Could not find dynamic endpoint: %d", endpoint); + return EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT; + } chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId); if (accessInterface == nullptr) + { + ChipLogError(DeviceLayer, "Cluster %d has no attribute access override", clusterId); return EMBER_ZCL_STATUS_FAILURE; + } // adding 64 bytes as padding to include the staging buffer used by // TLVWriter, which is 17 bytes @@ -356,12 +375,22 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI CHIP_ERROR err = static_cast(accessInterface) ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer); if (err != CHIP_NO_ERROR) + { + printChipError(err); + ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d", attributeMetadata->attributeId, endpoint, clusterId); return EMBER_ZCL_STATUS_FAILURE; + } writer.Finalize(); data.resize(writer.GetLengthWritten()); // read from `data` and write to `buffer` - ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, maxReadLength, false); + err = ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, maxReadLength, false); + if (err != CHIP_NO_ERROR) + { + printChipError(err); + ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); + return EMBER_ZCL_STATUS_FAILURE; + } return EMBER_ZCL_STATUS_SUCCESS; } @@ -372,29 +401,45 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); if ((endpointIndex >= CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) || (gDevices[endpointIndex] == nullptr)) + { + ChipLogError(DeviceLayer, "Could not find dynamic endpoint: %d", endpoint); return EMBER_ZCL_STATUS_FAILURE; + } chip::app::AttributeAccessInterface * accessInterface = chip::app::GetAttributeAccessOverride(endpoint, clusterId); if (accessInterface == nullptr) + { + ChipLogError(DeviceLayer, "Cluster %d has no attribute access override", clusterId); return EMBER_ZCL_STATUS_FAILURE; + } // adding 64 bytes as padding to include the staging buffer used by // TLVWriter, which is 17 bytes std::vector data(attributeMetadata->size + 64); // read from `buffer` and write to `data` - ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, 0, true); + CHIP_ERROR err = ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, 0, true); + if (err != CHIP_NO_ERROR) + { + printChipError(err); + ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); + return EMBER_ZCL_STATUS_FAILURE; + } // read from `data` and write to attribute chip::TLV::TLVReader reader; reader.Init(data.data(), data.size()); reader.Next(); chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); - CHIP_ERROR err = + err = accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); if (err != CHIP_NO_ERROR) + { + printChipError(err); + ChipLogError(DeviceLayer, "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; + } return EMBER_ZCL_STATUS_SUCCESS; } From ca682277081ab63173ec60450eae6fc8b73b986f Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Tue, 13 Dec 2022 01:25:35 +0000 Subject: [PATCH 08/29] Allow bitmap32 attribute reads for dynamic clusters in dynamic-bridge-app --- examples/dynamic-bridge-app/linux/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index c51ec7873a3482..f06720b8b86681 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -209,6 +209,10 @@ CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, c { return wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); } +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint32_t *) +{ + return wr.Put(chip::TLV::Tag(), (uint32_t) strtoll(buffer, nullptr, 10)); +} CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) { return wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); @@ -320,6 +324,8 @@ CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffe return ReadOrWriteBuffer(data, buffer, maxReadLength, read); case ZCL_BOOLEAN_ATTRIBUTE_TYPE: return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + case ZCL_BITMAP32_ATTRIBUTE_TYPE: + return ReadOrWriteBuffer(data, buffer, maxReadLength, read); default: // Assume integer return ReadOrWriteBuffer(data, buffer, maxReadLength, read); From fd91c1f83b068086da3bd8d9799886a9ca340568 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 15:00:34 +0000 Subject: [PATCH 09/29] Adjust indentation in BridgeClustersCpp.jinja --- scripts/idl/generators/bridge/BridgeClustersCpp.jinja | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 7d1e283f3a81bd..7543a0729be01a 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -59,7 +59,7 @@ struct {{cluster.name}}Cluster : public GeneratedCluster }); } - {%- if cluster.commands | length > 0 %} +{%- if cluster.commands | length > 0 %} chip::CommandId incomingCommandList[{{cluster.commands | length + 1}}] = { {%- for command in cluster.commands %} {{command.code}}, @@ -71,7 +71,7 @@ struct {{cluster.name}}Cluster : public GeneratedCluster { return incomingCommandList; } - {%- endif %} +{%- endif %} {% for attr in cluster.attributes %} {{"List" if attr.definition.is_list}}Attribute<{{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}; From 7ea7e8b4d43f0c6b9463d06f25af2fdbeb2428f5 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 16:12:37 +0000 Subject: [PATCH 10/29] Change the incoming command list for generated clusters to static --- .../generators/bridge/BridgeClustersCpp.jinja | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 7543a0729be01a..0021af25897dff 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -59,23 +59,31 @@ struct {{cluster.name}}Cluster : public GeneratedCluster }); } -{%- if cluster.commands | length > 0 %} - chip::CommandId incomingCommandList[{{cluster.commands | length + 1}}] = { - {%- for command in cluster.commands %} - {{command.code}}, - {%- endfor %} - chip::kInvalidCommandId - }; +{% for attr in cluster.attributes %} + {{"List" if attr.definition.is_list}}Attribute<{{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}; +{%- endfor %} +{%- if cluster.commands | length > 0 %} + static chip::CommandId incomingCommandList[]; chip::CommandId * GetIncomingCommandList() override { return incomingCommandList; } {%- endif %} -{% for attr in cluster.attributes %} - {{"List" if attr.definition.is_list}}Attribute<{{attr | getType(cluster, idl)}}> m{{attr.definition.name | capitalcase}}; -{%- endfor %} }; + +#ifndef {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS +#define {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS +{%- if cluster.commands | length > 0 %} + chip::CommandId {{cluster.name}}Cluster::incomingCommandList[] = { + {%- for command in cluster.commands %} + {{command.code}}, + {%- endfor %} + chip::kInvalidCommandId + }; +{%- endif %} +#endif + } From c8cc3c96a20b2dd3ff75b4ba90a898ed6c7898d4 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 16:22:35 +0000 Subject: [PATCH 11/29] Change the incoming command list for generated clusters to const --- .../dynamic-bridge-app/linux/include/GeneratedClusters.h | 4 ++-- scripts/idl/generators/bridge/BridgeClustersCpp.jinja | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index b0116086f669ae..14ee0f6de45789 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -25,6 +25,6 @@ class GeneratedCluster // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; - virtual chip::CommandId * GetIncomingCommandList() { return nullptr; } - virtual chip::CommandId * GetOutgoingCommandList() { return nullptr; }; + virtual const chip::CommandId * GetIncomingCommandList() { return nullptr; } + virtual const chip::CommandId * GetOutgoingCommandList() { return nullptr; }; }; diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 0021af25897dff..7e5f8c205163ef 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -64,8 +64,8 @@ struct {{cluster.name}}Cluster : public GeneratedCluster {%- endfor %} {%- if cluster.commands | length > 0 %} - static chip::CommandId incomingCommandList[]; - chip::CommandId * GetIncomingCommandList() override + static const chip::CommandId incomingCommandList[]; + const chip::CommandId * GetIncomingCommandList() override { return incomingCommandList; } @@ -77,7 +77,7 @@ struct {{cluster.name}}Cluster : public GeneratedCluster #ifndef {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS #define {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS {%- if cluster.commands | length > 0 %} - chip::CommandId {{cluster.name}}Cluster::incomingCommandList[] = { + const chip::CommandId {{cluster.name}}Cluster::incomingCommandList[] = { {%- for command in cluster.commands %} {{command.code}}, {%- endfor %} From f34dd3f40938ebfd6795b400f9a3ea7dfe9fd9cf Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 17:04:33 +0000 Subject: [PATCH 12/29] Rename incomingCommandList to mIncomingCommandList for generated clusters in dynamic-bridge-app --- scripts/idl/generators/bridge/BridgeClustersCpp.jinja | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 7e5f8c205163ef..8e54e01f8c679e 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -64,10 +64,10 @@ struct {{cluster.name}}Cluster : public GeneratedCluster {%- endfor %} {%- if cluster.commands | length > 0 %} - static const chip::CommandId incomingCommandList[]; + static const chip::CommandId mIncomingCommandList[]; const chip::CommandId * GetIncomingCommandList() override { - return incomingCommandList; + return mIncomingCommandList; } {%- endif %} @@ -77,7 +77,7 @@ struct {{cluster.name}}Cluster : public GeneratedCluster #ifndef {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS #define {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS {%- if cluster.commands | length > 0 %} - const chip::CommandId {{cluster.name}}Cluster::incomingCommandList[] = { + const chip::CommandId {{cluster.name}}Cluster::mIncomingCommandList[] = { {%- for command in cluster.commands %} {{command.code}}, {%- endfor %} From b13861cfd7130f40d06ac24b54c5decda897eaaf Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 18:24:08 +0000 Subject: [PATCH 13/29] add a test for bridge generated cluster headers --- .../generators/bridge/BridgeClustersCpp.jinja | 18 +++---- scripts/idl/tests/available_tests.yaml | 5 ++ .../tests/inputs/cluster_with_commands.matter | 44 +++++++++++++++++ .../bridge/BridgeClustersImpl.h | 26 ++++++++++ .../bridge/BridgeGlobalStructs.h | 13 +++++ .../cluster_with_commands/bridge/OnOff.h | 49 +++++++++++++++++++ 6 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 scripts/idl/tests/inputs/cluster_with_commands.matter create mode 100644 scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h create mode 100644 scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h create mode 100644 scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h diff --git a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja index 8e54e01f8c679e..0dc53754cd8bdd 100644 --- a/scripts/idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/idl/generators/bridge/BridgeClustersCpp.jinja @@ -70,20 +70,18 @@ struct {{cluster.name}}Cluster : public GeneratedCluster return mIncomingCommandList; } {%- endif %} - }; - +{%- if cluster.commands | length > 0 %} #ifndef {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS #define {{cluster.name | constcase}}_CLUSTER_INCOMING_COMMANDS -{%- if cluster.commands | length > 0 %} - const chip::CommandId {{cluster.name}}Cluster::mIncomingCommandList[] = { - {%- for command in cluster.commands %} - {{command.code}}, - {%- endfor %} - chip::kInvalidCommandId - }; -{%- endif %} +const chip::CommandId {{cluster.name}}Cluster::mIncomingCommandList[] = { +{%- for command in cluster.commands %} + {{command.code}}, +{%- endfor %} + chip::kInvalidCommandId +}; #endif +{%- endif %} } diff --git a/scripts/idl/tests/available_tests.yaml b/scripts/idl/tests/available_tests.yaml index bd5311ab050c48..a4e2c6778b5f95 100644 --- a/scripts/idl/tests/available_tests.yaml +++ b/scripts/idl/tests/available_tests.yaml @@ -59,6 +59,11 @@ bridge: bridge/ThirdServer.h: outputs/several_clusters/bridge/ThirdServer.h bridge/Third.h: outputs/several_clusters/bridge/Third.h + inputs/cluster_with_commands.matter: + bridge/BridgeClustersImpl.h: outputs/cluster_with_commands/bridge/BridgeClustersImpl.h + bridge/BridgeGlobalStructs.h: outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h + bridge/OnOff.h: outputs/cluster_with_commands/bridge/OnOff.h + cpp-app: inputs/several_clusters.matter: app/PluginApplicationCallbacks.h: outputs/several_clusters/cpp-app/PluginApplicationCallbacks.h diff --git a/scripts/idl/tests/inputs/cluster_with_commands.matter b/scripts/idl/tests/inputs/cluster_with_commands.matter new file mode 100644 index 00000000000000..c6128be7ffd870 --- /dev/null +++ b/scripts/idl/tests/inputs/cluster_with_commands.matter @@ -0,0 +1,44 @@ + +server cluster OnOff = 6 { + enum OnOffDelayedAllOffEffectVariant : ENUM8 { + kFadeToOffIn0p8Seconds = 0; + kNoFade = 1; + k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds = 2; + } + + enum OnOffDyingLightEffectVariant : ENUM8 { + k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second = 0; + } + + enum OnOffEffectIdentifier : ENUM8 { + kDelayedAllOff = 0; + kDyingLight = 1; + } + + enum OnOffStartUpOnOff : ENUM8 { + kOff = 0; + kOn = 1; + kTogglePreviousOnOff = 2; + } + + bitmap OnOffControl : BITMAP8 { + kAcceptOnlyWhenOn = 0x1; + } + + bitmap OnOffFeature : BITMAP32 { + kLighting = 0x1; + } + + bitmap SceneFeatures : BITMAP32 { + kSceneNames = 0x1; + } + + readonly attribute boolean onOff = 0; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command Off(): DefaultSuccess = 0; + command On(): DefaultSuccess = 1; + command Toggle(): DefaultSuccess = 2; +} + diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h new file mode 100644 index 00000000000000..0484909c914739 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "bridge/OnOff.h" + +namespace clusters { + +struct ClusterInfo +{ + chip::ClusterId id; + const char *name; + uint16_t size; + GeneratedCluster* (*ctor)(void*); +} static const kKnownClusters[] = { + + { + 6, + "OnOff", + sizeof(OnOffCluster), + [](void *mem) -> GeneratedCluster* { + return new(mem) OnOffCluster(); + }, + }, +}; + +} diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h new file mode 100644 index 00000000000000..3b56a6f868b109 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#include +#include + +namespace clusters { + + + +} diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h new file mode 100644 index 00000000000000..cc788958dad0d4 --- /dev/null +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h @@ -0,0 +1,49 @@ +#pragma once + +#include "BridgeGlobalStructs.h" +#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" + +namespace clusters { +struct OnOffCluster : public GeneratedCluster +{ + + OnOffCluster() : + mOnOff(chip::CharSpan("onOff"), 0, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1), + mFeatureMap(chip::CharSpan("featureMap"), 65532, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP32_ATTRIBUTE_TYPE, 4), + mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_ON_OFF_CLUSTER_REVISION) + { + } + + static constexpr uint32_t kClusterId =6; + chip::ClusterId GetClusterId() override { return kClusterId; } + + std::vector GetAttributes() override + { + return std::vector({ + static_cast(&mOnOff), + static_cast(&mFeatureMap), + static_cast(&mClusterRevision), + }); + } + + + Attribute mOnOff; + Attribute mFeatureMap; + Attribute mClusterRevision; + static const chip::CommandId mIncomingCommandList[]; + const chip::CommandId * GetIncomingCommandList() override + { + return mIncomingCommandList; + } +}; +#ifndef ON_OFF_CLUSTER_INCOMING_COMMANDS +#define ON_OFF_CLUSTER_INCOMING_COMMANDS +const chip::CommandId OnOffCluster::mIncomingCommandList[] = { + 0, + 1, + 2, + chip::kInvalidCommandId +}; +#endif + +} From 52d72b12fb91d58ad591d9edcb99f6c123e09c74 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 19 Dec 2022 18:49:09 +0000 Subject: [PATCH 14/29] Restyle one line if statements in dynamic-bridge-app main.cpp --- examples/dynamic-bridge-app/linux/main.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index f06720b8b86681..06f5255aebeba7 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -99,7 +99,9 @@ CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::Con for (auto c : dev->clusters()) { if (c->GetClusterId() == path.mClusterId) + { return static_cast(c); + } } } return nullptr; @@ -110,10 +112,14 @@ CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAtt { CommonCluster * c = FindCluster(aPath); if (!c) + { return CHIP_ERROR_NOT_FOUND; + } AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (!a) + { return CHIP_ERROR_NOT_FOUND; + } return a->Read(aPath, aEncoder); } @@ -122,7 +128,9 @@ CHIP_ERROR CommonAttributeAccessInterface::Write(const chip::app::ConcreteDataAt { CommonCluster * c = FindCluster(aPath); if (!c) + { return CHIP_ERROR_NOT_FOUND; + } return c->ForwardWriteToBridge(aPath, aDecoder); } @@ -130,10 +138,14 @@ CHIP_ERROR CommonAttributeAccessInterface::Read(const chip::app::ConcreteReadAtt { CommonCluster * c = FindCluster(aPath); if (!c) + { return CHIP_ERROR_NOT_FOUND; + } AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (!a) + { return CHIP_ERROR_NOT_FOUND; + } return a->Read(aPath, writer); } @@ -144,7 +156,9 @@ void CommonAttributeAccessInterface::OnListWriteBegin(const chip::app::ConcreteA { AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (a) + { a->ListWriteBegin(aPath); + } } } @@ -155,7 +169,9 @@ void CommonAttributeAccessInterface::OnListWriteEnd(const chip::app::ConcreteAtt { AttributeInterface * a = c->FindAttribute(aPath.mAttributeId); if (a) + { a->ListWriteEnd(aPath, aWriteWasSuccessful); + } } } @@ -455,7 +471,9 @@ Device * FindDeviceEndpoint(chip::EndpointId id) for (auto dev : gDevices) { if (dev && dev->GetEndpointId() == id) + { return dev; + } } return nullptr; } @@ -527,7 +545,9 @@ Room * FindRoom(const std::string & name) for (auto & room : gRooms) { if (room.GetName() == name) + { return &room; + } } return nullptr; } From 42661f626408834ef130441ce658c9b021ff1e02 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Thu, 5 Jan 2023 19:22:14 +0000 Subject: [PATCH 15/29] dynamic-bridge-app: change buffer read logic to assume byte arrays --- examples/dynamic-bridge-app/linux/main.cpp | 40 +++++----------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 06f5255aebeba7..df42544bf1a95d 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -205,43 +205,19 @@ std::unique_ptr CreateCluster(chip::ClusterId id) return nullptr; } -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const Span *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const Span & v) { - return wr.PutString(chip::TLV::Tag(), buffer, (uint32_t) strlen(buffer)); + return wr.PutString(chip::TLV::Tag(), v); } -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const ByteSpan *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const bool & v) { - return wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) buffer, (uint32_t) strlen(buffer)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const float *) -{ - return wr.Put(chip::TLV::Tag(), (float) atof(buffer)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const double *) -{ - return wr.Put(chip::TLV::Tag(), atof(buffer)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const int64_t *) -{ - return wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint32_t *) -{ - return wr.Put(chip::TLV::Tag(), (uint32_t) strtoll(buffer, nullptr, 10)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const uint64_t *) -{ - return wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(buffer, nullptr, 10)); -} -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const bool *) -{ - return wr.PutBoolean(chip::TLV::Tag(), (*buffer) ? true : false); + return wr.PutBoolean(chip::TLV::Tag(), v); } template -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const char * buffer, const T *) +CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const T & v) { - return wr.Put(chip::TLV::Tag(), (int64_t) strtoll(buffer, nullptr, 10)); + return wr.Put(chip::TLV::Tag(), v); } CHIP_ERROR WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) @@ -288,7 +264,9 @@ CHIP_ERROR ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint { chip::TLV::TLVWriter wr; wr.Init(data->data(), data->size()); - err = ReadValueFromBuffer(wr, (char *) buffer, (const T *) nullptr); + T value; + memcpy(&value, buffer, sizeof(T)); + err = ReadValueFromBuffer(wr, value); wr.Finalize(); data->resize(wr.GetLengthWritten()); } From 0941696937b41fa69a16a33e94aac48e15870b4e Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 9 Jan 2023 16:33:10 +0000 Subject: [PATCH 16/29] Restyled by clang-format --- examples/dynamic-bridge-app/linux/main.cpp | 19 +++--- .../bridge/BridgeClustersImpl.h | 24 ++++---- .../bridge/BridgeGlobalStructs.h | 2 - .../cluster_with_commands/bridge/OnOff.h | 61 ++++++++----------- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index df42544bf1a95d..25302141071453 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -224,7 +224,7 @@ CHIP_ERROR WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16 { if (maxReadLength != 1) { - return CHIP_ERROR_BUFFER_TOO_SMALL; + return CHIP_ERROR_BUFFER_TOO_SMALL; } *buffer = value ? 1 : 0; return CHIP_NO_ERROR; @@ -280,8 +280,8 @@ CHIP_ERROR ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint return err; } -CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, uint16_t maxReadLength, - bool read) +CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, + uint16_t maxReadLength, bool read) { switch (type) { @@ -377,7 +377,8 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI if (err != CHIP_NO_ERROR) { printChipError(err); - ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d", attributeMetadata->attributeId, endpoint, clusterId); + ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d", + attributeMetadata->attributeId, endpoint, clusterId); return EMBER_ZCL_STATUS_FAILURE; } writer.Finalize(); @@ -388,7 +389,8 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI if (err != CHIP_NO_ERROR) { printChipError(err); - ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); + ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, + attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; } @@ -423,7 +425,8 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster if (err != CHIP_NO_ERROR) { printChipError(err); - ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); + ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, + attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; } @@ -437,7 +440,9 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster if (err != CHIP_NO_ERROR) { printChipError(err); - ChipLogError(DeviceLayer, "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); + ChipLogError(DeviceLayer, + "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint, + clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; } diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h index 0484909c914739..5a5998741c96c1 100644 --- a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h @@ -1,26 +1,24 @@ #pragma once -#include #include "bridge/OnOff.h" +#include namespace clusters { struct ClusterInfo { - chip::ClusterId id; - const char *name; - uint16_t size; - GeneratedCluster* (*ctor)(void*); + chip::ClusterId id; + const char * name; + uint16_t size; + GeneratedCluster * (*ctor)(void *); } static const kKnownClusters[] = { - { - 6, - "OnOff", - sizeof(OnOffCluster), - [](void *mem) -> GeneratedCluster* { - return new(mem) OnOffCluster(); + { + 6, + "OnOff", + sizeof(OnOffCluster), + [](void * mem) -> GeneratedCluster * { return new (mem) OnOffCluster(); }, }, - }, }; -} +} // namespace clusters diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h index 3b56a6f868b109..c74bdfd2d75d4d 100644 --- a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h @@ -8,6 +8,4 @@ namespace clusters { - - } diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h b/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h index cc788958dad0d4..48d2666ecade75 100644 --- a/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h +++ b/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h @@ -7,43 +7,34 @@ namespace clusters { struct OnOffCluster : public GeneratedCluster { - OnOffCluster() : - mOnOff(chip::CharSpan("onOff"), 0, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1), - mFeatureMap(chip::CharSpan("featureMap"), 65532, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP32_ATTRIBUTE_TYPE, 4), - mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_ON_OFF_CLUSTER_REVISION) - { - } - - static constexpr uint32_t kClusterId =6; - chip::ClusterId GetClusterId() override { return kClusterId; } - - std::vector GetAttributes() override - { - return std::vector({ - static_cast(&mOnOff), - static_cast(&mFeatureMap), - static_cast(&mClusterRevision), - }); - } - - - Attribute mOnOff; - Attribute mFeatureMap; - Attribute mClusterRevision; - static const chip::CommandId mIncomingCommandList[]; - const chip::CommandId * GetIncomingCommandList() override - { - return mIncomingCommandList; - } + OnOffCluster() : + mOnOff(chip::CharSpan("onOff"), 0, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1), + mFeatureMap(chip::CharSpan("featureMap"), 65532, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP32_ATTRIBUTE_TYPE, 4), + mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), + ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_ON_OFF_CLUSTER_REVISION) + {} + + static constexpr uint32_t kClusterId = 6; + chip::ClusterId GetClusterId() override { return kClusterId; } + + std::vector GetAttributes() override + { + return std::vector({ + static_cast(&mOnOff), + static_cast(&mFeatureMap), + static_cast(&mClusterRevision), + }); + } + + Attribute mOnOff; + Attribute mFeatureMap; + Attribute mClusterRevision; + static const chip::CommandId mIncomingCommandList[]; + const chip::CommandId * GetIncomingCommandList() override { return mIncomingCommandList; } }; #ifndef ON_OFF_CLUSTER_INCOMING_COMMANDS #define ON_OFF_CLUSTER_INCOMING_COMMANDS -const chip::CommandId OnOffCluster::mIncomingCommandList[] = { - 0, - 1, - 2, - chip::kInvalidCommandId -}; +const chip::CommandId OnOffCluster::mIncomingCommandList[] = { 0, 1, 2, chip::kInvalidCommandId }; #endif -} +} // namespace clusters From 8c22ed083de606e2178e7b257592ad67aed50842 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Wed, 11 Jan 2023 10:51:56 -0500 Subject: [PATCH 17/29] dynamic-bridge-app: move tests to the proper location --- .../outputs/cluster_with_commands/bridge/BridgeClustersImpl.h | 0 .../outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h | 0 .../tests/outputs/cluster_with_commands/bridge/OnOff.h | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename scripts/{idl => py_matter_idl/matter_idl}/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h (100%) rename scripts/{idl => py_matter_idl/matter_idl}/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h (100%) rename scripts/{idl => py_matter_idl/matter_idl}/tests/outputs/cluster_with_commands/bridge/OnOff.h (100%) diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h similarity index 100% rename from scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h rename to scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h similarity index 100% rename from scripts/idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h rename to scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h diff --git a/scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h similarity index 100% rename from scripts/idl/tests/outputs/cluster_with_commands/bridge/OnOff.h rename to scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h From bc0238e5015b711a9d13a83350e82072b1f95fea Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Wed, 11 Jan 2023 11:20:03 -0500 Subject: [PATCH 18/29] dynamic-bridge-app: undo formatting done to matter_idl tests restyled by clang-formatter --- .../bridge/BridgeClustersImpl.h | 24 ++++---- .../bridge/BridgeGlobalStructs.h | 2 + .../cluster_with_commands/bridge/OnOff.h | 61 +++++++++++-------- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h index 5a5998741c96c1..0484909c914739 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeClustersImpl.h @@ -1,24 +1,26 @@ #pragma once -#include "bridge/OnOff.h" #include +#include "bridge/OnOff.h" namespace clusters { struct ClusterInfo { - chip::ClusterId id; - const char * name; - uint16_t size; - GeneratedCluster * (*ctor)(void *); + chip::ClusterId id; + const char *name; + uint16_t size; + GeneratedCluster* (*ctor)(void*); } static const kKnownClusters[] = { - { - 6, - "OnOff", - sizeof(OnOffCluster), - [](void * mem) -> GeneratedCluster * { return new (mem) OnOffCluster(); }, + { + 6, + "OnOff", + sizeof(OnOffCluster), + [](void *mem) -> GeneratedCluster* { + return new(mem) OnOffCluster(); }, + }, }; -} // namespace clusters +} diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h index c74bdfd2d75d4d..3b56a6f868b109 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/BridgeGlobalStructs.h @@ -8,4 +8,6 @@ namespace clusters { + + } diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h index 48d2666ecade75..cc788958dad0d4 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h @@ -7,34 +7,43 @@ namespace clusters { struct OnOffCluster : public GeneratedCluster { - OnOffCluster() : - mOnOff(chip::CharSpan("onOff"), 0, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1), - mFeatureMap(chip::CharSpan("featureMap"), 65532, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP32_ATTRIBUTE_TYPE, 4), - mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), - ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_ON_OFF_CLUSTER_REVISION) - {} - - static constexpr uint32_t kClusterId = 6; - chip::ClusterId GetClusterId() override { return kClusterId; } - - std::vector GetAttributes() override - { - return std::vector({ - static_cast(&mOnOff), - static_cast(&mFeatureMap), - static_cast(&mClusterRevision), - }); - } - - Attribute mOnOff; - Attribute mFeatureMap; - Attribute mClusterRevision; - static const chip::CommandId mIncomingCommandList[]; - const chip::CommandId * GetIncomingCommandList() override { return mIncomingCommandList; } + OnOffCluster() : + mOnOff(chip::CharSpan("onOff"), 0, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BOOLEAN_ATTRIBUTE_TYPE, 1), + mFeatureMap(chip::CharSpan("featureMap"), 65532, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_BITMAP32_ATTRIBUTE_TYPE, 4), + mClusterRevision(chip::CharSpan("clusterRevision"), 65533, 0 | ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZCL_INT16U_ATTRIBUTE_TYPE, 2, ZCL_ON_OFF_CLUSTER_REVISION) + { + } + + static constexpr uint32_t kClusterId =6; + chip::ClusterId GetClusterId() override { return kClusterId; } + + std::vector GetAttributes() override + { + return std::vector({ + static_cast(&mOnOff), + static_cast(&mFeatureMap), + static_cast(&mClusterRevision), + }); + } + + + Attribute mOnOff; + Attribute mFeatureMap; + Attribute mClusterRevision; + static const chip::CommandId mIncomingCommandList[]; + const chip::CommandId * GetIncomingCommandList() override + { + return mIncomingCommandList; + } }; #ifndef ON_OFF_CLUSTER_INCOMING_COMMANDS #define ON_OFF_CLUSTER_INCOMING_COMMANDS -const chip::CommandId OnOffCluster::mIncomingCommandList[] = { 0, 1, 2, chip::kInvalidCommandId }; +const chip::CommandId OnOffCluster::mIncomingCommandList[] = { + 0, + 1, + 2, + chip::kInvalidCommandId +}; #endif -} // namespace clusters +} From 98ea329755b6b9fa9039685c997c668c1adcd9db Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Thu, 12 Jan 2023 11:49:51 -0500 Subject: [PATCH 19/29] dynamic-bridge-app: change read and write functions to use AnonymousTag() instead of Tag() --- .../dynamic-bridge-app/linux/UserInputBackend.cpp | 14 +++++++------- .../linux/include/data-model/Attribute.h | 2 +- examples/dynamic-bridge-app/linux/main.cpp | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp index 03d6023d5f8864..b609ad9cceffa9 100644 --- a/examples/dynamic-bridge-app/linux/UserInputBackend.cpp +++ b/examples/dynamic-bridge-app/linux/UserInputBackend.cpp @@ -286,20 +286,20 @@ void ParseValue(std::vector * data, uint16_t size, const std::string & { case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: - wr.PutString(chip::TLV::Tag(), str.data(), (uint32_t) str.size()); + wr.PutString(chip::TLV::AnonymousTag(), str.data(), (uint32_t) str.size()); break; case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: - wr.PutBytes(chip::TLV::Tag(), (const uint8_t *) str.data(), (uint32_t) str.size()); + wr.PutBytes(chip::TLV::AnonymousTag(), (const uint8_t *) str.data(), (uint32_t) str.size()); break; case ZCL_STRUCT_ATTRIBUTE_TYPE: // Writing structs not supported yet break; case ZCL_SINGLE_ATTRIBUTE_TYPE: - wr.Put(chip::TLV::Tag(), (float) atof(str.c_str())); + wr.Put(chip::TLV::AnonymousTag(), (float) atof(str.c_str())); break; case ZCL_DOUBLE_ATTRIBUTE_TYPE: - wr.Put(chip::TLV::Tag(), atof(str.c_str())); + wr.Put(chip::TLV::AnonymousTag(), atof(str.c_str())); break; case ZCL_INT8S_ATTRIBUTE_TYPE: case ZCL_INT16S_ATTRIBUTE_TYPE: @@ -309,7 +309,7 @@ void ParseValue(std::vector * data, uint16_t size, const std::string & case ZCL_INT48S_ATTRIBUTE_TYPE: case ZCL_INT56S_ATTRIBUTE_TYPE: case ZCL_INT64S_ATTRIBUTE_TYPE: - wr.Put(chip::TLV::Tag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); + wr.Put(chip::TLV::AnonymousTag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); break; case ZCL_INT8U_ATTRIBUTE_TYPE: @@ -320,12 +320,12 @@ void ParseValue(std::vector * data, uint16_t size, const std::string & case ZCL_INT48U_ATTRIBUTE_TYPE: case ZCL_INT56U_ATTRIBUTE_TYPE: case ZCL_INT64U_ATTRIBUTE_TYPE: - wr.Put(chip::TLV::Tag(), (uint64_t) strtoll(str.c_str(), nullptr, 10)); + wr.Put(chip::TLV::AnonymousTag(), (uint64_t) strtoll(str.c_str(), nullptr, 10)); break; default: // Assume integer - wr.Put(chip::TLV::Tag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); + wr.Put(chip::TLV::AnonymousTag(), (int64_t) strtoll(str.c_str(), nullptr, 10)); break; } wr.Finalize(); diff --git a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index 4238162c1bd810..c7bcdd2fd99dd0 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -62,7 +62,7 @@ struct Attribute : public AttributeInterface template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { - return chip::app::DataModel::Encode(writer, chip::TLV::Tag(), value); + return chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), value); } CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer) override diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 25302141071453..6db183db53e0cd 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -207,17 +207,17 @@ std::unique_ptr CreateCluster(chip::ClusterId id) CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const Span & v) { - return wr.PutString(chip::TLV::Tag(), v); + return wr.PutString(chip::TLV::AnonymousTag(), v); } CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const bool & v) { - return wr.PutBoolean(chip::TLV::Tag(), v); + return wr.PutBoolean(chip::TLV::AnonymousTag(), v); } template CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const T & v) { - return wr.Put(chip::TLV::Tag(), v); + return wr.Put(chip::TLV::AnonymousTag(), v); } CHIP_ERROR WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) From b91b1f831352c37876d759ee883df7802abe9089 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Thu, 12 Jan 2023 14:04:52 -0500 Subject: [PATCH 20/29] dynamic-bridge-app: document unclear code and refactor function and variable names for better readability --- .../linux/include/GeneratedClusters.h | 9 +- examples/dynamic-bridge-app/linux/main.cpp | 96 +++++++++++-------- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 14ee0f6de45789..55e2aa5aad2c4b 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -25,6 +25,13 @@ class GeneratedCluster // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; + // Returns a list of client to server commands. Can be nulttptr or terminated by 0xFFFF_FFFF. + // The returned list mirrors the `acceptedCommandList` field in `EmberAfCluster` + // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. virtual const chip::CommandId * GetIncomingCommandList() { return nullptr; } - virtual const chip::CommandId * GetOutgoingCommandList() { return nullptr; }; + + // Returns a list of server generated commands (responses to client commands). Can be nulttptr or terminated by 0xFFFF_FFFF. + // The returned list mirrors the `generatedCommandList` field in `EmberAfCluster` + // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. + virtual const chip::CommandId * GetOutgoingCommandList() { return nullptr; } }; diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 6db183db53e0cd..fdb19de21c3407 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -205,45 +205,45 @@ std::unique_ptr CreateCluster(chip::ClusterId id) return nullptr; } -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const Span & v) +CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const Span & v) { return wr.PutString(chip::TLV::AnonymousTag(), v); } -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const bool & v) +CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const bool & v) { return wr.PutBoolean(chip::TLV::AnonymousTag(), v); } template -CHIP_ERROR ReadValueFromBuffer(chip::TLV::TLVWriter & wr, const T & v) +CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const T & v) { return wr.Put(chip::TLV::AnonymousTag(), v); } -CHIP_ERROR WriteValueToBuffer(const bool & value, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(const bool & value, chip::Span buffer) { - if (maxReadLength != 1) + if (buffer.size() != 1) { return CHIP_ERROR_BUFFER_TOO_SMALL; } - *buffer = value ? 1 : 0; + *(buffer.data()) = value ? 1 : 0; return CHIP_NO_ERROR; } template -CHIP_ERROR WriteValueToBuffer(const T & value, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(const T & value, chip::Span buffer) { size_t value_size = sizeof(value); - if (maxReadLength < value_size) + if (buffer.size() < value_size) { return CHIP_ERROR_BUFFER_TOO_SMALL; } - memcpy(buffer, &value, value_size); + memcpy(buffer.data(), &value, value_size); return CHIP_NO_ERROR; } template -CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, const uint16_t & maxReadLength) +CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, chip::Span buffer) { T v; CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); @@ -251,53 +251,61 @@ CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, uint8_t * buffer, c { return err; } - return WriteValueToBuffer(v, buffer, maxReadLength); + return WriteValueToBuffer(v, buffer); } -// if `read` is true, read from `buffer`, and write to `data` -// otherwise, read from `data`, and write to `buffer` +// Describes a conversion direction between: +// - A binary buffer (passed from ember internals) +// - A TLV data buffer (used by TLVWriter and TLVReader) +enum ConversionDirection { + BUFFER_TO_TLV, + TLV_TO_BUFFER +}; + template -CHIP_ERROR ReadOrWriteBuffer(std::vector * data, uint8_t * buffer, uint16_t maxReadLength, bool read) +CHIP_ERROR PerformTLVBufferConversion(std::vector * tlvData, chip::Span buffer, ConversionDirection convert_direction) { CHIP_ERROR err; - if (read) + if (convert_direction == BUFFER_TO_TLV) { + // buffer.size() is ignored here, because it was called from the external write ember callback, + // which does not provide a buffer size chip::TLV::TLVWriter wr; - wr.Init(data->data(), data->size()); + wr.Init(tlvData->data(), tlvData->size()); T value; - memcpy(&value, buffer, sizeof(T)); - err = ReadValueFromBuffer(wr, value); + memcpy(&value, buffer.data(), sizeof(T)); + err = TLVWriteValue(wr, value); wr.Finalize(); - data->resize(wr.GetLengthWritten()); + tlvData->resize(wr.GetLengthWritten()); } else { chip::TLV::TLVReader rd; - rd.Init(data->data(), data->size()); + rd.Init(tlvData->data(), tlvData->size()); rd.Next(); - err = WriteValueToBuffer(rd, buffer, maxReadLength); + err = WriteValueToBuffer(rd, buffer); } return err; } -CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffer, EmberAfAttributeType type, - uint16_t maxReadLength, bool read) +CHIP_ERROR PerformTLVBufferConversionForType(std::vector * tlvData, chip::Span buffer, + EmberAfAttributeType type, ConversionDirection convert_direction) { switch (type) { case ZCL_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_CHAR_STRING_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer>(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion>(tlvData, buffer, convert_direction); case ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: case ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_STRUCT_ATTRIBUTE_TYPE: // structs not supported yet return CHIP_ERROR_NOT_IMPLEMENTED; case ZCL_SINGLE_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_DOUBLE_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_INT8S_ATTRIBUTE_TYPE: case ZCL_INT16S_ATTRIBUTE_TYPE: case ZCL_INT24S_ATTRIBUTE_TYPE: @@ -306,7 +314,7 @@ CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffe case ZCL_INT48S_ATTRIBUTE_TYPE: case ZCL_INT56S_ATTRIBUTE_TYPE: case ZCL_INT64S_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_INT8U_ATTRIBUTE_TYPE: case ZCL_INT16U_ATTRIBUTE_TYPE: case ZCL_INT24U_ATTRIBUTE_TYPE: @@ -315,14 +323,14 @@ CHIP_ERROR ReadOrWriteBufferForType(std::vector * data, uint8_t * buffe case ZCL_INT48U_ATTRIBUTE_TYPE: case ZCL_INT56U_ATTRIBUTE_TYPE: case ZCL_INT64U_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_BOOLEAN_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); case ZCL_BITMAP32_ATTRIBUTE_TYPE: - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); default: // Assume integer - return ReadOrWriteBuffer(data, buffer, maxReadLength, read); + return PerformTLVBufferConversion(tlvData, buffer, convert_direction); } } @@ -366,12 +374,14 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI } // adding 64 bytes as padding to include the staging buffer used by - // TLVWriter, which is 17 bytes - std::vector data(attributeMetadata->size + 64); + // TLVReader and TLVWriter, which is 17 bytes + std::vector tlvData(attributeMetadata->size + 64); // read the attribute and write it to `data` chip::TLV::TLVWriter writer; - writer.Init(data.data(), data.size()); + writer.Init(tlvData.data(), tlvData.size()); + + // this cast is safe because all the registered attribute accessors are of type `CommonAttributeAccessInterface`. See `main()` CHIP_ERROR err = static_cast(accessInterface) ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer); if (err != CHIP_NO_ERROR) @@ -382,10 +392,12 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI return EMBER_ZCL_STATUS_FAILURE; } writer.Finalize(); - data.resize(writer.GetLengthWritten()); + tlvData.resize(writer.GetLengthWritten()); // read from `data` and write to `buffer` - err = ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, maxReadLength, false); + + // maxReadLength here is the maximum number of bytes to read from the attribute value and to write into the buffer. + err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, maxReadLength), attributeMetadata->attributeType, TLV_TO_BUFFER); if (err != CHIP_NO_ERROR) { printChipError(err); @@ -417,11 +429,13 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster } // adding 64 bytes as padding to include the staging buffer used by - // TLVWriter, which is 17 bytes - std::vector data(attributeMetadata->size + 64); + // TLVReader and TLVWriter, which is 17 bytes + std::vector tlvData(attributeMetadata->size + 64); // read from `buffer` and write to `data` - CHIP_ERROR err = ReadOrWriteBufferForType(&data, buffer, attributeMetadata->attributeType, 0, true); + + // buffer size will not be used in this code path, so we set it to 0. See `PerformTLVBufferConversion` + CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, 0), attributeMetadata->attributeType, BUFFER_TO_TLV); if (err != CHIP_NO_ERROR) { printChipError(err); @@ -432,7 +446,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster // read from `data` and write to attribute chip::TLV::TLVReader reader; - reader.Init(data.data(), data.size()); + reader.Init(tlvData.data(), tlvData.size()); reader.Next(); chip::app::AttributeValueDecoder decoder(reader, chip::Access::SubjectDescriptor()); err = From f5f2d64311b44ac23ec79d17b36ba02abfa298d3 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Thu, 12 Jan 2023 20:17:29 -0500 Subject: [PATCH 21/29] dynamic-bridge-app: mark OnListWriteBegin and OnListWriteEnd as overrides --- examples/dynamic-bridge-app/linux/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index fdb19de21c3407..82a7e5e0f9512c 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -87,8 +87,8 @@ struct CommonAttributeAccessInterface : public chip::app::AttributeAccessInterfa CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, TLV::TLVWriter & writer); - void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath); - void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful); + void OnListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override; + void OnListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override; }; CommonCluster * CommonAttributeAccessInterface::FindCluster(const chip::app::ConcreteClusterPath & path) From 1872a7cf5840af04abe404e053917b6f58cf0f1f Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Fri, 13 Jan 2023 10:31:16 -0500 Subject: [PATCH 22/29] dynamic-bridge-app: fix error handling in WriteValueToBuffer --- examples/dynamic-bridge-app/linux/main.cpp | 27 +++++----------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 82a7e5e0f9512c..44dec87eca70e6 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -222,7 +222,7 @@ CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const T & v) CHIP_ERROR WriteValueToBuffer(const bool & value, chip::Span buffer) { - if (buffer.size() != 1) + if (buffer.size() == 0) { return CHIP_ERROR_BUFFER_TOO_SMALL; } @@ -246,11 +246,7 @@ template CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, chip::Span buffer) { T v; - CHIP_ERROR err = chip::app::DataModel::Decode(reader, v); - if (err != CHIP_NO_ERROR) - { - return err; - } + ReturnErrorOnFailure(chip::app::DataModel::Decode(reader, v)); return WriteValueToBuffer(v, buffer); } @@ -342,17 +338,6 @@ bool emberAfActionsClusterInstantActionCallback(app::CommandHandler * commandObj return true; } -void printChipError(CHIP_ERROR err) -{ - char errorStr[160]; - bool errorStrFound = FormatCHIPError(errorStr, sizeof(errorStr), err); - if (!errorStrFound) - { - errorStr[0] = 0; - } - ChipLogError(DeviceLayer, "%s", errorStr); -} - EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer, uint16_t maxReadLength) @@ -386,7 +371,7 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer); if (err != CHIP_NO_ERROR) { - printChipError(err); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d", attributeMetadata->attributeId, endpoint, clusterId); return EMBER_ZCL_STATUS_FAILURE; @@ -400,7 +385,7 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, maxReadLength), attributeMetadata->attributeType, TLV_TO_BUFFER); if (err != CHIP_NO_ERROR) { - printChipError(err); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; @@ -438,7 +423,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, 0), attributeMetadata->attributeType, BUFFER_TO_TLV); if (err != CHIP_NO_ERROR) { - printChipError(err); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; @@ -453,7 +438,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); if (err != CHIP_NO_ERROR) { - printChipError(err); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); From a21b5281a0f74b04907928518683543f618022ce Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Fri, 13 Jan 2023 10:45:01 -0500 Subject: [PATCH 23/29] dynamic-bridge-app: simplify the include path in BridgeClustersCpp jinja template and update the relevant tests --- .../matter_idl/generators/bridge/BridgeClustersCpp.jinja | 2 +- .../outputs/cluster_struct_attribute/bridge/DemoClusterServer.h | 2 +- .../tests/outputs/cluster_with_commands/bridge/OnOff.h | 2 +- .../outputs/global_struct_attribute/bridge/DemoClusterServer.h | 2 +- .../tests/outputs/several_clusters/bridge/FirstServer.h | 2 +- .../tests/outputs/several_clusters/bridge/SecondServer.h | 2 +- .../matter_idl/tests/outputs/several_clusters/bridge/Third.h | 2 +- .../tests/outputs/several_clusters/bridge/ThirdServer.h | 2 +- .../tests/outputs/simple_attribute/bridge/MyClusterServer.h | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/py_matter_idl/matter_idl/generators/bridge/BridgeClustersCpp.jinja b/scripts/py_matter_idl/matter_idl/generators/bridge/BridgeClustersCpp.jinja index 0dc53754cd8bdd..14a6aca640b0ad 100644 --- a/scripts/py_matter_idl/matter_idl/generators/bridge/BridgeClustersCpp.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/bridge/BridgeClustersCpp.jinja @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct {{cluster.name}}Cluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h index 0350cb8e9bc9f4..eac0b0aeca0d1c 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_struct_attribute/bridge/DemoClusterServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct DemoClusterCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h index cc788958dad0d4..1e34c2c7953418 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/cluster_with_commands/bridge/OnOff.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct OnOffCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h index f0cf41365f3fa2..3c6feeb5a3baba 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/global_struct_attribute/bridge/DemoClusterServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct DemoClusterCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/FirstServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/FirstServer.h index 6d90a693779dfa..2786817c0dc8a5 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/FirstServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/FirstServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct FirstCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/SecondServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/SecondServer.h index 41f7f74660945b..71905bf252bd60 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/SecondServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/SecondServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct SecondCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/Third.h b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/Third.h index 47f4551754277b..3b15195c0af9e4 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/Third.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/Third.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct ThirdCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/ThirdServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/ThirdServer.h index bdc0cce18066f8..d2f8bccb12d648 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/ThirdServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/bridge/ThirdServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct ThirdCluster : public GeneratedCluster diff --git a/scripts/py_matter_idl/matter_idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h b/scripts/py_matter_idl/matter_idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h index 0c9fd7abb4a93f..831b39de9cfca4 100644 --- a/scripts/py_matter_idl/matter_idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h +++ b/scripts/py_matter_idl/matter_idl/tests/outputs/simple_attribute/bridge/MyClusterServer.h @@ -1,7 +1,7 @@ #pragma once #include "BridgeGlobalStructs.h" -#include "third_party/connectedhomeip/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h" +#include "GeneratedClusters.h" namespace clusters { struct MyClusterCluster : public GeneratedCluster From f2692f9b972d8adb9df6761ee5f48eea8af89773 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Fri, 13 Jan 2023 13:23:11 -0500 Subject: [PATCH 24/29] dynamic-bridge-app: change CHIP_ERROR_BUFFER_TOO_SMALL errors to CHIP_ERROR_INVALID_ARGUMENT --- examples/dynamic-bridge-app/linux/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 44dec87eca70e6..ce47616b8a5f8d 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -222,9 +222,9 @@ CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const T & v) CHIP_ERROR WriteValueToBuffer(const bool & value, chip::Span buffer) { - if (buffer.size() == 0) + if (buffer.size() != 1) { - return CHIP_ERROR_BUFFER_TOO_SMALL; + return CHIP_ERROR_INVALID_ARGUMENT; } *(buffer.data()) = value ? 1 : 0; return CHIP_NO_ERROR; @@ -234,9 +234,9 @@ template CHIP_ERROR WriteValueToBuffer(const T & value, chip::Span buffer) { size_t value_size = sizeof(value); - if (buffer.size() < value_size) + if (buffer.size() != value_size) { - return CHIP_ERROR_BUFFER_TOO_SMALL; + return CHIP_ERROR_INVALID_ARGUMENT; } memcpy(buffer.data(), &value, value_size); return CHIP_NO_ERROR; From ec0b498772e355a470d0c9bb2157696d58b91ca8 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 16 Jan 2023 12:22:30 -0500 Subject: [PATCH 25/29] dynamic-bridge-app: allow read operations on externally stored list attributes --- .../linux/include/data-model/Attribute.h | 5 +- .../linux/include/data-model/DataModel.h | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index c7bcdd2fd99dd0..8baf96d37c2ad7 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -53,12 +53,13 @@ struct Attribute : public AttributeInterface { return chip::app::DataModel::Encode(aPath, aEncoder, mData); } - + template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { - return CHIP_ERROR_NOT_IMPLEMENTED; + return chip::app::DataModel::Encode(aPath, writer, chip::TLV::AnonymousTag(), value); } + template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { diff --git a/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h index fde7bf07841f43..6f78787830e3f3 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/DataModel.h @@ -65,6 +65,7 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath &, AttributeValueEncoder & aEn /* * @brief * Lists that are string-like should be encoded as char/byte spans. + * Encode using a given AttributeValueEncoder. */ template < typename X, @@ -74,11 +75,26 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder return aEncoder.Encode(Span>(x.data(), x.size())); } +/* + * @brief + * Lists that are string-like should be encoded as char/byte spans. + * Encode using a given TLVWriter. + */ +template < + typename X, + std::enable_if_t>::value && sizeof(std::decay_t) == sizeof(char), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, TLV::TLVWriter & writer, TLV::Tag tag, const X & x) +{ + return writer.Put(tag, Span>(x.data(), x.size())); +} + /* * @brief * * If an item is requested from a list, encode just that single item, or the entire list otherwise. * + * Encodes items using a given AttributeValueEncoder. + * * The object must satisfy the following constraints * size() must return an integer * begin() must return a type conforming to LegacyRandomAccessIterator @@ -113,6 +129,46 @@ CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, AttributeValueEncoder }); } +/* + * @brief + * + * If an item is requested from a list, encode just that single item, or the entire list otherwise. + * + * Encodes items using a given TLVWriter. + * + * The object must satisfy the following constraints + * size() must return an integer + * begin() must return a type conforming to LegacyRandomAccessIterator + * + * This is const X& instead of X&& because it is "more specialized" and so this overload will + * be chosen if possible. + */ +template < + typename X, + std::enable_if_t>::value && (sizeof(std::decay_t) > sizeof(char)), bool> = true> +CHIP_ERROR Encode(const ConcreteReadAttributePath & aPath, TLV::TLVWriter & writer, TLV::Tag tag, const X & x) +{ + if (aPath.mListIndex.HasValue()) + { + uint16_t index = aPath.mListIndex.Value(); + if (index >= x.size()) + return CHIP_ERROR_INVALID_ARGUMENT; + + auto it = x.begin(); + std::advance(it, index); + return Encode(writer, tag, *it); + } + TLV::TLVType type; + + ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Array, type)); + for (auto & item : x) + { + ReturnErrorOnFailure(Encode(writer, tag, item)); + } + ReturnErrorOnFailure(writer.EndContainer(type)); + return CHIP_NO_ERROR; +} + /* * @brief * Set of overloaded encode methods that can be called from AttributeAccessInterface::Read From 8dc0893f13ab27b9e79db4722bc20ea294c8ac9a Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 16 Jan 2023 17:24:57 +0000 Subject: [PATCH 26/29] Restyled by whitespace --- examples/dynamic-bridge-app/linux/include/GeneratedClusters.h | 2 +- .../dynamic-bridge-app/linux/include/data-model/Attribute.h | 2 +- examples/dynamic-bridge-app/linux/main.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 55e2aa5aad2c4b..902c4ac54e5466 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -29,7 +29,7 @@ class GeneratedCluster // The returned list mirrors the `acceptedCommandList` field in `EmberAfCluster` // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. virtual const chip::CommandId * GetIncomingCommandList() { return nullptr; } - + // Returns a list of server generated commands (responses to client commands). Can be nulttptr or terminated by 0xFFFF_FFFF. // The returned list mirrors the `generatedCommandList` field in `EmberAfCluster` // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. diff --git a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h index 8baf96d37c2ad7..b44a0b43ec929f 100644 --- a/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h +++ b/examples/dynamic-bridge-app/linux/include/data-model/Attribute.h @@ -53,7 +53,7 @@ struct Attribute : public AttributeInterface { return chip::app::DataModel::Encode(aPath, aEncoder, mData); } - + template >::value, bool> = true> CHIP_ERROR ReadValue(const chip::app::ConcreteReadAttributePath & aPath, chip::TLV::TLVWriter & writer, Type & value) { diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index ce47616b8a5f8d..354492524605c4 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -419,7 +419,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster // read from `buffer` and write to `data` - // buffer size will not be used in this code path, so we set it to 0. See `PerformTLVBufferConversion` + // buffer size will not be used in this code path, so we set it to 0. See `PerformTLVBufferConversion` CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, 0), attributeMetadata->attributeType, BUFFER_TO_TLV); if (err != CHIP_NO_ERROR) { From 6069841439e760b136419985dba1de279055056e Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 16 Jan 2023 17:24:58 +0000 Subject: [PATCH 27/29] Restyled by clang-format --- .../linux/include/GeneratedClusters.h | 6 ++-- examples/dynamic-bridge-app/linux/main.cpp | 28 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index 902c4ac54e5466..d0a7cbaf61ca34 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -27,11 +27,13 @@ class GeneratedCluster // Returns a list of client to server commands. Can be nulttptr or terminated by 0xFFFF_FFFF. // The returned list mirrors the `acceptedCommandList` field in `EmberAfCluster` - // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. + // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See + // `AddCluster` in `UserInputBackend`. virtual const chip::CommandId * GetIncomingCommandList() { return nullptr; } // Returns a list of server generated commands (responses to client commands). Can be nulttptr or terminated by 0xFFFF_FFFF. // The returned list mirrors the `generatedCommandList` field in `EmberAfCluster` - // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See `AddCluster` in `UserInputBackend`. + // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See + // `AddCluster` in `UserInputBackend`. virtual const chip::CommandId * GetOutgoingCommandList() { return nullptr; } }; diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 354492524605c4..12b5cf5e9707a8 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -253,19 +253,21 @@ CHIP_ERROR WriteValueToBuffer(chip::TLV::TLVReader & reader, chip::Span // Describes a conversion direction between: // - A binary buffer (passed from ember internals) // - A TLV data buffer (used by TLVWriter and TLVReader) -enum ConversionDirection { +enum ConversionDirection +{ BUFFER_TO_TLV, TLV_TO_BUFFER }; template -CHIP_ERROR PerformTLVBufferConversion(std::vector * tlvData, chip::Span buffer, ConversionDirection convert_direction) +CHIP_ERROR PerformTLVBufferConversion(std::vector * tlvData, chip::Span buffer, + ConversionDirection convert_direction) { CHIP_ERROR err; if (convert_direction == BUFFER_TO_TLV) { - // buffer.size() is ignored here, because it was called from the external write ember callback, - // which does not provide a buffer size + // buffer.size() is ignored here, because it was called from the external write ember callback, + // which does not provide a buffer size chip::TLV::TLVWriter wr; wr.Init(tlvData->data(), tlvData->size()); T value; @@ -284,8 +286,8 @@ CHIP_ERROR PerformTLVBufferConversion(std::vector * tlvData, chip::Span return err; } -CHIP_ERROR PerformTLVBufferConversionForType(std::vector * tlvData, chip::Span buffer, - EmberAfAttributeType type, ConversionDirection convert_direction) +CHIP_ERROR PerformTLVBufferConversionForType(std::vector * tlvData, chip::Span buffer, EmberAfAttributeType type, + ConversionDirection convert_direction) { switch (type) { @@ -371,7 +373,7 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI ->Read(chip::app::ConcreteDataAttributePath(endpoint, clusterId, attributeMetadata->attributeId), writer); if (err != CHIP_NO_ERROR) { - ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Attribute access interface failed to read attribute %d, for endpoint %d cluster %d", attributeMetadata->attributeId, endpoint, clusterId); return EMBER_ZCL_STATUS_FAILURE; @@ -382,10 +384,11 @@ EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterI // read from `data` and write to `buffer` // maxReadLength here is the maximum number of bytes to read from the attribute value and to write into the buffer. - err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, maxReadLength), attributeMetadata->attributeType, TLV_TO_BUFFER); + err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, maxReadLength), attributeMetadata->attributeType, + TLV_TO_BUFFER); if (err != CHIP_NO_ERROR) { - ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Failed to write attribute to buffer. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; @@ -420,10 +423,11 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster // read from `buffer` and write to `data` // buffer size will not be used in this code path, so we set it to 0. See `PerformTLVBufferConversion` - CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, 0), attributeMetadata->attributeType, BUFFER_TO_TLV); + CHIP_ERROR err = PerformTLVBufferConversionForType(&tlvData, chip::Span(buffer, 0), attributeMetadata->attributeType, + BUFFER_TO_TLV); if (err != CHIP_NO_ERROR) { - ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Failed to read value from buffer: Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); return EMBER_ZCL_STATUS_FAILURE; @@ -438,7 +442,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, Cluster accessInterface->Write(chip::app::ConcreteReadAttributePath(endpoint, clusterId, attributeMetadata->attributeId), decoder); if (err != CHIP_NO_ERROR) { - ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(DeviceLayer, "%" CHIP_ERROR_FORMAT, err.Format()); ChipLogError(DeviceLayer, "Attribute access interface failed to write attribute value. Endpoint %d, Cluster %d, Attribute %d", endpoint, clusterId, attributeMetadata->attributeId); From be231e441e1891da1206a81a8a149119053a1f87 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 16 Jan 2023 12:44:03 -0500 Subject: [PATCH 28/29] dynamic-bridge-app: formatting - add whitespace between function definitions --- examples/dynamic-bridge-app/linux/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/dynamic-bridge-app/linux/main.cpp b/examples/dynamic-bridge-app/linux/main.cpp index 12b5cf5e9707a8..f71f120e3bdd38 100644 --- a/examples/dynamic-bridge-app/linux/main.cpp +++ b/examples/dynamic-bridge-app/linux/main.cpp @@ -209,6 +209,7 @@ CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const Span & v) { return wr.PutString(chip::TLV::AnonymousTag(), v); } + CHIP_ERROR TLVWriteValue(chip::TLV::TLVWriter & wr, const bool & v) { return wr.PutBoolean(chip::TLV::AnonymousTag(), v); From 449692743386c4eee4a1a8a5292b3b970ac1aeb9 Mon Sep 17 00:00:00 2001 From: Feras Muki Date: Mon, 16 Jan 2023 16:09:47 -0500 Subject: [PATCH 29/29] dynamic-bridge-app: fix typo in GeneratedClusters.h --- examples/dynamic-bridge-app/linux/include/GeneratedClusters.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h index d0a7cbaf61ca34..9c12ffe0b5d480 100644 --- a/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h +++ b/examples/dynamic-bridge-app/linux/include/GeneratedClusters.h @@ -25,13 +25,13 @@ class GeneratedCluster // Gets the list of available attributes for this cluster. virtual std::vector GetAttributes() = 0; - // Returns a list of client to server commands. Can be nulttptr or terminated by 0xFFFF_FFFF. + // Returns a list of client to server commands. Can be nullptr or terminated by 0xFFFF_FFFF. // The returned list mirrors the `acceptedCommandList` field in `EmberAfCluster` // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See // `AddCluster` in `UserInputBackend`. virtual const chip::CommandId * GetIncomingCommandList() { return nullptr; } - // Returns a list of server generated commands (responses to client commands). Can be nulttptr or terminated by 0xFFFF_FFFF. + // Returns a list of server generated commands (responses to client commands). Can be nullptr or terminated by 0xFFFF_FFFF. // The returned list mirrors the `generatedCommandList` field in `EmberAfCluster` // This function is used to pass a command list when creating a `DynamicCluster` and its underlying `EmberAfCluster`. See // `AddCluster` in `UserInputBackend`.