diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index c9851afce..9cbea08a3 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -4770,5 +4770,46 @@ attribute_t *create_progress(cluster_t *cluster, uint8_t *value, uint16_t length } /* attribute */ } /* service_area */ +namespace water_heater_management { +namespace attribute { +attribute_t *create_heater_types(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::HeaterTypes::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_bitmap8(value)); +} + +attribute_t *create_heat_demand(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::HeatDemand::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_bitmap8(value)); +} + +attribute_t *create_tank_volume(cluster_t *cluster, uint16_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::TankVolume::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); +} + +attribute_t *create_estimated_heat_required(cluster_t *cluster, int64_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::EstimatedHeatRequired::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_int64(value)); +} + +attribute_t *create_tank_percentage(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::TankPercentage::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); +} + +attribute_t *create_boost_state(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, WaterHeaterManagement::Attributes::BoostState::Id, + ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); +} + +} /* attribute */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 694c02a3b..cd3dea87b 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -1160,5 +1160,16 @@ attribute_t *create_progress(cluster_t *cluster, uint8_t *value, uint16_t length } /* attribute */ } /* service_area */ +namespace water_heater_management { +namespace attribute { +attribute_t *create_heater_types(cluster_t *cluster, uint8_t value); +attribute_t *create_heat_demand(cluster_t *cluster, uint8_t value); +attribute_t *create_tank_volume(cluster_t *cluster, uint16_t value); +attribute_t *create_estimated_heat_required(cluster_t *cluster, int64_t value); +attribute_t *create_tank_percentage(cluster_t *cluster, uint8_t value); +attribute_t *create_boost_state(cluster_t *cluster, uint8_t value); +} /* attribute */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index a9e34c86d..7e73b0611 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -3568,6 +3568,50 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_ } } /* service_area */ +namespace water_heater_management { +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, WaterHeaterManagement::Id, flags); + if (!cluster) { + ESP_LOGE(TAG, "Could not create cluster"); + return NULL; + } + if (flags & CLUSTER_FLAG_SERVER) { + if (config -> delegate != nullptr) { + static const auto delegate_init_cb = WaterHeaterManagementDelegateInitCB; + set_delegate_and_init_callback(cluster, delegate_init_cb, config->delegate); + } + static const auto plugin_server_init_cb = CALL_ONCE(MatterWaterHeaterManagementPluginServerInitCallback); + set_plugin_server_init_callback(cluster, plugin_server_init_cb); + add_function_list(cluster, function_list, function_flags); + + /* Attributes managed internally */ + global::attribute::create_feature_map(cluster, 0); + + /** Attributes not managed internally **/ + global::attribute::create_cluster_revision(cluster, cluster_revision); + attribute::create_heater_types(cluster, config->heater_types); + attribute::create_heat_demand(cluster, config->heat_demand); + attribute::create_tank_volume(cluster, config->tank_volume); + } + + if (features & feature::energy_management::get_id()) { + feature::energy_management::add(cluster, &(config->energy_management)); + } + if (features & feature::tank_percent::get_id()) { + feature::tank_percent::add(cluster, &(config->tank_percent)); + } + + event::create_boost_started(cluster); + event::create_boost_ended(cluster); + return cluster; +} + +} /* water_heater_management */ + // 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 33534cc2e..ac682c010 100644 --- a/components/esp_matter/esp_matter_cluster.h +++ b/components/esp_matter/esp_matter_cluster.h @@ -906,5 +906,19 @@ typedef struct config { cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features); } /* service_area */ +namespace water_heater_management { +typedef struct config { + uint8_t heater_types; + uint8_t heat_demand; + uint8_t tank_volume; + void *delegate; + feature::energy_management::config_t energy_management; + feature::tank_percent::config_t tank_percent; + config() : heater_types(0), heat_demand(0), tank_volume(0), delegate(nullptr) {} +} config_t; + +cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_t features); +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_command.cpp b/components/esp_matter/esp_matter_command.cpp index bd80373c2..02cfa2087 100644 --- a/components/esp_matter/esp_matter_command.cpp +++ b/components/esp_matter/esp_matter_command.cpp @@ -3261,6 +3261,30 @@ command_t *create_skip_area_response(cluster_t *cluster) } /* command */ } /* service_area */ +namespace water_heater_management { +namespace command { +constexpr const command_entry_t accepted_command_list[] = { + {WaterHeaterManagement::Commands::Boost::Id, COMMAND_FLAG_ACCEPTED, NULL}, + {WaterHeaterManagement::Commands::CancelBoost::Id, COMMAND_FLAG_ACCEPTED, NULL}, +}; + +constexpr const command_entry_t generated_command_list[] = {}; + +command_t *create_boost(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, WaterHeaterManagement::Commands::CancelBoost::Id, + COMMAND_FLAG_ACCEPTED, NULL); +} + +command_t *create_cancel_boost(cluster_t *cluster) +{ + return esp_matter::command::create(cluster, WaterHeaterManagement::Commands::CancelBoost::Id, + COMMAND_FLAG_ACCEPTED, NULL); +} + +} /* command */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ @@ -3307,6 +3331,7 @@ constexpr const cluster_command_t cluster_command_table[] = { {ThreadBorderRouterManagement::Id, GET_COMMAND_COUNT_LIST(cluster::thread_border_router_management)}, {WiFiNetworkManagement::Id, GET_COMMAND_COUNT_LIST(cluster::wifi_network_management)}, {ThreadNetworkDirectory::Id, GET_COMMAND_COUNT_LIST(cluster::thread_network_directory)}, + {WaterHeaterManagement::Id, GET_COMMAND_COUNT_LIST(cluster::water_heater_management)}, }; #if defined(CONFIG_ESP_MATTER_ENABLE_MATTER_SERVER) && defined(CONFIG_ESP_MATTER_ENABLE_DATA_MODEL) diff --git a/components/esp_matter/esp_matter_command.h b/components/esp_matter/esp_matter_command.h index e5f46c916..4740cc052 100644 --- a/components/esp_matter/esp_matter_command.h +++ b/components/esp_matter/esp_matter_command.h @@ -466,5 +466,12 @@ command_t *create_skip_area_response(cluster_t *cluster); } /* command */ } /* service_area */ +namespace water_heater_management { +namespace command { +command_t *create_boost(cluster_t *cluster); +command_t *create_cancel_boost(cluster_t *cluster); +} /* command */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_delegate_callbacks.cpp b/components/esp_matter/esp_matter_delegate_callbacks.cpp index 8d4b21b23..85447b9ca 100644 --- a/components/esp_matter/esp_matter_delegate_callbacks.cpp +++ b/components/esp_matter/esp_matter_delegate_callbacks.cpp @@ -38,6 +38,7 @@ #include #include #include +#include using namespace chip::app::Clusters; namespace esp_matter { @@ -379,6 +380,20 @@ 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. } + +void WaterHeaterManagementDelegateInitCB(void *delegate, uint16_t endpoint_id) +{ + if(delegate == nullptr) + { + return; + } + static WaterHeaterManagement::Instance * wHtrInstance = nullptr; + WaterHeaterManagement::Delegate *whtr_delegate = static_cast(delegate); + uint32_t feature_map = get_feature_map_value(endpoint_id, WaterHeaterManagement::Id); + wHtrInstance = new WaterHeaterManagement::Instance(endpoint_id, *whtr_delegate, chip::BitMask(feature_map)); + wHtrInstance->Init(); +} + } // namespace delegate_cb } // namespace cluster diff --git a/components/esp_matter/esp_matter_delegate_callbacks.h b/components/esp_matter/esp_matter_delegate_callbacks.h index 51416a017..14e05d925 100644 --- a/components/esp_matter/esp_matter_delegate_callbacks.h +++ b/components/esp_matter/esp_matter_delegate_callbacks.h @@ -47,6 +47,7 @@ void KeypadInputDelegateInitCB(void *delegate, uint16_t endpoint_id); void ModeSelectDelegateInitCB(void *delegate, uint16_t endpoint_id); void ThreadBorderRouterManagementDelegateInitCB(void *delegate, uint16_t endpoint_id); void ServiceAreaDelegateInitCB(void *delegate, uint16_t endpoint_id); +void WaterHeaterManagementDelegateInitCB(void *delegate, uint16_t endpoint_id); } // namespace delegate_cb } // namespace cluster diff --git a/components/esp_matter/esp_matter_event.cpp b/components/esp_matter/esp_matter_event.cpp index e335189a8..6797ee4d1 100644 --- a/components/esp_matter/esp_matter_event.cpp +++ b/components/esp_matter/esp_matter_event.cpp @@ -744,5 +744,20 @@ event_t *create_resumed(cluster_t *cluster) } // namespace event } // namespace device_energy_management +namespace water_heater_management { +namespace event { +event_t *create_boost_started(cluster_t *cluster) +{ + return esp_matter::event::create(cluster, WaterHeaterManagement::Events::BoostStarted::Id); +} + +event_t *create_boost_ended(cluster_t *cluster) +{ + return esp_matter::event::create(cluster, WaterHeaterManagement::Events::BoostEnded::Id); +} + +} // namespace event +} // namespace water_heater_management + } // namespace cluster } // namespace esp_matter diff --git a/components/esp_matter/esp_matter_event.h b/components/esp_matter/esp_matter_event.h index b95e2a0e4..46a5d83dd 100644 --- a/components/esp_matter/esp_matter_event.h +++ b/components/esp_matter/esp_matter_event.h @@ -223,5 +223,12 @@ event_t *create_resumed(cluster_t *cluster); } // namespace event } // namespace device_energy_management +namespace water_heater_management { +namespace event { +event_t *create_boost_started(cluster_t *cluster); +event_t *create_boost_ended(cluster_t *cluster); +} // namespace event +} // namespace water_heater_management + } // namespace cluster } // namespace esp_matter diff --git a/components/esp_matter/esp_matter_feature.cpp b/components/esp_matter/esp_matter_feature.cpp index 2d358de91..dfc39e878 100644 --- a/components/esp_matter/esp_matter_feature.cpp +++ b/components/esp_matter/esp_matter_feature.cpp @@ -4850,5 +4850,57 @@ esp_err_t add(cluster_t *cluster) } /* feature */ } /* service_area */ +namespace water_heater_management { +namespace feature { + +namespace energy_management { + +uint32_t get_id() +{ + return static_cast(WaterHeaterManagement::Feature::kEnergyManagement); +} + +esp_err_t add(cluster_t *cluster, config_t *config) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + /* attribute */ + attribute::create_tank_volume(cluster, config->tank_volume); + attribute::create_estimated_heat_required(cluster, config->estimated_heat_required); + + return ESP_OK; +} + +} /* energy_management */ + +namespace tank_percent { + +uint32_t get_id() +{ + return static_cast(WaterHeaterManagement::Feature::kEnergyManagement); +} + +esp_err_t add(cluster_t *cluster, config_t *config) +{ + if (!cluster) { + ESP_LOGE(TAG, "Cluster cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + update_feature_map(cluster, get_id()); + /* attribute */ + attribute::create_tank_percentage(cluster, config->tank_percentage); + + return ESP_OK; +} + + +} /* tank_percent */ + +} /* feature */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/esp_matter_feature.h b/components/esp_matter/esp_matter_feature.h index cfdf5b265..8fee7006e 100644 --- a/components/esp_matter/esp_matter_feature.h +++ b/components/esp_matter/esp_matter_feature.h @@ -2122,5 +2122,36 @@ esp_err_t add(cluster_t *cluster); } /* feature */ } /* service_area */ +namespace water_heater_management { +namespace feature { + +namespace energy_management { + +typedef struct config { + uint16_t tank_volume; + int64_t estimated_heat_required; + config(): tank_volume(0), estimated_heat_required(0) {} +} config_t; + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster, config_t *config); + +} /* energy_management */ + +namespace tank_percent { + +typedef struct config { + uint8_t tank_percentage; + config(): tank_percentage(0) {} +} config_t; + +uint32_t get_id(); +esp_err_t add(cluster_t *cluster, config_t *config); + +} /* tank_percent */ + +} /* feature */ +} /* water_heater_management */ + } /* cluster */ } /* esp_matter */ diff --git a/components/esp_matter/private/esp_matter_cluster_revisions.h b/components/esp_matter/private/esp_matter_cluster_revisions.h index 4378984f1..4cfee5b0f 100644 --- a/components/esp_matter/private/esp_matter_cluster_revisions.h +++ b/components/esp_matter/private/esp_matter_cluster_revisions.h @@ -383,6 +383,10 @@ namespace service_area { constexpr uint16_t cluster_revision = 1; } // namespace service_area +namespace water_heater_management { +constexpr uint16_t cluster_revision = 2; +} // namespace water_heater_management + } // namespace cluster } // namespace esp_matter diff --git a/docs/en/app_guide.rst b/docs/en/app_guide.rst index 40d3b4bea..bd3959bb3 100644 --- a/docs/en/app_guide.rst +++ b/docs/en/app_guide.rst @@ -45,6 +45,7 @@ List of clusters with delegate: - Wake On Lan Cluster. - Target Navigator Cluster. - Mode Select Cluster. + - Water Heater Management Cluster. 9.1.1 Mode Base Cluster ----------------------- @@ -216,6 +217,14 @@ ModeWaterHeater, ModeRefrigerator, ModeLaundryWasher and ModeMicrowaveOven. `Mode Select`_, `Mode Select Delegate`_ +9.1.21 Water Heater Management Cluster +-------------------------------------- + +.. csv-table:: + :header: "Delegate Class", "Reference Implementation" + + `Water Heater Management`_, `Water Heater Management Delegate`_ + .. note:: Make sure that after implementing delegate class, you set the delegate class pointer at the time of creating cluster. @@ -269,3 +278,5 @@ ModeWaterHeater, ModeRefrigerator, ModeLaundryWasher and ModeMicrowaveOven. .. _`Keypad Input Delegate`: https://github.com/espressif/connectedhomeip/blob/ea679d2dc674f576f4d391d1d71af1489010e580/examples/chef/common/clusters/keypad-input/KeypadInputManager.h .. _`Mode Select`: https://github.com/espressif/connectedhomeip/blob/ea679d2dc674f576f4d391d1d71af1489010e580/src/app/clusters/mode-select-server/supported-modes-manager.h .. _`Mode Select Delegate`: https://github.com/espressif/connectedhomeip/blob/ea679d2dc674f576f4d391d1d71af1489010e580/examples/all-clusters-app/all-clusters-common/include/static-supported-modes-manager.h +.. _`Water Heater Management`: https://github.com/espressif/connectedhomeip/blob/ea679d2dc674f576f4d391d1d71af1489010e580/src/app/clusters/water-heater-management-server/water-heater-management-server.h +.. _`Water Heater Management Delegate`: https://github.com/espressif/connectedhomeip/blob/ea679d2dc674f576f4d391d1d71af1489010e580/examples/energy-management-app/energy-management-common/water-heater/include/WhmDelegate.h