components/esp_matter: Support to get optional bits while initialisation of delegates.

Fixes: https://github.com/espressif/esp-matter/issues/1471
This commit is contained in:
Rohit
2025-07-14 16:50:54 +05:30
committed by Shubham Patil
parent 61e2d88a01
commit 7138fd3867
6 changed files with 193 additions and 10 deletions
@@ -609,6 +609,18 @@ esp_err_t enable_all()
}
return ESP_OK;
}
bool is_attribute_enabled(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id)
{
attribute_t *attr = attribute::get(endpoint_id, cluster_id, attribute_id);
return (attr != nullptr);
}
bool is_command_enabled(uint16_t endpoint_id, uint32_t cluster_id, uint32_t command_id)
{
command_t *cmd = command::get(endpoint_id, cluster_id, command_id);
return (cmd != nullptr);
}
} /* endpoint */
namespace attribute {
@@ -380,6 +380,29 @@ esp_err_t set_identify(uint16_t endpoint_id, void *identify);
*/
esp_err_t enable(endpoint_t *endpoint);
/** Check if attribute is enabled
*
* Check if the attribute of a cluster is enabled on an endpoint.
*
* @param[in] endpoint_id Endpoint id.
* @param[in] cluster_id Cluster id.
* @param[in] attribute_id Attribute id.
*
* @return true if an attribute is enabled otherwise false.
*/
bool is_attribute_enabled(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id);
/** Check if command is enabled
*
* Check if the command of a cluster is enabled on an endpoint.
*
* @param[in] endpoint_id Endpoint id.
* @param[in] cluster_id Cluster id.
* @param[in] command_id Command id.
*
* @return true if a command is enabled otherwise false.
*/
bool is_command_enabled(uint16_t endpoint_id, uint32_t cluster_id, uint32_t command_id);
} /* endpoint */
namespace cluster {
@@ -36,7 +36,7 @@
#include <app/clusters/window-covering-server/window-covering-server.h>
#include <app/clusters/dishwasher-alarm-server/dishwasher-alarm-server.h>
#include <app/clusters/keypad-input-server/keypad-input-server.h>
#include <app/clusters/mode-select-server//supported-modes-manager.h>
#include <app/clusters/mode-select-server/supported-modes-manager.h>
#include <app/clusters/thread-border-router-management-server/thread-border-router-management-server.h>
#include <app/clusters/water-heater-management-server/water-heater-management-server.h>
#include <app/clusters/energy-preference-server/energy-preference-server.h>
@@ -60,11 +60,118 @@ static uint32_t get_feature_map_value(uint16_t endpoint_id, uint32_t cluster_id)
uint32_t attribute_id = Globals::Attributes::FeatureMap::Id;
attribute_t *attribute = attribute::get(endpoint_id, cluster_id, attribute_id);
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
esp_matter_attr_val_t val = esp_matter_invalid(nullptr);
attribute::get_val(attribute, &val);
return val.val.u32;
}
// Cluster-specific optional attributes handlers
chip::BitMask<EnergyEvse::OptionalAttributes> get_energy_evse_enabled_optional_attributes(uint16_t endpoint_id)
{
chip::BitMask<EnergyEvse::OptionalAttributes> optional_attrs = 0;
if (endpoint::is_attribute_enabled(endpoint_id, EnergyEvse::Id, EnergyEvse::Attributes::UserMaximumChargeCurrent::Id)) {
optional_attrs.Set(EnergyEvse::OptionalAttributes::kSupportsUserMaximumChargingCurrent);
}
if (endpoint::is_attribute_enabled(endpoint_id, EnergyEvse::Id, EnergyEvse::Attributes::RandomizationDelayWindow::Id)) {
optional_attrs.Set(EnergyEvse::OptionalAttributes::kSupportsRandomizationWindow);
}
if (endpoint::is_attribute_enabled(endpoint_id, EnergyEvse::Id, EnergyEvse::Attributes::ApproximateEVEfficiency::Id)) {
optional_attrs.Set(EnergyEvse::OptionalAttributes::kSupportsApproximateEvEfficiency);
}
return optional_attrs;
}
chip::BitMask<PowerTopology::OptionalAttributes> get_power_topology_enabled_optional_attributes(uint16_t endpoint_id)
{
chip::BitMask<PowerTopology::OptionalAttributes> optional_attrs = 0;
if (endpoint::is_attribute_enabled(endpoint_id, PowerTopology::Id, PowerTopology::Attributes::AvailableEndpoints::Id)) {
optional_attrs.Set(PowerTopology::OptionalAttributes::kOptionalAttributeAvailableEndpoints);
}
if (endpoint::is_attribute_enabled(endpoint_id, PowerTopology::Id, PowerTopology::Attributes::ActiveEndpoints::Id)) {
optional_attrs.Set(PowerTopology::OptionalAttributes::kOptionalAttributeActiveEndpoints);
}
return optional_attrs;
}
chip::BitMask<ElectricalPowerMeasurement::OptionalAttributes> get_electrical_power_measurement_enabled_optional_attributes(uint16_t endpoint_id)
{
chip::BitMask<ElectricalPowerMeasurement::OptionalAttributes> optional_attrs = 0;
// Check for various optional attributes
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::Ranges::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRanges);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::Voltage::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeVoltage);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::ActiveCurrent::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeActiveCurrent);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::ReactiveCurrent::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactiveCurrent);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::ApparentCurrent::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentCurrent);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::ReactivePower::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactivePower);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::ApparentPower::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentPower);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::RMSVoltage::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSVoltage);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::RMSCurrent::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSCurrent);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::RMSPower::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSPower);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::Frequency::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeFrequency);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::PowerFactor::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributePowerFactor);
}
if (endpoint::is_attribute_enabled(endpoint_id, ElectricalPowerMeasurement::Id, ElectricalPowerMeasurement::Attributes::NeutralCurrent::Id)) {
optional_attrs.Set(ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeNeutralCurrent);
}
return optional_attrs;
}
// Cluster-specific optional commands handlers
chip::BitMask<EnergyEvse::OptionalCommands> get_energy_evse_enabled_optional_commands(uint16_t endpoint_id)
{
chip::BitMask<EnergyEvse::OptionalCommands> optional_cmds = 0;
if (endpoint::is_command_enabled(endpoint_id, EnergyEvse::Id, EnergyEvse::Commands::StartDiagnostics::Id)) {
optional_cmds.Set(EnergyEvse::OptionalCommands::kSupportsStartDiagnostics);
}
return optional_cmds;
}
namespace delegate_cb {
void InitModeDelegate(void *delegate, uint16_t endpoint_id, uint32_t cluster_id)
@@ -140,8 +247,10 @@ void EnergyEvseDelegateInitCB(void *delegate, uint16_t endpoint_id)
static EnergyEvse::Instance * energyEvseInstance = nullptr;
EnergyEvse::Delegate *energy_evse_delegate = static_cast<EnergyEvse::Delegate*>(delegate);
uint32_t feature_map = get_feature_map_value(endpoint_id, EnergyEvse::Id);
chip::BitMask<EnergyEvse::OptionalAttributes> optional_attrs = get_energy_evse_enabled_optional_attributes(endpoint_id);
chip::BitMask<EnergyEvse::OptionalCommands> optional_cmds = get_energy_evse_enabled_optional_commands(endpoint_id);
energyEvseInstance = new EnergyEvse::Instance(endpoint_id, *energy_evse_delegate, chip::BitMask<EnergyEvse::Feature, uint32_t>(feature_map),
chip::BitMask<EnergyEvse::OptionalAttributes, uint32_t>(), chip::BitMask<EnergyEvse::OptionalCommands, uint32_t>());
optional_attrs, optional_cmds);
energyEvseInstance->Init();
}
@@ -287,8 +396,9 @@ void PowerTopologyDelegateInitCB(void *delegate, uint16_t endpoint_id)
static PowerTopology::Instance * powerTopologyInstance = nullptr;
PowerTopology::Delegate *power_topology_delegate = static_cast<PowerTopology::Delegate*>(delegate);
uint32_t feature_map = get_feature_map_value(endpoint_id, PowerTopology::Id);
chip::BitMask<PowerTopology::OptionalAttributes> optional_attrs = get_power_topology_enabled_optional_attributes(endpoint_id);
powerTopologyInstance = new PowerTopology::Instance(endpoint_id, *power_topology_delegate, chip::BitMask<PowerTopology::Feature,
uint32_t>(feature_map), chip::BitMask<PowerTopology::OptionalAttributes, uint32_t>(0));
uint32_t>(feature_map), optional_attrs);
powerTopologyInstance->Init();
}
@@ -298,9 +408,9 @@ void ElectricalPowerMeasurementDelegateInitCB(void *delegate, uint16_t endpoint_
static ElectricalPowerMeasurement::Instance * electricalPowerMeasurementInstance = nullptr;
ElectricalPowerMeasurement::Delegate *electrical_power_measurement_delegate = static_cast<ElectricalPowerMeasurement::Delegate*>(delegate);
uint32_t feature_map = get_feature_map_value(endpoint_id, ElectricalPowerMeasurement::Id);
chip::BitMask<ElectricalPowerMeasurement::OptionalAttributes> optional_attrs = get_electrical_power_measurement_enabled_optional_attributes(endpoint_id);
electricalPowerMeasurementInstance = new ElectricalPowerMeasurement::Instance(endpoint_id, *electrical_power_measurement_delegate,
chip::BitMask<ElectricalPowerMeasurement::Feature, uint32_t>(feature_map),
chip::BitMask<ElectricalPowerMeasurement::OptionalAttributes, uint32_t>(0));
chip::BitMask<ElectricalPowerMeasurement::Feature, uint32_t>(feature_map), optional_attrs);
electricalPowerMeasurementInstance->Init();
}
@@ -346,7 +456,7 @@ void ThreadBorderRouterManagementDelegateInitCB(void *delegate, uint16_t endpoin
attribute_t *attribute = attribute::get(endpoint_id, ThreadBorderRouterManagement::Id, Globals::Attributes::FeatureMap::Id);
assert(attribute != nullptr);
/* Update the value if the attribute already exists */
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
esp_matter_attr_val_t val = esp_matter_invalid(nullptr);
attribute::get_val(attribute, &val);
bool pan_change_supported = (val.val.u32 & thread_border_router_management::feature::pan_change::get_id()) ? true : false;
ThreadBorderRouterManagement::Delegate *thread_br_delegate = static_cast<ThreadBorderRouterManagement::Delegate *>(delegate);
@@ -358,7 +468,7 @@ void ThreadBorderRouterManagementDelegateInitCB(void *delegate, uint16_t endpoin
void ServiceAreaDelegateInitCB(void *delegate, uint16_t endpoint_id)
{
// TODO: This cluster have two delegates we need to update exsiting delegate logic to accomodate multiple delegates.
// TODO: This cluster has two delegates. We need to update existing delegate logic to accommodate multiple delegates.
}
void WaterHeaterManagementDelegateInitCB(void *delegate, uint16_t endpoint_id)
@@ -39,6 +39,15 @@ static std::unique_ptr<ElectricalPowerMeasurementDelegate> gEPMDelegate;
// Global pointer to our ElectricalPowerMeasurementInstance
static std::unique_ptr<ElectricalPowerMeasurementInstance> gEPMInstance;
CHIP_ERROR PowerTopology::PowerTopologyDelegate::GetAvailableEndpointAtIndex(size_t index, EndpointId & endpointId)
{
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}
CHIP_ERROR PowerTopology::PowerTopologyDelegate::GetActiveEndpointAtIndex(size_t index, EndpointId & endpointId)
{
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}
// Example of how to create and send energy measurement events
esp_err_t send_energy_measurement_events(uint16_t endpoint_id)
{
@@ -45,6 +45,33 @@ esp_err_t send_energy_measurement_events(uint16_t endpoint_id);
}
#endif
#include <app/clusters/power-topology-server/power-topology-server.h>
using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::PowerTopology;
namespace chip {
namespace app {
namespace Clusters {
namespace PowerTopology {
class PowerTopologyDelegate : public Delegate
{
public:
~PowerTopologyDelegate() = default;
CHIP_ERROR GetAvailableEndpointAtIndex(size_t index, EndpointId & endpointId) override;
CHIP_ERROR GetActiveEndpointAtIndex(size_t index, EndpointId & endpointId) override;
};
} // namespace PowerTopology
} // namespace Clusters
} // namespace app
} // namespace chip
/**
* Electrical Power Measurement Delegate implementation
*/
@@ -162,4 +189,4 @@ private:
} // namespace ElectricalPowerMeasurement
} // namespace Clusters
} // namespace app
} // namespace chip
} // namespace chip
@@ -168,6 +168,7 @@ static void initialize_console(void)
namespace esp_matter {
static chip::app::Clusters::PowerTopology::PowerTopologyDelegate powerTopologyDelegate;
namespace data_model {
int create(uint8_t device_type_index)
@@ -454,7 +455,8 @@ int create(uint8_t device_type_index)
}
case ESP_MATTER_ELECTRICAL_SENSOR: {
esp_matter::endpoint::electrical_sensor::config_t electrical_sensor_config;
electrical_sensor_config.power_topology.feature_flags = esp_matter::cluster::power_topology::feature::node_topology::get_id();
electrical_sensor_config.power_topology.feature_flags = esp_matter::cluster::power_topology::feature::set_topology::get_id();
electrical_sensor_config.power_topology.delegate = &powerTopologyDelegate;
electrical_sensor_config.electrical_power_measurement.feature_flags =
esp_matter::cluster::electrical_power_measurement::feature::direct_current::get_id() |
esp_matter::cluster::electrical_power_measurement::feature::alternating_current::get_id();