diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index d3eed04e3..72abc3c0d 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -75,6 +75,12 @@ attribute_t *create_parts_list(cluster_t *cluster, uint8_t *value, uint16_t leng esp_matter_array(value, length, count)); } +attribute_t *create_tag_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, Descriptor::Attributes::TagList::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_array(value, length, count)); +} + } /* attribute */ } /* descriptor */ diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 919873f9f..de6555655 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -39,6 +39,7 @@ attribute_t *create_device_list(cluster_t *cluster, uint8_t *value, uint16_t len attribute_t *create_server_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_client_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_parts_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); +attribute_t *create_tag_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); } /* attribute */ } /* descriptor */ diff --git a/components/esp_matter/esp_matter_feature.cpp b/components/esp_matter/esp_matter_feature.cpp index 81589498f..8ed828376 100644 --- a/components/esp_matter/esp_matter_feature.cpp +++ b/components/esp_matter/esp_matter_feature.cpp @@ -63,6 +63,34 @@ static uint32_t get_feature_map_value(cluster_t *cluster) return val.val.u32; } +namespace descriptor { +namespace feature { +namespace taglist { + +uint32_t get_id() +{ + return (uint32_t)Descriptor::Feature::kTagList; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + /* Attributes managed internally */ + attribute::create_tag_list(cluster, NULL, 0, 0); + + return ESP_OK; +} + +} /* taglist */ + +} +} + namespace power_source { namespace feature { namespace wired { diff --git a/components/esp_matter/esp_matter_feature.h b/components/esp_matter/esp_matter_feature.h index 634ea81b9..0a64add9e 100644 --- a/components/esp_matter/esp_matter_feature.h +++ b/components/esp_matter/esp_matter_feature.h @@ -31,6 +31,18 @@ namespace esp_matter { namespace cluster { +namespace descriptor { +namespace feature { +namespace taglist { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); + +} /* taglist */ + +} /* feature */ +} /* descriptor */ + namespace power_source { namespace feature { namespace wired { diff --git a/docs/en/developing.rst b/docs/en/developing.rst index 8f2eebd6e..3e3857695 100644 --- a/docs/en/developing.rst +++ b/docs/en/developing.rst @@ -747,6 +747,17 @@ Examples: command_t *command = level_control::command::create_move_to_level(cluster); +2.4.2.4 Features +^^^^^^^^^^^^^^^^^^ +Optional features which are applicable to a cluster can also be added. + +- feature: taglist: Descriptor cluster: + + :: + + cluster_t* cluster = cluster::get(endpoint, Descriptor::Id); + descriptor::feature::taglist::add(cluster); + 2.4.3 Adding custom data model fields ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/generic_switch/README.md b/examples/generic_switch/README.md index 08560ab29..45e373bf2 100644 --- a/examples/generic_switch/README.md +++ b/examples/generic_switch/README.md @@ -2,7 +2,12 @@ This example creates a Generic Switch device using the ESP Matter data model. -This example aims to demonstrate the use of Fixed Label Cluster and User Label Cluster which provide a feature for the device to tag an endpoint with zero or more read-only labels using nvs api and zero or more labels respectively. +This example demonstrates the use of few optional data model elements like : +- Fixed Label Cluster : provides a feature for the device to tag an endpoint with zero or more read only labels.(demonnstrated through nvs) +- User Label Cluster : This cluster provides a feature to tag an endpoint with zero or more labels. +- Taglist Feature of Descriptor Cluster : used to disambiguate sibling endpoints where two or more sibling + endpoints have an overlap in the supported device types with each such endpoint having a unique TagList. + Note: In order to retrieve the label-list from the fixed-label cluster the two options: @@ -47,6 +52,13 @@ To read label-list of User Label Cluster execute the command given below. ``` chip-tool userlabel read label-list 0x7283 1 + +### Using the TagList Feature + +To read the taglist of the Descriptor cluster execute the command given below. + +``` +chip-tool descriptor read tag-list 0x7283 1 ``` ## 2. Post Commissioning Setup diff --git a/examples/generic_switch/main/app_main.cpp b/examples/generic_switch/main/app_main.cpp index 917ad5464..ebb54c947 100644 --- a/examples/generic_switch/main/app_main.cpp +++ b/examples/generic_switch/main/app_main.cpp @@ -16,6 +16,8 @@ #include #include +#include + #if CHIP_DEVICE_CONFIG_ENABLE_THREAD #include #endif @@ -28,8 +30,32 @@ static button_endpoint button_list[CONFIG_MAX_CONFIGURABLE_BUTTONS]; using namespace esp_matter; using namespace esp_matter::attribute; using namespace esp_matter::endpoint; +using namespace esp_matter::cluster; using namespace chip::app::Clusters; +namespace { +// Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces +constexpr const uint8_t kNamespaceSwitches = 43; +// Common Number Namespace: 7, tag 0 (Zero) +constexpr const uint8_t kTagSwitchOn = 0; +// Common Number Namespace: 7, tag 1 (One) +constexpr const uint8_t kTagSwitchOff = 1; + +constexpr const uint8_t kNamespacePosition = 8; +// Common Position Namespace: 8, tag: 0 (Left) +constexpr const uint8_t kTagPositionLeft = 0; +// Common Position Namespace: 8, tag: 1 (Right) +constexpr const uint8_t kTagPositionRight = 1; + +const Descriptor::Structs::SemanticTagStruct::Type gEp0TagList[] = { + {.namespaceID = kNamespaceSwitches, .tag = kTagSwitchOn}, + {.namespaceID = kNamespacePosition, .tag = kTagPositionRight}}; +const Descriptor::Structs::SemanticTagStruct::Type gEp1TagList[] = { + {.namespaceID = kNamespaceSwitches, .tag = kTagSwitchOff}, + {.namespaceID = kNamespacePosition, .tag = kTagPositionLeft}}; + +} + static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) { switch (event->Type) { @@ -103,6 +129,9 @@ static esp_err_t create_button(struct gpio_button* button, node_t* node) generic_switch::config_t switch_config; endpoint_t *endpoint = generic_switch::create(node, &switch_config, ENDPOINT_FLAG_NONE, button_handle); + cluster_t* descriptor = cluster::get(endpoint,Descriptor::Id); + descriptor::feature::taglist::add(descriptor); + /* These node and endpoint handles can be used to create/add other endpoints and clusters. */ if (!node || !endpoint) { @@ -201,6 +230,10 @@ extern "C" void app_main() ESP_LOGE(TAG, "Matter start failed: %d", err); } + SetTagList(0, chip::Span(gEp0TagList)); + SetTagList(1, chip::Span(gEp1TagList)); + + nvs_handle_t handle; nvs_open_from_partition(CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION_LABEL, "chip-factory", NVS_READWRITE, &handle);