diff --git a/components/esp_matter/data_model/esp_matter_data_model.cpp b/components/esp_matter/data_model/esp_matter_data_model.cpp index 84cb26536..1e53f85ec 100644 --- a/components/esp_matter/data_model/esp_matter_data_model.cpp +++ b/components/esp_matter/data_model/esp_matter_data_model.cpp @@ -212,11 +212,27 @@ esp_err_t read_min_unused_endpoint_id() namespace endpoint { +static void report_parts_list_change_internal(endpoint_t *endpoint) +{ + chip::EndpointId parent_endpoint_id = endpoint::get_parent_endpoint_id(endpoint); + while (parent_endpoint_id != chip::kInvalidEndpointId) { + MatterReportingAttributeChangeCallback(parent_endpoint_id, chip::app::Clusters::Descriptor::Id, + chip::app::Clusters::Descriptor::Attributes::PartsList::Id); + parent_endpoint_id = endpoint::get_parent_endpoint_id(endpoint::get(parent_endpoint_id)); + } + MatterReportingAttributeChangeCallback(/* endpoint = */ 0, chip::app::Clusters::Descriptor::Id, + chip::app::Clusters::Descriptor::Attributes::PartsList::Id); +} + esp_err_t disable(endpoint_t *endpoint) { VerifyOrReturnError(endpoint, ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Endpoint cannot be NULL")); _endpoint_t *current_endpoint = (_endpoint_t *)endpoint; current_endpoint->enabled = false; + { + esp_matter::lock::ScopedChipStackLock lock(portMAX_DELAY); + report_parts_list_change_internal(endpoint); + } return ESP_OK; } @@ -240,12 +256,62 @@ static esp_err_t init_identification(endpoint_t *endpoint) return ESP_OK; } +static void invoke_init_callbacks_internal(endpoint_t *endpoint) +{ + cluster_t *cluster = cluster::get_first(endpoint); + while (cluster) { + /* Delegate server init callback */ + cluster::delegate_init_callback_t delegate_init_callback = cluster::get_delegate_init_callback(cluster); + if (delegate_init_callback) { + delegate_init_callback(cluster::get_delegate_impl(cluster), endpoint::get_id(endpoint)); + } + + /* Add bounds callback */ + cluster::add_bounds_callback_t add_bounds_callback = cluster::get_add_bounds_callback(cluster); + if (add_bounds_callback) { + add_bounds_callback(cluster); + } + + /* Plugin server init callback */ + cluster::plugin_server_init_callback_t plugin_server_init_callback = + cluster::get_plugin_server_init_callback(cluster); + if (plugin_server_init_callback) { + plugin_server_init_callback(); + } + + /* Initialization callback */ + uint8_t flags = cluster::get_flags(cluster); + cluster::initialization_callback_t init_callback = cluster::get_init_callback(cluster); + if (init_callback) { + init_callback(endpoint::get_id(endpoint)); + } + + /* Init function */ + if ((flags & CLUSTER_FLAG_SERVER) && (flags & CLUSTER_FLAG_INIT_FUNCTION)) { + cluster::function_cluster_init_t init_function = + (cluster::function_cluster_init_t)cluster::get_function(cluster, CLUSTER_FLAG_INIT_FUNCTION); + if (init_function) { + init_function(endpoint::get_id(endpoint)); + } + } + cluster = cluster::get_next(cluster); + } +} + esp_err_t enable(endpoint_t *endpoint) { VerifyOrReturnError(endpoint, ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Endpoint cannot be NULL")); _endpoint_t *current_endpoint = (_endpoint_t *)endpoint; current_endpoint->enabled = true; init_identification(endpoint); + { + // Use the lock instead of schedule lambda to ensure the callbacks are invoked before esp_matter::start() returns. + esp_matter::lock::ScopedChipStackLock lock(portMAX_DELAY); + invoke_init_callbacks_internal(endpoint); + // Mark the endpoint as dirty so that the data model provider will report the attribute changes. + MatterReportingAttributeChangeCallback(endpoint::get_id(endpoint)); + report_parts_list_change_internal(endpoint); + } return ESP_OK; } @@ -1660,6 +1726,30 @@ esp_err_t destroy(node_t *node, endpoint_t *endpoint) } VerifyOrReturnError(current_endpoint != NULL, ESP_FAIL, ESP_LOGE(TAG, "Could not find the endpoint to delete")); + { + esp_matter::lock::ScopedChipStackLock lock(portMAX_DELAY); + cluster_t *cluster = cluster::get_first(endpoint); + while (cluster) { + /* Shutdown callback */ + cluster::shutdown_callback_t shutdown_callback = cluster::get_shutdown_callback(cluster); + if (shutdown_callback) { + shutdown_callback(endpoint::get_id(endpoint)); + } + cluster = cluster::get_next(cluster); + + /* Shutdown function */ + uint8_t flags = cluster::get_flags(cluster); + if ((flags & CLUSTER_FLAG_SERVER) && (flags & CLUSTER_FLAG_SHUTDOWN_FUNCTION)) { + cluster::function_cluster_shutdown_t shutdown_function = + (cluster::function_cluster_shutdown_t)cluster::get_function(cluster, CLUSTER_FLAG_SHUTDOWN_FUNCTION); + if (shutdown_function) { + shutdown_function(endpoint::get_id(endpoint)); + } + } + cluster = cluster::get_next(cluster); + } + } + /* Parse and delete all clusters */ _cluster_t *cluster = current_endpoint->cluster_list; while (cluster) { diff --git a/components/esp_matter/data_model_provider/esp_matter_data_model_provider.cpp b/components/esp_matter/data_model_provider/esp_matter_data_model_provider.cpp index 57fa06bc1..4dd3a8d5b 100644 --- a/components/esp_matter/data_model_provider/esp_matter_data_model_provider.cpp +++ b/components/esp_matter/data_model_provider/esp_matter_data_model_provider.cpp @@ -235,28 +235,6 @@ CHIP_ERROR provider::Startup(InteractionModelContext context) { ReturnErrorOnFailure(DataModel::Provider::Startup(context)); mContext.emplace(context); - esp_matter::cluster::add_bounds_callback_common(); - esp_matter::cluster::plugin_init_callback_common(); - endpoint_t *ep = endpoint::get_first(node::get()); - while (ep) { - cluster_t *cluster = cluster::get_first(ep); - while (cluster) { - uint8_t flags = cluster::get_flags(cluster); - cluster::initialization_callback_t init_callback = cluster::get_init_callback(cluster); - if (init_callback) { - init_callback(endpoint::get_id(ep)); - } - if ((flags & CLUSTER_FLAG_SERVER) && (flags & CLUSTER_FLAG_INIT_FUNCTION)) { - cluster::function_cluster_init_t init_function = - (cluster::function_cluster_init_t)cluster::get_function(cluster, CLUSTER_FLAG_INIT_FUNCTION); - if (init_function) { - init_function(endpoint::get_id(ep)); - } - } - cluster = cluster::get_next(cluster); - } - ep = endpoint::get_next(ep); - } if (GetAttributePersistenceProvider() == nullptr) { gDefaultAttributePersistence.Init(&Server::GetInstance().GetPersistentStorage()); SetAttributePersistenceProvider(&gDefaultAttributePersistence); @@ -605,9 +583,13 @@ CHIP_ERROR provider::Attributes(const ConcreteClusterPath &path, ReadOnlyBufferB void provider::Temporary_ReportAttributeChanged(const AttributePathParams &path) { - cluster_t *cluster = cluster::get(path.mEndpointId, path.mClusterId); - VerifyOrReturn(cluster != nullptr); - VerifyOrReturn(cluster::increase_data_version(cluster) == ESP_OK); + VerifyOrReturn(!path.HasWildcardEndpointId()); + // If the cluster is not wildcard, increase the data version + if (!path.HasWildcardClusterId()) { + cluster_t *cluster = cluster::get(path.mEndpointId, path.mClusterId); + VerifyOrReturn(cluster != nullptr); + VerifyOrReturn(cluster::increase_data_version(cluster) == ESP_OK); + } mContext->dataModelChangeListener.MarkDirty(path); } diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 7e3763df5..7b97e2e9c 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -225,8 +225,6 @@ static void esp_matter_chip_init_task(intptr_t context) if (endpoint::enable_all() != ESP_OK) { ESP_LOGE(TAG, "Enable all endpoints failure"); } - // Initialise clusters which have delegate implemented - esp_matter::cluster::delegate_init_callback_common(); #endif // CONFIG_ESP_MATTER_ENABLE_DATA_MODEL #if CHIP_CONFIG_ENABLE_ICD_SERVER if (!icd::get_icd_server_enabled()) {