From bd446e5565f15525948a02dd8ae84bc9f47cd119 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Wed, 19 Mar 2025 19:08:33 +0530 Subject: [PATCH 1/2] components/esp_matter: get the cluster count from the node details We used to have a static variable to get the groups cluster, but if people use low level APIs i.e. cluster::create(endpoint,cluster_id,flag) then group data provider will be falsly initialized since it does not have the correct group count. --- components/esp_matter/esp_matter_cluster.cpp | 5 - components/esp_matter/esp_matter_core.cpp | 104 ++++++++++++++++++- components/esp_matter/esp_matter_core.h | 22 ++++ 3 files changed, 125 insertions(+), 6 deletions(-) diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index cdfee9481..200f029eb 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -1215,9 +1215,6 @@ const function_generic_t function_list[] = { }; const int function_flags = CLUSTER_FLAG_INIT_FUNCTION; -static uint8_t server_cluster_count = 0; -uint8_t get_server_cluster_count() { return server_cluster_count; } - cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) { cluster_t *cluster = cluster::create(endpoint, Groups::Id, flags); @@ -1246,8 +1243,6 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) } else { ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes."); } - - server_cluster_count++; } /* Commands */ diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 5d973bebd..5fc94f9a1 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -920,7 +920,7 @@ static void esp_matter_chip_init_task(intptr_t context) #ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL // Group data provider injection for dynamic data model { - uint8_t groups_server_cluster_count = cluster::groups::get_server_cluster_count(); + uint8_t groups_server_cluster_count = node::get_server_cluster_endpoint_count(chip::app::Clusters::Groups::Id); uint16_t max_groups_per_fabric = groups_server_cluster_count * MAX_GROUPS_PER_FABRIC_PER_ENDPOINT; // since groupDataProvider is a static variable, it won't be released. @@ -2312,5 +2312,107 @@ esp_err_t destroy() return destroy_raw(); } +// Treat 0xFFFF'FFFF as wildcard cluster +static inline bool is_wildcard_cluster_id(uint32_t cluster_id) +{ + return cluster_id == chip::kInvalidClusterId; +} + +// Treat 0xFFFF as wildcard endpoint +static inline bool is_wildcard_endpoint_id(uint16_t endpoint_id) +{ + return endpoint_id == chip::kInvalidEndpointId; +} + +/** + * @brief Get the number of clusters that match the given flags + * + * @param endpoint_id: The endpoint ID to check, 0xFFFF is treated as wildcard endpoint id + * @param cluster_id: The cluster ID to check, 0xFFFF is treated as wildcard cluster id + * @param cluster_flags: The flags to check + * @return The number of clusters that match the given flags + */ +static uint32_t get_cluster_count(uint32_t endpoint_id, uint32_t cluster_id, uint8_t cluster_flags) +{ + uint32_t count = 0; + node_t *node = get(); + VerifyOrReturnValue(node, count, ESP_LOGE(TAG, "Node cannot be NULL")); + + // lambda to check if cluster matches flags and return 1 if it does, 0 otherwise + auto check_cluster_flags = [cluster_flags](const endpoint_t *endpoint, const cluster_t *cluster) -> uint32_t { + if (cluster && endpoint) { + const _endpoint_t *_endpoint = (_endpoint_t *)endpoint; + const _cluster_t *_cluster = (_cluster_t *)cluster; + EmberAfClusterMask flags = _endpoint->endpoint_type->cluster[_cluster->index].mask; + return (flags & cluster_flags) ? 1 : 0; + } + return 0; + }; + + // lambda to count all matching clusters for an endpoint + auto get_count_on_all_clusters = [&check_cluster_flags](endpoint_t *endpoint) -> uint32_t { + uint32_t result = 0; + if (!endpoint) return result; + + cluster_t *cluster = cluster::get_first(endpoint); + while (cluster) { + result += check_cluster_flags(endpoint, cluster); + cluster = cluster::get_next(cluster); + } + return result; + }; + + // lambda to find and count a specific cluster + auto get_count_on_specific_cluster = [&check_cluster_flags](const endpoint_t *endpoint, uint32_t cluster_id) -> uint32_t { + if (!endpoint) return 0; + cluster_t *cluster = cluster::get((endpoint_t *)endpoint, cluster_id); + return check_cluster_flags(endpoint, cluster); + }; + + // Case 1: Wildcard endpoint + if (is_wildcard_endpoint_id(endpoint_id)) { + endpoint_t *endpoint = endpoint::get_first(node); + while (endpoint) { + // Case 1.1: Wildcard cluster - count all clusters with matching flags + if (is_wildcard_cluster_id(cluster_id)) { + count += get_count_on_all_clusters(endpoint); + } + // Case 1.2: Specific cluster - count if it exists and has matching flags + else { + count += get_count_on_specific_cluster(endpoint, cluster_id); + } + endpoint = endpoint::get_next(endpoint); + } + } + // Case 2: Specific endpoint + else { + endpoint_t *endpoint = endpoint::get(endpoint_id); + if (!endpoint) { + return count; + } + + // Case 2.1: Wildcard cluster - count all clusters with matching flags + if (is_wildcard_cluster_id(cluster_id)) { + count += get_count_on_all_clusters(endpoint); + } + // Case 2.2: Specific cluster - count if it exists and has matching flags + else { + count += get_count_on_specific_cluster(endpoint, cluster_id); + } + } + + return count; +} + +uint32_t get_server_cluster_endpoint_count(uint32_t cluster_id) +{ + return get_cluster_count(chip::kInvalidEndpointId, cluster_id, CLUSTER_FLAG_SERVER); +} + +uint32_t get_client_cluster_endpoint_count(uint32_t cluster_id) +{ + return get_cluster_count(chip::kInvalidEndpointId, cluster_id, CLUSTER_FLAG_CLIENT); +} + } /* node */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index 41684aee6..dd51a9adc 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -145,6 +145,28 @@ node_t *get(); */ esp_err_t destroy(); +/** Get the endpoint count for a server cluster + * + * Get the number of endpoints that have the given cluster ID as a server cluster. + * + * @param[in] cluster_id Cluster ID. + * + * @return Endpoint count on success. + * @return 0 in case of failure or if not found on any endpoint. + */ + +uint32_t get_server_cluster_endpoint_count(uint32_t cluster_id); + +/** Get the endpoint count for a client cluster + * + * Get the number of endpoints that have the given cluster ID as a client cluster. + * + * @param[in] cluster_id Cluster ID. + * + * @return Endpoint count on success. + * @return 0 in case of failure or if not found on any endpoint. + */ +uint32_t get_client_cluster_endpoint_count(uint32_t cluster_id); } /* node */ namespace endpoint { From cfcdb7b3c980f03fb9fe9d0535808053c2ddce4d Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Tue, 13 May 2025 11:00:19 +0530 Subject: [PATCH 2/2] Use v1.3 compatible APIs for get cluster count impl --- components/esp_matter/esp_matter_core.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 5fc94f9a1..291a6d121 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -2341,9 +2341,8 @@ static uint32_t get_cluster_count(uint32_t endpoint_id, uint32_t cluster_id, uin // lambda to check if cluster matches flags and return 1 if it does, 0 otherwise auto check_cluster_flags = [cluster_flags](const endpoint_t *endpoint, const cluster_t *cluster) -> uint32_t { if (cluster && endpoint) { - const _endpoint_t *_endpoint = (_endpoint_t *)endpoint; const _cluster_t *_cluster = (_cluster_t *)cluster; - EmberAfClusterMask flags = _endpoint->endpoint_type->cluster[_cluster->index].mask; + EmberAfClusterMask flags = _cluster->flags; return (flags & cluster_flags) ? 1 : 0; } return 0; @@ -2386,7 +2385,7 @@ static uint32_t get_cluster_count(uint32_t endpoint_id, uint32_t cluster_id, uin } // Case 2: Specific endpoint else { - endpoint_t *endpoint = endpoint::get(endpoint_id); + endpoint_t *endpoint = endpoint::get(node, endpoint_id); if (!endpoint) { return count; }