diff --git a/SUPPORTED_DEVICE_TYPES.md b/SUPPORTED_DEVICE_TYPES.md index 705d1264a..2839d1dd1 100644 --- a/SUPPORTED_DEVICE_TYPES.md +++ b/SUPPORTED_DEVICE_TYPES.md @@ -9,6 +9,7 @@ Utility Device Types 4. OTA Provider 5. Aggregator 6. Bridged Node +7. Electrical Sensor Application Device Types @@ -53,6 +54,7 @@ g. Sensors 7. Flow Sensor 8. Smoke CO Alarm 9. Water Leak Detector +10. Rain Sensor h. Robotic 1. Robotic Vacuum Cleaner diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index ca002f4f1..f511f785c 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -4117,5 +4117,162 @@ attribute_t *create_current_mode(cluster_t *cluster, uint8_t value) } /* attribute */ } /* rvc_clean_mode */ +namespace power_topology { +namespace attribute { + +attribute_t *create_available_endpoints(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, PowerTopology::Attributes::AvailableEndpoints::Id, ATTRIBUTE_FLAG_NONE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_active_endpoints(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, PowerTopology::Attributes::ActiveEndpoints::Id, ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_array((uint8_t*)value, length, count)); +} + +} /* attribute */ +} /* power_topology */ + +namespace electrical_power_measurement { +namespace attribute { +attribute_t *create_power_mode(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::PowerMode::Id, ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); +} + +attribute_t *create_number_of_measurement_types(cluster_t *cluster, const uint8_t value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::NumberOfMeasurementTypes::Id, ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); +} + +attribute_t *create_accuracy(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::Accuracy::Id, ATTRIBUTE_FLAG_NONE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_ranges(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::Ranges::Id, ATTRIBUTE_FLAG_NONE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_voltage(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::Voltage::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_active_current(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ActiveCurrent::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_reactive_current(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ReactiveCurrent::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_apparent_current(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ApparentCurrent::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_active_power(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ActivePower::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_reactive_power(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ReactivePower::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_apparent_power(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::ApparentPower::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_rms_voltage(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::RMSVoltage::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_rms_current(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::RMSCurrent::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_rms_power(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::RMSPower::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_frequency(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::Frequency::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_harmonic_currents(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::HarmonicCurrents::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_harmonic_phases(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::HarmonicPhases::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_power_factor(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::PowerFactor::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +attribute_t *create_neutral_current(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, ElectricalPowerMeasurement::Attributes::NeutralCurrent::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int64(value)); +} + +} /* attribute */ +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +namespace attribute { +attribute_t *create_accuracy(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes::Accuracy::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_cumulative_energy_imported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes:: + CumulativeEnergyImported::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_cumulative_energy_exported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes:: + CumulativeEnergyExported::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_periodic_energy_imported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes:: + PeriodicEnergyImported::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_periodic_energy_exported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes:: + PeriodicEnergyExported::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +attribute_t *create_cumulative_energy_reset(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, ElectricalEnergyMeasurement::Attributes:: + CumulativeEnergyReset::Id, ATTRIBUTE_FLAG_NULLABLE, esp_matter_array((uint8_t*)value, length, count)); +} + +} /* attribute */ +} /* electrical_energy_measurement */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 5b6410748..b885d2b5d 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -948,5 +948,47 @@ attribute_t *create_current_mode(cluster_t *cluster, uint8_t value); } /* attribute */ } /* rvc_clean_mode */ +namespace power_topology { +namespace attribute { +attribute_t *create_available_endpoints(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +attribute_t *create_active_endpoints(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +} /* attribute */ +} /* power_topology */ + +namespace electrical_power_measurement { +namespace attribute { +attribute_t *create_power_mode(cluster_t *cluster, uint8_t value); +attribute_t *create_number_of_measurement_types(cluster_t *cluster, const uint8_t value); +attribute_t *create_accuracy(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +attribute_t *create_ranges(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +attribute_t *create_voltage(cluster_t *cluster, nullable value); +attribute_t *create_active_current(cluster_t *cluster, nullable value); +attribute_t *create_reactive_current(cluster_t *cluster, nullable value); +attribute_t *create_apparent_current(cluster_t *cluster, nullable value); +attribute_t *create_active_power(cluster_t *cluster, nullable value); +attribute_t *create_reactive_power(cluster_t *cluster, nullable value); +attribute_t *create_apparent_power(cluster_t *cluster, nullable value); +attribute_t *create_rms_voltage(cluster_t *cluster, nullable value); +attribute_t *create_rms_current(cluster_t *cluster, nullable value); +attribute_t *create_rms_power(cluster_t *cluster, nullable value); +attribute_t *create_frequency(cluster_t *cluster, nullable value); +attribute_t *create_harmonic_currents(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +attribute_t *create_harmonic_phases(cluster_t *cluster, const uint8_t * value, uint16_t length, uint16_t count); +attribute_t *create_power_factor(cluster_t *cluster, nullable value); +attribute_t *create_neutral_current(cluster_t *cluster, nullable value); +} /* attribute */ +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +namespace attribute { +attribute_t *create_accuracy(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +attribute_t *create_cumulative_energy_imported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +attribute_t *create_cumulative_energy_exported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +attribute_t *create_periodic_energy_imported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +attribute_t *create_periodic_energy_exported(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +attribute_t *create_cumulative_energy_reset(cluster_t *cluster, const uint8_t* value, uint16_t length, uint16_t count); +} /* attribute */ +} /* electrical_energy_measurement */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index 25d1950d6..b73830028 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -3377,6 +3377,178 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) } } /* keypad_input */ +namespace power_topology { +const function_generic_t *function_list = NULL; +const int function_flags = CLUSTER_FLAG_NONE; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features) +{ + cluster_t *cluster = cluster::create(endpoint, PowerTopology::Id, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_FLAG_SERVER) { + add_function_list(cluster, function_list, function_flags); + } + + if (flags & CLUSTER_FLAG_SERVER) { + /* Attributes managed internally */ + global::attribute::create_feature_map(cluster, 0); +#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE + global::attribute::create_event_list(cluster, NULL, 0, 0); +#endif + + /* Attributes not managed internally */ + if (config) { + global::attribute::create_cluster_revision(cluster, config->cluster_revision); + } else { + ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes."); + } + } + + /* Features */ + if (features & feature::node_topology::get_id()) { + feature::node_topology::add(cluster); + } + else if (features & feature::tree_topology::get_id()) { + feature::tree_topology::add(cluster); + } + else if (features & feature::set_topology::get_id()) { + feature::set_topology::add(cluster); + if (features & feature::dynamic_power_flow::get_id()) { + feature::dynamic_power_flow::add(cluster); + } + } + + return cluster; +} +} /* power_topology */ + +namespace electrical_power_measurement { +const function_generic_t *function_list = NULL; +const int function_flags = CLUSTER_FLAG_NONE; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features) +{ + cluster_t *cluster = cluster::create(endpoint, ElectricalPowerMeasurement::Id, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_FLAG_SERVER) { + add_function_list(cluster, function_list, function_flags); + } + + if (flags & CLUSTER_FLAG_SERVER) { + /* Attributes managed internally */ + global::attribute::create_feature_map(cluster, 0); +#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE + global::attribute::create_event_list(cluster, NULL, 0, 0); +#endif + attribute::create_power_mode(cluster, 0); + attribute::create_number_of_measurement_types(cluster, 0); + attribute::create_accuracy(cluster, NULL, 0, 0); + attribute::create_active_power(cluster, 0); + /* Attributes not managed internally */ + if (config) { + global::attribute::create_cluster_revision(cluster, config->cluster_revision); + } else { + ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes."); + } + } + + /* Features */ + if((features & feature::direct_current::get_id()) || (features & feature::alternating_current::get_id())) { + if (features & feature::direct_current::get_id()) { + feature::direct_current::add(cluster); + } + if (features & feature::alternating_current::get_id()) { + feature::alternating_current::add(cluster); + + if (features & feature::polyphase_power::get_id()) { + feature::polyphase_power::add(cluster); + } + + if (features & feature::harmonics::get_id()) { + feature::harmonics::add(cluster); + } + + if (features & feature::power_quality::get_id()) { + feature::power_quality::add(cluster); + } + } + } else { + ESP_LOGE(TAG, "At least one of the feature from Direct Current, Alternating Current shall be supported."); + return NULL; + } + + return cluster; +} +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +const function_generic_t *function_list = NULL; +const int function_flags = CLUSTER_FLAG_NONE; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features) +{ + cluster_t *cluster = cluster::create(endpoint, ElectricalEnergyMeasurement::Id, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + + if (flags & CLUSTER_FLAG_SERVER) { + add_function_list(cluster, function_list, function_flags); + } + + if (flags & CLUSTER_FLAG_SERVER) { + /* Attributes managed internally */ + global::attribute::create_feature_map(cluster, 0); +#if CHIP_CONFIG_ENABLE_EVENTLIST_ATTRIBUTE + global::attribute::create_event_list(cluster, NULL, 0, 0); +#endif + attribute::create_accuracy(cluster, NULL, 0, 0); + /* Attributes not managed internally */ + if (config) { + global::attribute::create_cluster_revision(cluster, config->cluster_revision); + } else { + ESP_LOGE(TAG, "Config is NULL. Cannot add some attributes."); + } + } + + /* Features */ + if((features & feature::imported_energy::get_id()) || (features & feature::exported_energy::get_id())) { + if (features & feature::imported_energy::get_id()) { + feature::imported_energy::add(cluster); + } + if (features & feature::exported_energy::get_id()) { + feature::exported_energy::add(cluster); + } + } else { + ESP_LOGE(TAG, "At least one of the feature from Imported Energy, Exported Energy shall be supported."); + return NULL; + } + + if((features & feature::cumulative_energy::get_id()) || (features & feature::periodic_energy::get_id())) { + if (features & feature::cumulative_energy::get_id()) { + feature::cumulative_energy::add(cluster); + } + if (features & feature::periodic_energy::get_id()) { + feature::periodic_energy::add(cluster); + } + } else { + ESP_LOGE(TAG, "At least one of the feature from Cumulative Energy, Periodic Energy shall be supported."); + return NULL; + } + + return cluster; +} +} /* electrical_energy_measurement */ + // namespace binary_input_basic { // // ToDo // } /* binary_input_basic */ diff --git a/components/esp_matter/esp_matter_cluster.h b/components/esp_matter/esp_matter_cluster.h index 482d87289..5393b9a7f 100644 --- a/components/esp_matter/esp_matter_cluster.h +++ b/components/esp_matter/esp_matter_cluster.h @@ -824,5 +824,32 @@ typedef struct config { cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); } /* keypad_input */ +namespace power_topology { +typedef struct config { + uint16_t cluster_revision; + config() : cluster_revision(1) {} +} config_t; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features); +} /* power_topology */ + +namespace electrical_power_measurement { +typedef struct config { + uint16_t cluster_revision; + config() : cluster_revision(1) {} +} config_t; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features); +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +typedef struct config { + uint16_t cluster_revision; + config() : cluster_revision(1) {} +} config_t; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features); +} /* electrical_energy_measurement */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_endpoint.cpp b/components/esp_matter/esp_matter_endpoint.cpp index 02e8d7cc9..954d5906f 100644 --- a/components/esp_matter/esp_matter_endpoint.cpp +++ b/components/esp_matter/esp_matter_endpoint.cpp @@ -1555,6 +1555,47 @@ esp_err_t add(endpoint_t *endpoint, config_t *config) } } /* rain_sensor */ +namespace electrical_sensor { +uint32_t get_device_type_id() +{ + return ESP_MATTER_ELECTRICAL_SENSOR_DEVICE_TYPE_ID; +} + +uint8_t get_device_type_version() +{ + return ESP_MATTER_ELECTRICAL_SENSOR_DEVICE_TYPE_VERSION; +} + +endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data) +{ + endpoint_t *endpoint = endpoint::create(node, flags, priv_data); + add(endpoint, config); + return endpoint; +} + +esp_err_t add(endpoint_t *endpoint, config_t *config) +{ + if (!endpoint) { + ESP_LOGE(TAG, "Endpoint cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = add_device_type(endpoint, get_device_type_id(), get_device_type_version()); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to add device type id:%" PRIu32 ",err: %d", get_device_type_id(), err); + return err; + } + + descriptor::create(endpoint, &(config->descriptor), CLUSTER_FLAG_SERVER); + power_topology::create(endpoint, &(config->power_topology), CLUSTER_FLAG_SERVER, + power_topology::feature::set_topology::get_id()); + electrical_power_measurement::create(endpoint, &(config->electrical_power_measurement), CLUSTER_FLAG_SERVER, + electrical_power_measurement::feature::direct_current::get_id() + | electrical_power_measurement::feature::alternating_current::get_id()); + + return ESP_OK; +} +} /* electrical_sensor */ + } /* endpoint */ namespace node { diff --git a/components/esp_matter/esp_matter_endpoint.h b/components/esp_matter/esp_matter_endpoint.h index eeb944db4..a5b1e3ee7 100644 --- a/components/esp_matter/esp_matter_endpoint.h +++ b/components/esp_matter/esp_matter_endpoint.h @@ -100,6 +100,8 @@ #define ESP_MATTER_WATER_LEAK_DETECTOR_DEVICE_TYPE_VERSION 1 #define ESP_MATTER_RAIN_SENSOR_DEVICE_TYPE_ID 0x0044 #define ESP_MATTER_RAIN_SENSOR_DEVICE_TYPE_VERSION 1 +#define ESP_MATTER_ELECTRICAL_SENSOR_DEVICE_TYPE_ID 0x0510 +#define ESP_MATTER_ELECTRICAL_SENSOR_DEVICE_TYPE_VERSION 1 namespace esp_matter { @@ -636,6 +638,19 @@ endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_dat esp_err_t add(endpoint_t *endpoint, config_t *config); } /* rain_sensor */ +namespace electrical_sensor { +typedef struct config { + cluster::descriptor::config_t descriptor; + cluster::power_topology::config_t power_topology; + cluster::electrical_power_measurement::config_t electrical_power_measurement; +} config_t; + +uint32_t get_device_type_id(); +uint8_t get_device_type_version(); +endpoint_t *create(node_t *node, config_t *config, uint8_t flags, void *priv_data); +esp_err_t add(endpoint_t *endpoint, config_t *config); +} /* electrical_sensor */ + } /* endpoint */ namespace node { diff --git a/components/esp_matter/esp_matter_event.cpp b/components/esp_matter/esp_matter_event.cpp index d93f18b1c..a86fcc00e 100644 --- a/components/esp_matter/esp_matter_event.cpp +++ b/components/esp_matter/esp_matter_event.cpp @@ -680,5 +680,30 @@ esp_err_t send_turbine_operation() } // namespace event } // namespace pump_configuration_and_control +namespace electrical_power_measurement { +namespace event { + +event_t *create_measurement_period_ranges(cluster_t *cluster) +{ + return esp_matter::event::create(cluster, ElectricalPowerMeasurement::Events::MeasurementPeriodRanges::Id); +} +} // namespace event +} // namespace electrical_power_measurement + +namespace electrical_energy_measurement { +namespace event { + +event_t *create_cumulative_energy_measured(cluster_t *cluster) +{ + return esp_matter::event::create(cluster, ElectricalEnergyMeasurement::Events::CumulativeEnergyMeasured::Id); +} + +event_t *create_periodic_energy_measured(cluster_t *cluster) +{ + return esp_matter::event::create(cluster, ElectricalEnergyMeasurement::Events::PeriodicEnergyMeasured::Id); +} +} // namespace event +} // namespace electrical_energy_measurement + } // namespace cluster } // namespace esp_matter diff --git a/components/esp_matter/esp_matter_event.h b/components/esp_matter/esp_matter_event.h index 1cb01de5b..3c2b4eea3 100644 --- a/components/esp_matter/esp_matter_event.h +++ b/components/esp_matter/esp_matter_event.h @@ -194,5 +194,18 @@ event_t *create_turbine_operation(cluster_t *cluster); } // namespace event } // namespace pump_configuration_and_control +namespace electrical_power_measurement { +namespace event { +event_t *create_measurement_period_ranges(cluster_t *cluster); +} // namespace event +} // namespace electrical_power_measurement + +namespace electrical_energy_measurement { +namespace event { +event_t *create_cumulative_energy_measured(cluster_t *cluster); +event_t *create_periodic_energy_measured(cluster_t *cluster); +} // namespace event +} // namespace electrical_energy_measurement + } // namespace cluster } // namespace esp_matter diff --git a/components/esp_matter/esp_matter_feature.cpp b/components/esp_matter/esp_matter_feature.cpp index a33c5e16e..fec1b4e15 100644 --- a/components/esp_matter/esp_matter_feature.cpp +++ b/components/esp_matter/esp_matter_feature.cpp @@ -3488,5 +3488,329 @@ esp_err_t add(cluster_t *cluster, config_t *config) } /* feature */ } /* boolean_state_configuration */ +namespace power_topology { +namespace feature { + +namespace node_topology { + +uint32_t get_id() +{ + return (uint32_t)PowerTopology::Feature::kNodeTopology; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* node_topology */ + +namespace tree_topology { + +uint32_t get_id() +{ + return (uint32_t)PowerTopology::Feature::kTreeTopology; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* tree_topology */ + +namespace set_topology { + +uint32_t get_id() +{ + return (uint32_t)PowerTopology::Feature::kSetTopology; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + attribute::create_available_endpoints(cluster, NULL, 0, 0); + return ESP_OK; +} +} /* set_topology */ + +namespace dynamic_power_flow { + +uint32_t get_id() +{ + return (uint32_t)PowerTopology::Feature::kDynamicPowerFlow; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + uint32_t set_topology_feature_map = feature::set_topology::get_id(); + if((get_feature_map_value(cluster) & set_topology_feature_map) == set_topology_feature_map) { + + update_feature_map(cluster, get_id()); + + attribute::create_active_endpoints(cluster, NULL, 0, 0); + } else { + ESP_LOGE(TAG, "Cluster shall support Set Topology feature"); + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} +} /* dynamic_power_flow */ + +} /* feature */ +} /* power_topology */ + +namespace electrical_power_measurement { +namespace feature { + +namespace direct_current { + +uint32_t get_id() +{ + return (uint32_t)ElectricalPowerMeasurement::Feature::kDirectCurrent; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* direct_current */ + +namespace alternating_current { + +uint32_t get_id() +{ + return (uint32_t)ElectricalPowerMeasurement::Feature::kAlternatingCurrent; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* alternating_current */ + +namespace polyphase_power { + +uint32_t get_id() +{ + return (uint32_t)ElectricalPowerMeasurement::Feature::kPolyphasePower; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + uint32_t ac_feature_map = feature::alternating_current::get_id(); + if((get_feature_map_value(cluster) & ac_feature_map) == ac_feature_map) { + + update_feature_map(cluster, get_id()); + + } else { + ESP_LOGE(TAG, "Cluster shall support Alternating Current feature"); + return ESP_ERR_NOT_SUPPORTED; + } + + + return ESP_OK; +} +} /* polyphase_power */ + +namespace harmonics { + +uint32_t get_id() +{ + return (uint32_t)ElectricalPowerMeasurement::Feature::kHarmonics; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + uint32_t ac_feature_map = feature::alternating_current::get_id(); + if((get_feature_map_value(cluster) & ac_feature_map) == ac_feature_map) { + + update_feature_map(cluster, get_id()); + + attribute::create_harmonic_currents(cluster, NULL, 0, 0); + } else { + ESP_LOGE(TAG, "Cluster shall support Alternating Current feature"); + return ESP_ERR_NOT_SUPPORTED; + } + + + return ESP_OK; +} +} /* harmonics */ + +namespace power_quality { + +uint32_t get_id() +{ + return (uint32_t)ElectricalPowerMeasurement::Feature::kPowerQuality; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + uint32_t ac_feature_map = feature::alternating_current::get_id(); + if((get_feature_map_value(cluster) & ac_feature_map) == ac_feature_map) { + + update_feature_map(cluster, get_id()); + + attribute::create_harmonic_phases(cluster, NULL, 0, 0); + } else { + ESP_LOGE(TAG, "Cluster shall support Alternating Current feature"); + return ESP_ERR_NOT_SUPPORTED; + } + + + return ESP_OK; +} +} /* power_quality */ + +} /* feature */ +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +namespace feature { + +namespace imported_energy { + +uint32_t get_id() +{ + return (uint32_t)ElectricalEnergyMeasurement::Feature::kImportedEnergy; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* imported_energy */ + +namespace exported_energy { + +uint32_t get_id() +{ + return (uint32_t)ElectricalEnergyMeasurement::Feature::kExportedEnergy; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + + return ESP_OK; +} +} /* exported_energy */ + +namespace cumulative_energy { + +uint32_t get_id() +{ + return (uint32_t)ElectricalEnergyMeasurement::Feature::kCumulativeEnergy; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + update_feature_map(cluster, get_id()); + uint32_t imported_feature_map = feature::imported_energy::get_id(); + uint32_t exported_feature_map = feature::exported_energy::get_id(); + if((get_feature_map_value(cluster) & imported_feature_map) == imported_feature_map) { + attribute::create_cumulative_energy_imported(cluster, NULL, 0, 0); + } + if((get_feature_map_value(cluster) & exported_feature_map) == exported_feature_map) { + attribute::create_cumulative_energy_exported(cluster, NULL, 0, 0); + } + + event::create_cumulative_energy_measured(cluster); + return ESP_OK; +} +} /* cumulative_energy */ + +namespace periodic_energy { + +uint32_t get_id() +{ + return (uint32_t)ElectricalEnergyMeasurement::Feature::kPeriodicEnergy; +} + +esp_err_t add(cluster_t *cluster) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + update_feature_map(cluster, get_id()); + uint32_t imported_feature_map = feature::imported_energy::get_id(); + uint32_t exported_feature_map = feature::exported_energy::get_id(); + if((get_feature_map_value(cluster) & imported_feature_map) == imported_feature_map) { + attribute::create_periodic_energy_imported(cluster, NULL, 0, 0); + } + if((get_feature_map_value(cluster) & exported_feature_map) == exported_feature_map) { + attribute::create_periodic_energy_exported(cluster, NULL, 0, 0); + } + + event::create_periodic_energy_measured(cluster); + return ESP_OK; +} +} /* periodic_energy */ + +} /* feature */ +} /* electrical_energy_measurement */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_feature.h b/components/esp_matter/esp_matter_feature.h index af2fd1cd4..68fa638df 100644 --- a/components/esp_matter/esp_matter_feature.h +++ b/components/esp_matter/esp_matter_feature.h @@ -1679,5 +1679,101 @@ esp_err_t add(cluster_t *cluster, config_t *config); } /* feature */ } /* boolean_state_configuration */ +namespace power_topology { +namespace feature { + +namespace node_topology { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* node_topology */ + +namespace tree_topology { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* tree_topology */ + +namespace set_topology { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* set_topology */ + +namespace dynamic_power_flow { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* dynamic_power_flow */ + +} /* feature */ +} /* power_topology */ + +namespace electrical_power_measurement { +namespace feature { + +namespace direct_current { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* direct_current */ + +namespace alternating_current { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* alternating_current */ + +namespace polyphase_power { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* polyphase_power */ + +namespace harmonics { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* harmonics */ + +namespace power_quality { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* power_quality */ + +} /* feature */ +} /* electrical_power_measurement */ + +namespace electrical_energy_measurement { +namespace feature { + +namespace imported_energy { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* imported_energy */ + +namespace exported_energy { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* exported_energy */ + +namespace cumulative_energy { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* cumulative_energy */ + +namespace periodic_energy { + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster); +} /* periodic_energy */ + +} /* feature */ +} /* electrical_energy_measurement */ + } /* cluster */ } /* esp_matter */ diff --git a/examples/all_device_types_app/main/device_types.h b/examples/all_device_types_app/main/device_types.h index fffb4e4aa..5d3a22b6e 100644 --- a/examples/all_device_types_app/main/device_types.h +++ b/examples/all_device_types_app/main/device_types.h @@ -40,6 +40,7 @@ enum device_type_enum { ESP_MATTER_WATER_LEAK_DETECTOR, ESP_MATTER_POWER_SOURCE, ESP_MATTER_RAIN_SENSOR, + ESP_MATTER_ELECTRICAL_SENSOR, ESP_MATTER_DEVICE_TYPE_MAX }; @@ -49,42 +50,43 @@ struct device_type_name { }; const device_type_name device_type_list[ESP_MATTER_DEVICE_TYPE_MAX] = { - {"on_off_light", ESP_MATTER_ON_OFF_LIGHT}, - {"dimmable_light", ESP_MATTER_DIMMABLE_LIGHT}, - {"color_temperature_light",ESP_MATTER_COLOR_TEMP_LIGHT}, - {"extended_color_light", ESP_MATTER_EXTENDED_COLOR_LIGHT}, - {"on_off_switch", ESP_MATTER_ON_OFF_SWITCH}, - {"dimmer_switch", ESP_MATTER_DIMMER_SWITCH}, - {"color_dimmer_switch", ESP_MATTER_COLOR_DIMMER_SWITCH}, - {"generic_switch", ESP_MATTER_GENERIC_SWITCH}, - {"on_off_plugin_unit", ESP_MATTER_ON_OFF_PLUGIN_UNIT}, - {"dimmable_plugin_unit", ESP_MATTER_DIMMABLE_PLUGIN_UNIT}, - {"fan", ESP_MATTER_FAN}, - {"thermostat", ESP_MATTER_THERMOSTAT}, - {"aggregator", ESP_MATTER_AGGREGATOR}, - {"bridged_node", ESP_MATTER_BRIDGED_NODE}, - {"door_lock", ESP_MATTER_DOOR_LOCK}, - {"window_covering_device", ESP_MATTER_WINDOW_COVERING_DEVICE}, - {"temperature_sensor", ESP_MATTER_TEMP_SENSOR}, - {"humidity_sensor", ESP_MATTER_HUMIDITY_SENSOR}, - {"occupancy_sensor", ESP_MATTER_OCCUPANCY_SENSOR}, - {"contact_sensor", ESP_MATTER_CONTACT_SENSOR}, - {"light_sensor", ESP_MATTER_LIGHT_SENSOR}, - {"pressure_sensor", ESP_MATTER_PRESSURE_SENSOR}, - {"flow_sensor", ESP_MATTER_FLOW_SENSOR}, - {"pump", ESP_MATTER_PUMP}, - {"mode_select_device", ESP_MATTER_MODE_SELECT_DEVICE}, - {"room_ac", ESP_MATTER_RAC}, - {"temp_ctrl_cabinet", ESP_MATTER_TEMP_CTRL_CABINET}, - {"refrigerator", ESP_MATTER_REFRIGERATOR}, - {"air_purifier", ESP_MATTER_AIR_PURIFIER}, - {"air_quality_sensor", ESP_MATTER_AIR_QUALITY_SENSOR}, - {"robotic_vacuum_cleaner", ESP_MATTER_ROBOTIC_VACUUM_CLEANER}, - {"laundry_washer", ESP_MATTER_LAUNDRY_WASHER}, - {"dish_washer", ESP_MATTER_DISH_WASHER}, - {"smoke_co_alarm", ESP_MATTER_SMOKE_CO_ALARM}, - {"water_leak_detector", ESP_MATTER_WATER_LEAK_DETECTOR}, - {"power_source", ESP_MATTER_POWER_SOURCE}, - {"rain_sensor", ESP_MATTER_RAIN_SENSOR} + {"on_off_light", ESP_MATTER_ON_OFF_LIGHT}, + {"dimmable_light", ESP_MATTER_DIMMABLE_LIGHT}, + {"color_temperature_light",ESP_MATTER_COLOR_TEMP_LIGHT}, + {"extended_color_light", ESP_MATTER_EXTENDED_COLOR_LIGHT}, + {"on_off_switch", ESP_MATTER_ON_OFF_SWITCH}, + {"dimmer_switch", ESP_MATTER_DIMMER_SWITCH}, + {"color_dimmer_switch", ESP_MATTER_COLOR_DIMMER_SWITCH}, + {"generic_switch", ESP_MATTER_GENERIC_SWITCH}, + {"on_off_plugin_unit", ESP_MATTER_ON_OFF_PLUGIN_UNIT}, + {"dimmable_plugin_unit", ESP_MATTER_DIMMABLE_PLUGIN_UNIT}, + {"fan", ESP_MATTER_FAN}, + {"thermostat", ESP_MATTER_THERMOSTAT}, + {"aggregator", ESP_MATTER_AGGREGATOR}, + {"bridged_node", ESP_MATTER_BRIDGED_NODE}, + {"door_lock", ESP_MATTER_DOOR_LOCK}, + {"window_covering_device", ESP_MATTER_WINDOW_COVERING_DEVICE}, + {"temperature_sensor", ESP_MATTER_TEMP_SENSOR}, + {"humidity_sensor", ESP_MATTER_HUMIDITY_SENSOR}, + {"occupancy_sensor", ESP_MATTER_OCCUPANCY_SENSOR}, + {"contact_sensor", ESP_MATTER_CONTACT_SENSOR}, + {"light_sensor", ESP_MATTER_LIGHT_SENSOR}, + {"pressure_sensor", ESP_MATTER_PRESSURE_SENSOR}, + {"flow_sensor", ESP_MATTER_FLOW_SENSOR}, + {"pump", ESP_MATTER_PUMP}, + {"mode_select_device", ESP_MATTER_MODE_SELECT_DEVICE}, + {"room_ac", ESP_MATTER_RAC}, + {"temp_ctrl_cabinet", ESP_MATTER_TEMP_CTRL_CABINET}, + {"refrigerator", ESP_MATTER_REFRIGERATOR}, + {"air_purifier", ESP_MATTER_AIR_PURIFIER}, + {"air_quality_sensor", ESP_MATTER_AIR_QUALITY_SENSOR}, + {"robotic_vacuum_cleaner", ESP_MATTER_ROBOTIC_VACUUM_CLEANER}, + {"laundry_washer", ESP_MATTER_LAUNDRY_WASHER}, + {"dish_washer", ESP_MATTER_DISH_WASHER}, + {"smoke_co_alarm", ESP_MATTER_SMOKE_CO_ALARM}, + {"water_leak_detector", ESP_MATTER_WATER_LEAK_DETECTOR}, + {"power_source", ESP_MATTER_POWER_SOURCE}, + {"rain_sensor", ESP_MATTER_RAIN_SENSOR}, + {"electrical_sensor", ESP_MATTER_ELECTRICAL_SENSOR} }; } /* namespace esp_matter */ 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 3c32b3201..f658abed7 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 @@ -364,6 +364,11 @@ int create(uint8_t device_type_index) endpoint = esp_matter::endpoint::rain_sensor::create(node, &rain_sensor_config, ENDPOINT_FLAG_NONE, NULL); break; } + case ESP_MATTER_ELECTRICAL_SENSOR: { + esp_matter::endpoint::electrical_sensor::config_t electrical_sensor_config; + endpoint = esp_matter::endpoint::electrical_sensor::create(node, &electrical_sensor_config, ENDPOINT_FLAG_NONE, NULL); + break; + } default: { ESP_LOGE(TAG, "Please input a valid device type"); break;