diff --git a/components/esp_matter/esp_matter_core.cpp b/components/esp_matter/esp_matter_core.cpp index 9f9babb6e..ebf61f37d 100644 --- a/components/esp_matter/esp_matter_core.cpp +++ b/components/esp_matter/esp_matter_core.cpp @@ -845,6 +845,11 @@ static esp_err_t chip_init(event_callback_t callback, intptr_t callback_arg) return ESP_OK; } +bool is_started() +{ + return esp_matter_started; +} + esp_err_t start(event_callback_t callback, intptr_t callback_arg) { VerifyOrReturnError(!esp_matter_started, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "esp_matter has started")); diff --git a/components/esp_matter/esp_matter_core.h b/components/esp_matter/esp_matter_core.h index a6334fd38..d7161f434 100644 --- a/components/esp_matter/esp_matter_core.h +++ b/components/esp_matter/esp_matter_core.h @@ -53,6 +53,13 @@ typedef handle_t event_t; /** TODO: Change this */ typedef void (*event_callback_t)(const ChipDeviceEvent *event, intptr_t arg); +/** Return whether the Matter is intialized and started + * + * @return true if Matter is started + * @return false if Matter is not started + */ +bool is_started(); + /** ESP Matter Start * * Initialize and start the matter thread. diff --git a/components/esp_matter/esp_matter_icd_configuration.cpp b/components/esp_matter/esp_matter_icd_configuration.cpp new file mode 100644 index 000000000..60a869412 --- /dev/null +++ b/components/esp_matter/esp_matter_icd_configuration.cpp @@ -0,0 +1,125 @@ +// 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 + +#include +#include +#include + +using namespace chip::System::Clock; +static constexpr char *TAG = "icd"; + +namespace chip { +namespace Test { +class ICDConfigurationDataTestAccess { +// This class is a friend class for ICDConfigurationData, so it can access private members of ICDConfigurationData. +public: + static void SetFastPollingInterval(Milliseconds32 pollInterval) + { + ICDConfigurationData::GetInstance().SetFastPollingInterval(pollInterval); + } + + static void SetSlowPollingInterval(Milliseconds32 pollInterval) + { + ICDConfigurationData::GetInstance().SetSlowPollingInterval(pollInterval); + if (pollInterval >= Milliseconds32(15000)) { + // Active Threshold SHALL NOT be smaller than 5 seconds for LIT ICD. + ICDConfigurationData::GetInstance().SetICDMode(ICDConfigurationData::ICDMode::LIT); + if (ICDConfigurationData::GetInstance().mActiveThreshold < Milliseconds32(5000)) { + ICDConfigurationData::GetInstance().mActiveThreshold = Milliseconds32(5000); + } + } + } + + static esp_err_t SetModeDurations(Optional activeModeDuration, Optional idleModeDuration) + { + Optional idleModeDurationMs = chip::NullOptional; + if (idleModeDuration.HasValue()) { + idleModeDurationMs = MakeOptional(std::chrono::duration_cast(idleModeDuration.Value())); + } + CHIP_ERROR err = ICDConfigurationData::GetInstance().SetModeDurations(activeModeDuration, idleModeDurationMs); + return err == CHIP_NO_ERROR ? ESP_OK : ESP_ERR_INVALID_ARG; + } + + static esp_err_t SetActiveThreshold(Milliseconds32 activeThreshold) + { + if (ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT && + activeThreshold < Milliseconds32(5000)) { + return ESP_ERR_INVALID_ARG; + } + ICDConfigurationData::GetInstance().mActiveThreshold = activeThreshold; + return ESP_OK; + } +}; +} // namespace Test +} // namespace chip + +namespace esp_matter { +namespace icd { + +static esp_err_t set_polling_intervals(std::optional fast_interval_ms, + std::optional slow_interval_ms) +{ + if (slow_interval_ms.has_value()) { +#if !CHIP_CONFIG_ENABLE_ICD_LIT + if (slow_interval_ms.value() > 15000) { + return ESP_ERR_INVALID_ARG; + } +#endif + chip::Test::ICDConfigurationDataTestAccess::SetSlowPollingInterval(Milliseconds32(slow_interval_ms.value())); + } + if (fast_interval_ms.has_value()) { + chip::Test::ICDConfigurationDataTestAccess::SetFastPollingInterval(Milliseconds32(fast_interval_ms.value())); + } + return ESP_OK; +} + +static esp_err_t set_mode_durations(std::optional active_mode_duration_ms, + std::optional idle_mode_duration_s) +{ + Milliseconds32 active_mode_duration = active_mode_duration_ms.has_value() + ? Milliseconds32(active_mode_duration_ms.value()) + : chip::ICDConfigurationData::GetInstance().GetActiveModeDuration(); + Seconds32 idle_mode_duration = idle_mode_duration_s.has_value() + ? Seconds32(idle_mode_duration_s.value()) + : chip::ICDConfigurationData::GetInstance().GetIdleModeDuration(); + return chip::Test::ICDConfigurationDataTestAccess::SetModeDurations(chip::MakeOptional(active_mode_duration), + chip::MakeOptional(idle_mode_duration)); +} + +static esp_err_t set_active_threshold(uint32_t active_threshold_ms) +{ + return chip::Test::ICDConfigurationDataTestAccess::SetActiveThreshold(Milliseconds32(active_threshold_ms)); +} + +esp_err_t set_configuration_data(config_t *config) +{ + ESP_RETURN_ON_FALSE(!is_started(), ESP_ERR_INVALID_STATE, TAG, + "Could not change ICD configuration data after Matter is started"); + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "config cannot be NULL"); + ESP_RETURN_ON_ERROR(set_polling_intervals(config->fast_interval_ms, config->slow_interval_ms), TAG, + "Failed to set polling intervals"); + ESP_RETURN_ON_ERROR(set_mode_durations(config->active_mode_duration_ms, config->idle_mode_duration_s), TAG, + "Failed to set mode durations"); + ESP_RETURN_ON_ERROR(set_active_threshold(config->active_threshold_ms.value()), TAG, + "Failed to set active threshold"); + return ESP_OK; +} + +} // namespace icd +} // namespace esp_matter diff --git a/components/esp_matter/esp_matter_icd_configuration.h b/components/esp_matter/esp_matter_icd_configuration.h new file mode 100644 index 000000000..59f98efd1 --- /dev/null +++ b/components/esp_matter/esp_matter_icd_configuration.h @@ -0,0 +1,32 @@ +// 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 + +namespace esp_matter { +namespace icd { + +typedef struct config { + std::optional fast_interval_ms; + std::optional slow_interval_ms; + std::optional active_mode_duration_ms; + std::optional idle_mode_duration_s; + std::optional active_threshold_ms; +} config_t; + +esp_err_t set_configuration_data(config_t *config); + +} // namespace icd +} // namespace esp_matter diff --git a/components/esp_matter/zap_common/zap-generated/access.h b/components/esp_matter/zap_common/zap-generated/access.h index 82cd432f8..75bca1e55 100644 --- a/components/esp_matter/zap_common/zap-generated/access.h +++ b/components/esp_matter/zap_common/zap-generated/access.h @@ -15,6 +15,7 @@ 0x00000030, /* Cluster: General Commissioning, Attribute: TCMinRequiredVersion, Privilege: administer */ \ 0x00000030, /* Cluster: General Commissioning, Attribute: TCAcknowledgements, Privilege: administer */ \ 0x00000030, /* Cluster: General Commissioning, Attribute: TCAcknowledgementsRequired, Privilege: administer */ \ + 0x00000030, /* Cluster: General Commissioning, Attribute: TCUpdateDeadline, Privilege: administer */ \ 0x00000031, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ 0x00000031, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ 0x00000031, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \ @@ -47,6 +48,7 @@ 0x00000006, /* Cluster: General Commissioning, Attribute: TCMinRequiredVersion, Privilege: administer */ \ 0x00000007, /* Cluster: General Commissioning, Attribute: TCAcknowledgements, Privilege: administer */ \ 0x00000008, /* Cluster: General Commissioning, Attribute: TCAcknowledgementsRequired, Privilege: administer */ \ + 0x00000009, /* Cluster: General Commissioning, Attribute: TCUpdateDeadline, Privilege: administer */ \ 0x00000000, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ 0x00000001, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ 0x00000005, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \ @@ -79,6 +81,7 @@ chip::Access::Privilege::kAdminister, /* Cluster: General Commissioning, Attribute: TCMinRequiredVersion, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: General Commissioning, Attribute: TCAcknowledgements, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: General Commissioning, Attribute: TCAcknowledgementsRequired, Privilege: administer */ \ + chip::Access::Privilege::kAdminister, /* Cluster: General Commissioning, Attribute: TCUpdateDeadline, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: Network Commissioning, Attribute: MaxNetworks, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: Network Commissioning, Attribute: Networks, Privilege: administer */ \ chip::Access::Privilege::kAdminister, /* Cluster: Network Commissioning, Attribute: LastNetworkingStatus, Privilege: administer */ \