From 8164d351b1349c7f0772d84b836a001bab76a984 Mon Sep 17 00:00:00 2001 From: mahesh Date: Mon, 2 Feb 2026 16:15:38 +0530 Subject: [PATCH] components/esp_matter:Add missing feature for device energy management cluster Replace at most validation check with exact one for closure dimension cluster - removed at most validation macro - add features for door lock, microwave oven, device energy management, energy evse devices in all device type app to make them conformant --- .../data_model/esp_matter_cluster.cpp | 42 ++++++++++++++----- .../data_model/esp_matter_cluster.h | 3 +- .../main/esp_matter_console_helpers.cpp | 12 +++++- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/components/esp_matter/data_model/esp_matter_cluster.cpp b/components/esp_matter/data_model/esp_matter_cluster.cpp index cfaa0dda5..2a8ad2ba1 100644 --- a/components/esp_matter/data_model/esp_matter_cluster.cpp +++ b/components/esp_matter/data_model/esp_matter_cluster.cpp @@ -57,7 +57,6 @@ namespace { enum class feature_policy { k_exact_one = 0, // O.a k_at_least_one = 1, // 0.a+ - k_at_most_one = 2, // 0.a- }; const char feature_policy_strs[3][16] = {"Exactly one", "At least one", "At most one"}; @@ -81,9 +80,6 @@ bool validate_features(uint32_t feature_flag, feature_policy policy, case feature_policy::k_at_least_one: result = count >= 1; break; - case feature_policy::k_at_most_one: - result = count <= 1; - break; } if (!result) { @@ -102,10 +98,6 @@ bool validate_features(uint32_t feature_flag, feature_policy policy, do { if (!validate_features(config->feature_flags, feature_policy::k_at_least_one, name, {__VA_ARGS__})) \ return ABORT_CLUSTER_CREATE(cluster); } while(0) -#define VALIDATE_FEATURES_AT_MOST_ONE(name, ...) \ - do { if (!validate_features(config->feature_flags, feature_policy::k_at_most_one, name, {__VA_ARGS__})) \ - return ABORT_CLUSTER_CREATE(cluster); } while(0) - } // anonymous namespace namespace esp_matter { @@ -903,7 +895,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) global::attribute::create_feature_map(cluster, config->feature_flags); // check against O.a feature conformance for Wired and Battery - VALIDATE_FEATURES_EXACT_ONE("PowerSource,Battery", feature::wired::get_id(), feature::battery::get_id()); + VALIDATE_FEATURES_EXACT_ONE("Wired, Battery", feature::wired::get_id(), feature::battery::get_id()); /* Features */ if (has(feature::wired::get_id())) { @@ -3360,6 +3352,34 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) attribute::create_abs_max_power(cluster, 0); /** Attributes not managed internally **/ global::attribute::create_cluster_revision(cluster, cluster_revision); + if ((!(has(feature::power_adjustment::get_id())))) { + VALIDATE_FEATURES_EXACT_ONE("PowerForecastReporting,StateForecastReporting", + feature::power_forecast_reporting::get_id(), feature::state_forecast_reporting::get_id()); + if (has(feature::power_forecast_reporting::get_id())) { + VerifyOrReturnValue(feature::power_forecast_reporting::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::state_forecast_reporting::get_id())) { + VerifyOrReturnValue(feature::state_forecast_reporting::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + } + if (has(feature::start_time_adjustment::get_id()) || has(feature::pausable::get_id()) || has(feature::forecast_adjustment::get_id()) || has(feature::constraint_based_adjustment::get_id())) { + VerifyOrReturnValue(feature::power_forecast_reporting::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::power_adjustment::get_id())) { + VerifyOrReturnValue(feature::power_adjustment::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::start_time_adjustment::get_id())) { + VerifyOrReturnValue(feature::start_time_adjustment::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::pausable::get_id())) { + VerifyOrReturnValue(feature::pausable::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::forecast_adjustment::get_id())) { + VerifyOrReturnValue(feature::forecast_adjustment::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } + if (has(feature::constraint_based_adjustment::get_id())) { + VerifyOrReturnValue(feature::constraint_based_adjustment::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); + } cluster::set_init_and_shutdown_callbacks(cluster, ESPMatterDeviceEnergyManagementClusterServerInitCallback, ESPMatterDeviceEnergyManagementClusterServerShutdownCallback); } @@ -4173,8 +4193,8 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) if (has(feature::positioning::get_id())) { VerifyOrReturnValue(feature::positioning::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); - VALIDATE_FEATURES_AT_MOST_ONE("Translation, Rotation, Modulation", - feature::translation::get_id(), feature::rotation::get_id(), feature::modulation::get_id()); + VALIDATE_FEATURES_EXACT_ONE("Translation, Rotation, Modulation", + feature::translation::get_id(), feature::rotation::get_id(), feature::modulation::get_id()); if (has(feature::translation::get_id())) { VerifyOrReturnValue(feature::translation::add(cluster) == ESP_OK, ABORT_CLUSTER_CREATE(cluster)); } diff --git a/components/esp_matter/data_model/esp_matter_cluster.h b/components/esp_matter/data_model/esp_matter_cluster.h index c23b1216f..445956505 100644 --- a/components/esp_matter/data_model/esp_matter_cluster.h +++ b/components/esp_matter/data_model/esp_matter_cluster.h @@ -842,7 +842,8 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); namespace device_energy_management { typedef struct config { void *delegate; - config() : delegate(nullptr) {} + uint32_t feature_flags; + config() : delegate(nullptr), feature_flags(0) {} } config_t; cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); diff --git a/examples/all_device_types_app/main/esp_matter_console_helpers.cpp b/examples/all_device_types_app/main/esp_matter_console_helpers.cpp index 5c9d62df6..3eb98b30b 100644 --- a/examples/all_device_types_app/main/esp_matter_console_helpers.cpp +++ b/examples/all_device_types_app/main/esp_matter_console_helpers.cpp @@ -292,6 +292,12 @@ int create(uint8_t device_type_index) case ESP_MATTER_DOOR_LOCK: { esp_matter::endpoint::door_lock::config_t door_lock_config; endpoint = esp_matter::endpoint::door_lock::create(node, &door_lock_config, ENDPOINT_FLAG_NONE, NULL); + cluster_t *door_lock_cluster = cluster::get(endpoint, chip::app::Clusters::DoorLock::Id); + VerifyOrReturnError(door_lock_cluster, ESP_ERR_INVALID_STATE, ESP_LOGE(TAG, "Failed to get door lock cluster")); + cluster::door_lock::feature::pin_credential::config_t pin_credential_config; + cluster::door_lock::feature::user::config_t user_config; + cluster::door_lock::feature::pin_credential::add(door_lock_cluster, &pin_credential_config); + cluster::door_lock::feature::user::add(door_lock_cluster, &user_config); break; } case ESP_MATTER_WINDOW_COVERING_DEVICE: { @@ -500,6 +506,8 @@ int create(uint8_t device_type_index) case ESP_MATTER_ENERGY_EVSE: { esp_matter::endpoint::energy_evse::config_t energy_evse_config; endpoint = esp_matter::endpoint::energy_evse::create(node, &energy_evse_config, ENDPOINT_FLAG_NONE, NULL); + cluster_t *energy_evse_cluster = cluster::get(endpoint, chip::app::Clusters::EnergyEvse::Id); + cluster::energy_evse::feature::charging_preferences::add(energy_evse_cluster); esp_matter::endpoint::power_source::config_t power_source_config; esp_matter::endpoint_t *ps_endpoint = esp_matter::endpoint::power_source::create(node, &power_source_config, ENDPOINT_FLAG_NONE, NULL); @@ -514,6 +522,7 @@ int create(uint8_t device_type_index) } case ESP_MATTER_MICROWAVE_OVEN: { esp_matter::endpoint::microwave_oven::config_t microwave_oven_config; + microwave_oven_config.microwave_oven_control.feature_flags = esp_matter::cluster::microwave_oven_control::feature::power_as_number::get_id(); endpoint = esp_matter::endpoint::microwave_oven::create(node, µwave_oven_config, ENDPOINT_FLAG_NONE, NULL); break; } @@ -534,6 +543,7 @@ int create(uint8_t device_type_index) } case ESP_MATTER_DEVICE_ENERGY_MANAGEMENT: { esp_matter::endpoint::device_energy_management::config_t device_energy_management_config; + device_energy_management_config.device_energy_management.feature_flags = esp_matter::cluster::device_energy_management::feature::power_forecast_reporting::get_id(); endpoint = esp_matter::endpoint::device_energy_management::create(node, &device_energy_management_config, ENDPOINT_FLAG_NONE, NULL); break; } @@ -615,7 +625,7 @@ int create(uint8_t device_type_index) } case ESP_MATTER_CLOSURE_PANEL: { esp_matter::endpoint::closure_panel::config_t closure_panel_config; - closure_panel_config.closure_dimension.feature_flags = cluster::closure_dimension::feature::positioning::get_id(); + closure_panel_config.closure_dimension.feature_flags = cluster::closure_dimension::feature::positioning::get_id() | cluster::closure_dimension::feature::rotation::get_id(); endpoint = esp_matter::endpoint::closure_panel::create(node, &closure_panel_config, ENDPOINT_FLAG_NONE, NULL); break; }