From 250c2e8af6dded4e81750ab212f180792feba298 Mon Sep 17 00:00:00 2001 From: shripad621git Date: Thu, 21 Aug 2025 14:24:31 +0530 Subject: [PATCH] components/esp_matter: esp-matter component changes for the submodule - Added esp-matter codegen integration files for migrated clusters. - Fixed the commissioning flow for wifi and thread due to migration of network commissioning instances from platform to example. - Fixed the spell check issues for the modified files. - Fixed the decode method syntax for fabric scoped commands. - Modified the cluster revisions for few clusters as per spec. --- components/esp_matter/CMakeLists.txt | 11 ++ ...ator_commissioning_codegen_integration.cpp | 79 ++++++++++++++ .../data_model/esp_matter_attribute.cpp | 24 ++++- .../data_model/esp_matter_attribute.h | 9 +- .../data_model/esp_matter_cluster.cpp | 1 + .../data_model/esp_matter_command.cpp | 66 +++++++++--- .../data_model/esp_matter_endpoint.cpp | 5 +- .../data_model/esp_matter_endpoint.h | 6 +- .../data_model/esp_matter_feature.cpp | 11 +- .../data_model/ota_provider_integration.cpp | 102 ++++++++++++++++++ ...ftware_diagnostics_codegen_integration.cpp | 74 +++++++++++++ components/esp_matter/esp_matter_core.cpp | 6 +- components/esp_matter/esp_matter_core.h | 13 ++- .../network_commissioning_instance.cpp | 50 +++++++++ .../private/esp_matter_cluster_revisions.h | 8 +- 15 files changed, 428 insertions(+), 37 deletions(-) create mode 100644 components/esp_matter/data_model/administrator_commissioning_codegen_integration.cpp create mode 100644 components/esp_matter/data_model/ota_provider_integration.cpp create mode 100644 components/esp_matter/data_model/software_diagnostics_codegen_integration.cpp create mode 100644 components/esp_matter/network_commissioning_instance.cpp diff --git a/components/esp_matter/CMakeLists.txt b/components/esp_matter/CMakeLists.txt index e3e01ff19..fe0c88f8d 100644 --- a/components/esp_matter/CMakeLists.txt +++ b/components/esp_matter/CMakeLists.txt @@ -11,6 +11,7 @@ set(INCLUDE_DIRS_LIST "." # TODO: This file has compilation errors set(EXCLUDE_SRCS_LIST "${MATTER_SDK_PATH}/src/app/clusters/closure-control-server/closure-control-server.cpp") +list(APPEND EXCLUDE_SRCS_LIST "${MATTER_SDK_PATH}/src/app/clusters/general-commissioning-server/TemporaryTestCoupling.cpp") if (CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER) list(APPEND SRC_DIRS_LIST "${MATTER_SDK_PATH}/src/app/server" @@ -36,6 +37,14 @@ if (CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER) "private") list(APPEND INCLUDE_DIRS_LIST "zap_common" "data_model") + list(APPEND EXCLUDE_SRCS_LIST "${MATTER_SDK_PATH}/src/app/clusters/software-diagnostics-server/CodegenIntegration.cpp") + list(APPEND EXCLUDE_SRCS_LIST "${MATTER_SDK_PATH}/src/app/clusters/administrator-commissioning-server/CodegenIntegration.cpp") + list(APPEND EXCLUDE_SRCS_LIST "${MATTER_SDK_PATH}/src/app/clusters/ota-provider/CodegenIntegration.cpp") + + if(NOT CONFIG_SUPPORT_SOFTWARE_DIAGNOSTICS_CLUSTER) + list(APPEND EXCLUDE_SRCS_LIST "data_model/software_diagnostics_codegen_integration.cpp") + endif() + endif(CONFIG_ESP_MATTER_ENABLE_DATA_MODEL) else() list(APPEND EXCLUDE_SRCS_LIST "esp_matter_identify.cpp" @@ -43,6 +52,8 @@ else() "esp_matter_attribute_utils.cpp") endif(CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER) + + set(REQUIRES_LIST chip bt esp_matter_console nvs_flash app_update esp_secure_cert_mgr mbedtls esp_system openthread json) idf_component_register( SRC_DIRS ${SRC_DIRS_LIST} diff --git a/components/esp_matter/data_model/administrator_commissioning_codegen_integration.cpp b/components/esp_matter/data_model/administrator_commissioning_codegen_integration.cpp new file mode 100644 index 000000000..32e6b4879 --- /dev/null +++ b/components/esp_matter/data_model/administrator_commissioning_codegen_integration.cpp @@ -0,0 +1,79 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::AdministratorCommissioning::Attributes; +using chip::Protocols::InteractionModel::Status; + +namespace { + +// AdministratorCommissioningCluster implementation is specifically implemented +// only for the root endpoint (endpoint 0) +// So either: +// - we have a fixed config and it is endpoint 0 OR +// - we have a fully dynamic config + +static constexpr size_t kAdministratorCommissioningFixedClusterCount = 0; + +using ClusterImpl = AdministratorCommissioningWithBasicCommissioningWindowCluster; +LazyRegisteredServerCluster gServer; + +} // namespace + +void emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpointId) +{ + if (endpointId != kRootEndpointId) + { + return; + } + + uint32_t rawFeatureMap; + if (FeatureMap::Get(endpointId, &rawFeatureMap) != Status::Success) + { + ChipLogError(AppServer, "Failed to get feature map for endpoint %u", endpointId); + rawFeatureMap = 0; + } + + gServer.Create(endpointId, BitFlags(rawFeatureMap)); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(gServer.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Admin Commissioning register error: endpoint %u, %" CHIP_ERROR_FORMAT, endpointId, err.Format()); + } +} + +void emberAfAdministratorCommissioningClusterShutdownCallback(EndpointId endpointId) +{ + if (endpointId != kRootEndpointId) + { + return; + } + + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Unregister(&gServer.Cluster()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Admin Commissioning unregister error: endpoint %u, %" CHIP_ERROR_FORMAT, endpointId, err.Format()); + } + gServer.Destroy(); +} + +void MatterAdministratorCommissioningPluginServerInitCallback() {} +void MatterAdministratorCommissioningPluginServerShutdownCallback() {} diff --git a/components/esp_matter/data_model/esp_matter_attribute.cpp b/components/esp_matter/data_model/esp_matter_attribute.cpp index 12be832b9..5c9374955 100644 --- a/components/esp_matter/data_model/esp_matter_attribute.cpp +++ b/components/esp_matter/data_model/esp_matter_attribute.cpp @@ -297,6 +297,13 @@ attribute_t *create_max_paths_per_invoke(cluster_t *cluster, uint16_t value) esp_matter_uint16(value)); } +attribute_t *create_configuration_version(cluster_t *cluster, uint32_t value) +{ + return esp_matter::attribute::create(cluster, BasicInformation::Attributes::ConfigurationVersion::Id, + ATTRIBUTE_FLAG_MANAGED_INTERNALLY, esp_matter_uint32(value)); +} + + } /* attribute */ } /* basic_information */ @@ -958,7 +965,7 @@ attribute_t *create_detached_role_count(cluster_t *cluster, uint16_t value) ATTRIBUTE_FLAG_MANAGED_INTERNALLY, esp_matter_uint16(value)); } -attribute_t *create_chlid_role_count(cluster_t *cluster, uint16_t value) +attribute_t *create_child_role_count(cluster_t *cluster, uint16_t value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id, ATTRIBUTE_FLAG_MANAGED_INTERNALLY, esp_matter_uint16(value)); @@ -1388,6 +1395,12 @@ attribute_t *create_product_appearance(cluster_t *cluster, uint8_t *value, uint1 ATTRIBUTE_FLAG_NONE, esp_matter_array(value, length, count)); } +attribute_t *create_configuration_version(cluster_t *cluster, uint32_t value) +{ + return esp_matter::attribute::create(cluster, BridgedDeviceBasicInformation::Attributes::ConfigurationVersion::Id, + ATTRIBUTE_FLAG_MANAGED_INTERNALLY, esp_matter_uint32(value)); +} + } /* attribute */ } /* bridged_device_basic_information */ @@ -2758,7 +2771,7 @@ attribute_t *create_auto_relock_time(cluster_t *cluster, uint32_t value) esp_matter_uint32(value)); } -attribute_t *create_sound_valume(cluster_t *cluster, uint8_t value) +attribute_t *create_sound_volume(cluster_t *cluster, uint8_t value) { return esp_matter::attribute::create(cluster, DoorLock::Attributes::SoundVolume::Id, ATTRIBUTE_FLAG_WRITABLE, esp_matter_enum8(value)); @@ -3333,6 +3346,13 @@ attribute_t *create_temperature_unit(cluster_t *cluster, uint8_t value) ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_enum8(value)); } + +attribute_t *create_supported_temperature_units(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, UnitLocalization::Attributes::SupportedTemperatureUnits::Id, ATTRIBUTE_FLAG_MANAGED_INTERNALLY, + esp_matter_array(value, length, count)); +} + } /* attribute */ } /* unit_localization */ diff --git a/components/esp_matter/data_model/esp_matter_attribute.h b/components/esp_matter/data_model/esp_matter_attribute.h index 6515ae4bf..430bee20c 100644 --- a/components/esp_matter/data_model/esp_matter_attribute.h +++ b/components/esp_matter/data_model/esp_matter_attribute.h @@ -86,6 +86,7 @@ attribute_t *create_unique_id(cluster_t *cluster, char *value, uint16_t length); attribute_t *create_capability_minima(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_specification_version(cluster_t *cluster, uint32_t value); attribute_t *create_max_paths_per_invoke(cluster_t *cluster, uint16_t value); +attribute_t *create_configuration_version(cluster_t *cluster, uint32_t value); /** These attributes are optional for the cluster, but when added to this cluster, the value is maintained internally. * If the attributes are added in some other cluster, then the value is not maintained internally. @@ -259,7 +260,7 @@ attribute_t *create_ext_address(cluster_t *cluster, nullable value); attribute_t *create_rloc16(cluster_t *cluster, nullable value); attribute_t *create_overrun_count(cluster_t *cluster, uint64_t value); attribute_t *create_detached_role_count(cluster_t *cluster, uint16_t value); -attribute_t *create_chlid_role_count(cluster_t *cluster, uint16_t value); +attribute_t *create_child_role_count(cluster_t *cluster, uint16_t value); attribute_t *create_router_role_count(cluster_t *cluster, uint16_t value); attribute_t *create_leader_role_count(cluster_t *cluster, uint16_t value); attribute_t *create_attach_attempt_count(cluster_t *cluster, uint16_t value); @@ -355,6 +356,8 @@ attribute_t *create_serial_number(cluster_t *cluster, char *value, uint16_t leng attribute_t *create_reachable(cluster_t *cluster, bool value); attribute_t *create_unique_id(cluster_t *cluster, char *value, uint16_t length); attribute_t *create_product_appearance(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); +attribute_t *create_configuration_version(cluster_t *cluster, uint32_t *value); + } /* attribute */ } /* bridged_device_basic_information */ @@ -667,7 +670,7 @@ attribute_t *create_number_of_credentials_supported_per_user(cluster_t *cluster, attribute_t *create_language(cluster_t *cluster, const char * value, uint16_t length); attribute_t *create_led_settings(cluster_t *cluster, uint8_t value); attribute_t *create_auto_relock_time(cluster_t *cluster, uint32_t value); -attribute_t *create_sound_valume(cluster_t *cluster, uint8_t value); +attribute_t *create_sound_volume(cluster_t *cluster, uint8_t value); attribute_t *create_operating_mode(cluster_t *cluster, uint8_t value, uint8_t min, uint8_t max); attribute_t *create_supported_operating_modes(cluster_t *cluster, const uint16_t value); attribute_t *create_default_configuration_register(cluster_t *cluster, uint16_t value); @@ -830,6 +833,8 @@ attribute_t *create_supported_locales(cluster_t *cluster, uint8_t *value, uint16 namespace unit_localization { namespace attribute { attribute_t *create_temperature_unit(cluster_t *cluster, uint8_t value); +attribute_t *create_supported_temperature_units(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); + } /* attribute */ } /* unit_localization */ diff --git a/components/esp_matter/data_model/esp_matter_cluster.cpp b/components/esp_matter/data_model/esp_matter_cluster.cpp index baa494f3a..31c2e00a1 100644 --- a/components/esp_matter/data_model/esp_matter_cluster.cpp +++ b/components/esp_matter/data_model/esp_matter_cluster.cpp @@ -240,6 +240,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) attribute::create_capability_minima(cluster, NULL, 0, 0); attribute::create_specification_version(cluster, 0); attribute::create_max_paths_per_invoke(cluster, 0); + attribute::create_configuration_version(cluster, 0); /* Attributes not managed internally */ global::attribute::create_cluster_revision(cluster, cluster_revision); diff --git a/components/esp_matter/data_model/esp_matter_command.cpp b/components/esp_matter/data_model/esp_matter_command.cpp index dae4a6341..452e8daee 100644 --- a/components/esp_matter/data_model/esp_matter_command.cpp +++ b/components/esp_matter/data_model/esp_matter_command.cpp @@ -94,7 +94,9 @@ static esp_err_t esp_matter_command_callback_key_set_write(const ConcreteCommand void *opaque_ptr) { chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupKeyManagementClusterKeySetWriteCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -105,7 +107,9 @@ static esp_err_t esp_matter_command_callback_key_set_read(const ConcreteCommandP void *opaque_ptr) { chip::app::Clusters::GroupKeyManagement::Commands::KeySetRead::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupKeyManagementClusterKeySetReadCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -116,7 +120,9 @@ static esp_err_t esp_matter_command_callback_key_set_remove(const ConcreteComman TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::GroupKeyManagement::Commands::KeySetRemove::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupKeyManagementClusterKeySetRemoveCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -127,7 +133,9 @@ static esp_err_t esp_matter_command_callback_key_set_read_all_indices(const Conc TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::GroupKeyManagement::Commands::KeySetReadAllIndices::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupKeyManagementClusterKeySetReadAllIndicesCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -186,7 +194,9 @@ static esp_err_t esp_matter_command_callback_update_noc(const ConcreteCommandPat void *opaque_ptr) { chip::app::Clusters::OperationalCredentials::Commands::UpdateNOC::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfOperationalCredentialsClusterUpdateNOCCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -197,7 +207,9 @@ static esp_err_t esp_matter_command_callback_update_fabric_label(const ConcreteC TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::OperationalCredentials::Commands::UpdateFabricLabel::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfOperationalCredentialsClusterUpdateFabricLabelCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -234,7 +246,9 @@ static esp_err_t esp_matter_command_callback_set_vid_verification_statement(cons TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::OperationalCredentials::Commands::SetVIDVerificationStatement::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfOperationalCredentialsClusterSetVIDVerificationStatementCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -294,7 +308,9 @@ static esp_err_t esp_matter_command_callback_add_group(const ConcreteCommandPath void *opaque_ptr) { chip::app::Clusters::Groups::Commands::AddGroup::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterAddGroupCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -305,7 +321,9 @@ static esp_err_t esp_matter_command_callback_view_group(const ConcreteCommandPat void *opaque_ptr) { chip::app::Clusters::Groups::Commands::ViewGroup::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterViewGroupCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -316,7 +334,9 @@ static esp_err_t esp_matter_command_callback_get_group_membership(const Concrete TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::Groups::Commands::GetGroupMembership::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterGetGroupMembershipCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -327,7 +347,9 @@ static esp_err_t esp_matter_command_callback_remove_group(const ConcreteCommandP void *opaque_ptr) { chip::app::Clusters::Groups::Commands::RemoveGroup::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterRemoveGroupCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -338,7 +360,9 @@ static esp_err_t esp_matter_command_callback_remove_all_groups(const ConcreteCom TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::Groups::Commands::RemoveAllGroups::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterRemoveAllGroupsCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -349,7 +373,9 @@ static esp_err_t esp_matter_command_callback_add_group_if_identifying(const Conc TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::Groups::Commands::AddGroupIfIdentifying::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfGroupsClusterAddGroupIfIdentifyingCallback((CommandHandler *)opaque_ptr, command_path, command_data); } @@ -360,7 +386,9 @@ static esp_err_t esp_matter_command_callback_register_client(const ConcreteComma TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::IcdManagement::Commands::RegisterClient::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { #if CONFIG_ENABLE_ICD_SERVER emberAfIcdManagementClusterRegisterClientCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -373,7 +401,9 @@ static esp_err_t esp_matter_command_callback_unregister_client(const ConcreteCom TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::IcdManagement::Commands::UnregisterClient::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { #if CONFIG_ENABLE_ICD_SERVER emberAfIcdManagementClusterUnregisterClientCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -1426,7 +1456,9 @@ static esp_err_t esp_matter_command_callback_set_trusted_time_source(const Concr TLVReader &tlv_data, void *opaque_ptr) { chip::app::Clusters::TimeSynchronization::Commands::SetTrustedTimeSource::DecodableType command_data; - CHIP_ERROR error = Decode(tlv_data, command_data); + chip::app::CommandHandler *command_obj = (chip::app::CommandHandler *)opaque_ptr; + CHIP_ERROR error = command_data.Decode(tlv_data, command_obj->GetAccessingFabricIndex()); + if (error == CHIP_NO_ERROR) { emberAfTimeSynchronizationClusterSetTrustedTimeSourceCallback((CommandHandler *)opaque_ptr, command_path, command_data); @@ -2836,7 +2868,7 @@ command_t *create_reset_condition(cluster_t *cluster) namespace mode_base { namespace command { -// command response is null because of InvokeCommandHandler is overriden in srs/app/clusters/mode-base +// command response is null because of InvokeCommandHandler is overridden in srs/app/clusters/mode-base command_t *create_change_to_mode(cluster_t *cluster) { return esp_matter::command::create(cluster, ModeBase::Commands::ChangeToMode::Id, COMMAND_FLAG_ACCEPTED, NULL); diff --git a/components/esp_matter/data_model/esp_matter_endpoint.cpp b/components/esp_matter/data_model/esp_matter_endpoint.cpp index 64fbb5fe4..cdf44b6c1 100644 --- a/components/esp_matter/data_model/esp_matter_endpoint.cpp +++ b/components/esp_matter/data_model/esp_matter_endpoint.cpp @@ -330,6 +330,7 @@ esp_err_t add(endpoint_t *endpoint, config_t *config) cluster_t *identify_cluster = identify::create(endpoint, &(config->identify), CLUSTER_FLAG_SERVER); identify::command::create_trigger_effect(identify_cluster); groups::create(endpoint, &(config->groups), CLUSTER_FLAG_SERVER); + scenes_management::create(endpoint, &(config->scenes_management), CLUSTER_FLAG_SERVER); cluster_t *on_off_cluster = on_off::create(endpoint, &(config->on_off), CLUSTER_FLAG_SERVER); on_off::feature::lighting::add(on_off_cluster, &(config->on_off_lighting)); on_off::command::create_on(on_off_cluster); @@ -1343,12 +1344,12 @@ namespace robotic_vacuum_cleaner { uint32_t get_device_type_id() { - return ESP_MATTER_ROBOTIC_VACCUM_CLEANER_DEVICE_TYPE_ID; + return ESP_MATTER_ROBOTIC_VACUUM_CLEANER_DEVICE_TYPE_ID; } uint8_t get_device_type_version() { - return ESP_MATTER_ROBOTIC_VACCUM_CLEANER_DEVICE_TYPE_VERSION; + return ESP_MATTER_ROBOTIC_VACUUM_CLEANER_DEVICE_TYPE_VERSION; } endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) diff --git a/components/esp_matter/data_model/esp_matter_endpoint.h b/components/esp_matter/data_model/esp_matter_endpoint.h index 606c07604..f87aa9a0f 100644 --- a/components/esp_matter/data_model/esp_matter_endpoint.h +++ b/components/esp_matter/data_model/esp_matter_endpoint.h @@ -111,8 +111,8 @@ #define ESP_MATTER_PUMP_CONTROLLER_DEVICE_TYPE_VERSION 4 #define ESP_MATTER_MODE_SELECT_DEVICE_TYPE_ID 0x0027 #define ESP_MATTER_MODE_SELECT_DEVICE_TYPE_VERSION 1 -#define ESP_MATTER_ROBOTIC_VACCUM_CLEANER_DEVICE_TYPE_ID 0x0074 -#define ESP_MATTER_ROBOTIC_VACCUM_CLEANER_DEVICE_TYPE_VERSION 3 +#define ESP_MATTER_ROBOTIC_VACUUM_CLEANER_DEVICE_TYPE_ID 0x0074 +#define ESP_MATTER_ROBOTIC_VACUUM_CLEANER_DEVICE_TYPE_VERSION 3 #define ESP_MATTER_WATER_LEAK_DETECTOR_DEVICE_TYPE_ID 0x0043 #define ESP_MATTER_WATER_LEAK_DETECTOR_DEVICE_TYPE_VERSION 1 #define ESP_MATTER_RAIN_SENSOR_DEVICE_TYPE_ID 0x0044 @@ -293,9 +293,11 @@ esp_err_t add(endpoint_t *endpoint, config_t *config); namespace extended_color_light { typedef struct config : dimmable_light::config_t { cluster::color_control::config_t color_control; + cluster::scenes_management::config_t scenes_management; cluster::color_control::feature::color_temperature::config_t color_control_color_temperature; cluster::color_control::feature::xy::config_t color_control_xy; uint16_t color_control_remaining_time; + config() : color_control_remaining_time(0) {} } config_t; diff --git a/components/esp_matter/data_model/esp_matter_feature.cpp b/components/esp_matter/data_model/esp_matter_feature.cpp index 24f5764db..5037789ad 100644 --- a/components/esp_matter/data_model/esp_matter_feature.cpp +++ b/components/esp_matter/data_model/esp_matter_feature.cpp @@ -369,8 +369,8 @@ uint32_t get_id() esp_err_t add(cluster_t *cluster) { VerifyOrReturnError(cluster, ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Cluster cannot be NULL")); - uint32_t lits_feature_map = feature::long_idle_time_support::get_id(); - VerifyOrReturnError((get_feature_map_value(cluster) & lits_feature_map) == lits_feature_map, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "Long Idle Time Support feature should be added to this cluster")); + uint32_t long_idle_time_support_feature_map = feature::long_idle_time_support::get_id(); + VerifyOrReturnError((get_feature_map_value(cluster) & long_idle_time_support_feature_map) == long_idle_time_support_feature_map, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "Long Idle Time Support feature should be added to this cluster")); update_feature_map(cluster, get_id()); @@ -399,8 +399,8 @@ uint32_t get_id() esp_err_t add(cluster_t *cluster, config_t *config) { VerifyOrReturnError((cluster && config), ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Cluster and config cannot be NULL")); - uint32_t lits_feature_map = feature::long_idle_time_support::get_id(); - VerifyOrReturnError((get_feature_map_value(cluster) & lits_feature_map) == lits_feature_map, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "Long Idle Time Support feature should be added to this cluster")); + uint32_t long_idle_time_support_feature_map = feature::long_idle_time_support::get_id(); + VerifyOrReturnError((get_feature_map_value(cluster) & long_idle_time_support_feature_map) == long_idle_time_support_feature_map, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "Long Idle Time Support feature should be added to this cluster")); update_feature_map(cluster, get_id()); @@ -1801,6 +1801,7 @@ esp_err_t add(cluster_t *cluster, config_t *config) /* Attributes not managed internally */ attribute::create_temperature_unit(cluster, config->temperature_unit); + attribute::create_supported_temperature_units(cluster, NULL, 0, 0); return ESP_OK; } @@ -3348,7 +3349,7 @@ uint32_t get_id() esp_err_t add(cluster_t *cluster) { - VerifyOrReturnError(cluster, ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Cluster connot be NULL")); + VerifyOrReturnError(cluster, ESP_ERR_INVALID_ARG, ESP_LOGE(TAG, "Cluster cannot be NULL")); update_feature_map(cluster, get_id()); /* attribute */ nullable timestamp; diff --git a/components/esp_matter/data_model/ota_provider_integration.cpp b/components/esp_matter/data_model/ota_provider_integration.cpp new file mode 100644 index 000000000..2a6ee8173 --- /dev/null +++ b/components/esp_matter/data_model/ota_provider_integration.cpp @@ -0,0 +1,102 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; + +namespace { + +static constexpr size_t kOtaProviderFixedClusterCount = 0; +static constexpr size_t kOtaProviderMaxClusterCount = kOtaProviderFixedClusterCount + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +LazyRegisteredServerCluster gServers[kOtaProviderMaxClusterCount]; + +// Find the 0-based array index corresponding to the given endpoint id. +// Log an error if not found. +bool findEndpointWithLog(EndpointId endpointId, uint16_t & outArrayIndex) +{ + uint16_t arrayIndex = + emberAfGetClusterServerEndpointIndex(endpointId, OtaSoftwareUpdateProvider::Id, kOtaProviderFixedClusterCount); + + if (arrayIndex >= kOtaProviderMaxClusterCount) + { + ChipLogError(AppServer, "Could not find endpoint index for endpoint %u", endpointId); + return false; + } + return true; +} + +} // namespace + +void emberAfOtaSoftwareUpdateProviderClusterInitCallback(EndpointId endpointId) +{ + uint16_t arrayIndex = 0; + if (!findEndpointWithLog(endpointId, arrayIndex)) + { + return; + } + gServers[arrayIndex].Create(endpointId); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(gServers[arrayIndex].Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to register OTA on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, err.Format()); + } +} + +void emberAfOtaSoftwareUpdateProviderClusterShutdownCallback(EndpointId endpointId) +{ + uint16_t arrayIndex = 0; + if (!findEndpointWithLog(endpointId, arrayIndex)) + { + return; + } + + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Unregister(&gServers[arrayIndex].Cluster()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to unregister OTA on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, err.Format()); + } + gServers[arrayIndex].Destroy(); +} + +void MatterOtaSoftwareUpdateProviderPluginServerInitCallback() {} + +void MatterOtaSoftwareUpdateProviderPluginServerShutdownCallback() {} + +namespace chip { +namespace app { +namespace Clusters { +namespace OTAProvider { + +void SetDelegate(EndpointId endpointId, OTAProviderDelegate * delegate) +{ + uint16_t arrayIndex = 0; + if (!findEndpointWithLog(endpointId, arrayIndex)) + { + return; + } + gServers[arrayIndex].Cluster().SetDelegate(delegate); +} + +} // namespace OTAProvider +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/components/esp_matter/data_model/software_diagnostics_codegen_integration.cpp b/components/esp_matter/data_model/software_diagnostics_codegen_integration.cpp new file mode 100644 index 000000000..f037ed10d --- /dev/null +++ b/components/esp_matter/data_model/software_diagnostics_codegen_integration.cpp @@ -0,0 +1,74 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_matter_core.h" +#include +#include +#include +#include +#include "clusters/SoftwareDiagnostics/AttributeIds.h" +#include "clusters/SoftwareDiagnostics/ClusterId.h" +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::SoftwareDiagnostics; + +namespace { +LazyRegisteredServerCluster> gServer; +} + +bool isAttributeEnabled(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id) +{ + esp_matter::attribute_t *attr = esp_matter::attribute::get(endpoint_id, cluster_id, attribute_id); + printf("attr %ld enabled %d", attribute_id, attr != nullptr); + return attr != nullptr; +} + +void emberAfSoftwareDiagnosticsClusterInitCallback(chip::EndpointId endpointId) +{ + VerifyOrReturn(endpointId == chip::kRootEndpointId); + SoftwareDiagnosticsEnabledAttributes enabledAttributes{ + .enableThreadMetrics = isAttributeEnabled(endpointId, Id, Attributes::ThreadMetrics::Id), + .enableCurrentHeapFree = isAttributeEnabled(endpointId, Id, Attributes::CurrentHeapFree::Id), + .enableCurrentHeapUsed = isAttributeEnabled(endpointId, Id, Attributes::CurrentHeapUsed::Id), + .enableCurrentWatermarks = isAttributeEnabled(endpointId, Id, Attributes::CurrentHeapHighWatermark::Id), + }; + + gServer.Create(enabledAttributes); + + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Register(gServer.Registration()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to register SoftwareDiagnostics on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, + err.Format()); + } +} + +void emberAfSoftwareDiagnosticsClusterShutdownCallback(EndpointId endpointId) +{ + VerifyOrReturn(endpointId == kRootEndpointId); + CHIP_ERROR err = CodegenDataModelProvider::Instance().Registry().Unregister(&gServer.Cluster()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to unregister SoftwareDiagnostics on endpoint %u: %" CHIP_ERROR_FORMAT, endpointId, + err.Format()); + } + gServer.Destroy(); +} + +void MatterSoftwareDiagnosticsPluginServerInitCallback() {} + +void MatterSoftwareDiagnosticsPluginServerShutdownCallback() {} diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 2902b94e7..1e56eba03 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER #include @@ -223,6 +225,8 @@ static void esp_matter_chip_init_task(intptr_t context) ESP_LOGE(TAG, "Failed to add fabric delegate, err:%" CHIP_ERROR_FORMAT, ret.Format()); } chip::Server::GetInstance().Init(initParams); + network_commissioning_instance_init(); + #ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL if (endpoint::enable_all() != ESP_OK) { ESP_LOGE(TAG, "Enable all endpoints failure"); @@ -231,7 +235,7 @@ static void esp_matter_chip_init_task(intptr_t context) // TODO: Find a better way to record the events which should be recorded in matter server init // Record start up event in basic information cluster. PlatformMgr().HandleServerStarted(); - // Record boot reason evnet in general diagnostics cluster. + // Record boot reason event in general diagnostics cluster. chip::app::Clusters::GeneralDiagnostics::BootReasonEnum bootReason; if (GetDiagnosticDataProvider().GetBootReason(bootReason) == CHIP_NO_ERROR) { chip::app::Clusters::GeneralDiagnosticsServer::Instance().OnDeviceReboot(bootReason); diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index 50399826f..ec03d7b39 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -38,7 +38,7 @@ namespace esp_matter { /** TODO: Change this */ typedef void (*event_callback_t)(const ChipDeviceEvent *event, intptr_t arg); -/** Return whether the Matter is intialized and started +/** Return whether the Matter is initialized and started * * @return true if Matter is started * @return false if Matter is not started @@ -57,7 +57,7 @@ bool is_started(); */ esp_err_t start(event_callback_t callback, intptr_t callback_arg = static_cast(NULL)); -/** Return whether the Matter is intialized and started +/** Return whether the Matter is initialized and started * * @return true if Matter is started * @return false if Matter is not started @@ -73,6 +73,15 @@ bool is_started(); */ esp_err_t factory_reset(); +#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER +/** + * + * Initialize WiFi, Ethernet, and Thread network commissioning instances. + * This function is called internally during Matter initialization. + */ +void network_commissioning_instance_init(); +#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER + namespace lock { /** Lock status */ diff --git a/components/esp_matter/network_commissioning_instance.cpp b/components/esp_matter/network_commissioning_instance.cpp new file mode 100644 index 000000000..a0c3b2966 --- /dev/null +++ b/components/esp_matter/network_commissioning_instance.cpp @@ -0,0 +1,50 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#ifdef CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER + +#include +#include + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD && CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER +#include +#endif + +namespace esp_matter { + +void network_commissioning_instance_init() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI && CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER + static chip::app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(CONFIG_WIFI_NETWORK_ENDPOINT_ID /* Endpoint Id */, + &(chip::DeviceLayer::NetworkCommissioning::ESPWiFiDriver::GetInstance())); + sWiFiNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_WIFI_NETWORK_DRIVER + +#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET && CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER + static chip::app::Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(CONFIG_ETHERNET_NETWORK_ENDPOINT_ID /* Endpoint Id */, + &(chip::DeviceLayer::NetworkCommissioning::ESPEthernetDriver::GetInstance())); + sEthernetNetworkCommissioningInstance.Init(); +#endif // CHIP_DEVICE_CONFIG_ETHERNET_NETWORK_DRIVER + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD && CONFIG_THREAD_NETWORK_COMMISSIONING_DRIVER + static chip::app::Clusters::NetworkCommissioning::InstanceAndDriver sThreadNetworkDriver(CONFIG_THREAD_NETWORK_ENDPOINT_ID); + sThreadNetworkDriver.Init(); +#endif +} + +} // namespace esp_matter + +#endif // CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER diff --git a/components/esp_matter/private/esp_matter_cluster_revisions.h b/components/esp_matter/private/esp_matter_cluster_revisions.h index 3f80ed2f8..afef27db0 100644 --- a/components/esp_matter/private/esp_matter_cluster_revisions.h +++ b/components/esp_matter/private/esp_matter_cluster_revisions.h @@ -96,11 +96,11 @@ constexpr uint16_t cluster_revision = 2; } // namespace time_synchronization namespace unit_localization { -constexpr uint16_t cluster_revision = 1; +constexpr uint16_t cluster_revision = 2; } // namespace unit_localization namespace bridged_device_basic_information { -constexpr uint16_t cluster_revision = 4; +constexpr uint16_t cluster_revision = 5; } // namespace bridged_device_basic_information namespace power_source { @@ -108,7 +108,7 @@ constexpr uint16_t cluster_revision = 3; } // namespace power_source namespace icd_management { -constexpr uint16_t cluster_revision = 2; +constexpr uint16_t cluster_revision = 3; } // namespace icd_management namespace user_label { @@ -120,7 +120,7 @@ constexpr uint16_t cluster_revision = 1; } // namespace fixed_label namespace identify { -constexpr uint16_t cluster_revision = 5; +constexpr uint16_t cluster_revision = 6; } // namespace identify namespace groups {