From cfc72f6ecb799a4c83e264afa82863a8e0e79a11 Mon Sep 17 00:00:00 2001 From: Hannes-Beckmann Date: Tue, 11 Nov 2025 18:05:37 +0100 Subject: [PATCH 1/5] Test to use the right Core --- libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index 484506e139d..039a23be67d 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -92,7 +92,7 @@ bool ZigbeeTempSensor::setTemperature(float temperature) { int16_t zb_temperature = zb_float_to_s16(temperature); log_v("Updating temperature sensor value..."); /* Update temperature sensor measured value */ - log_d("Setting temperature to %d", zb_temperature); + log_d("Setting temperature test test test !!! to %d", zb_temperature); esp_zb_lock_acquire(portMAX_DELAY); ret = esp_zb_zcl_set_attribute_val( _endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false From c32846c8c0d51ed9d14eef25893d166730053738 Mon Sep 17 00:00:00 2001 From: Hannes-Beckmann Date: Sat, 15 Nov 2025 11:33:07 +0100 Subject: [PATCH 2/5] Undo test --- libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index 039a23be67d..484506e139d 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -92,7 +92,7 @@ bool ZigbeeTempSensor::setTemperature(float temperature) { int16_t zb_temperature = zb_float_to_s16(temperature); log_v("Updating temperature sensor value..."); /* Update temperature sensor measured value */ - log_d("Setting temperature test test test !!! to %d", zb_temperature); + log_d("Setting temperature to %d", zb_temperature); esp_zb_lock_acquire(portMAX_DELAY); ret = esp_zb_zcl_set_attribute_val( _endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false From fa081b8917c32d681f55bb44a6d5a826d79f59f2 Mon Sep 17 00:00:00 2001 From: Hannes-Beckmann Date: Sat, 15 Nov 2025 11:33:39 +0100 Subject: [PATCH 3/5] Add Temperature Dimmable Light --- libraries/Zigbee/src/Zigbee.h | 1 + .../src/ep/ZigbeeTemperatureDimmableLight.cpp | 178 ++++++++++++++++++ .../src/ep/ZigbeeTemperatureDimmableLight.h | 117 ++++++++++++ 3 files changed, 296 insertions(+) create mode 100644 libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.cpp create mode 100644 libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.h diff --git a/libraries/Zigbee/src/Zigbee.h b/libraries/Zigbee/src/Zigbee.h index 837c19fa461..9e8198b6f44 100644 --- a/libraries/Zigbee/src/Zigbee.h +++ b/libraries/Zigbee/src/Zigbee.h @@ -29,6 +29,7 @@ #include "ep/ZigbeeSwitch.h" //// Lights #include "ep/ZigbeeColorDimmableLight.h" +#include "ep/ZigbeeTemperatureDimmableLight.h" #include "ep/ZigbeeDimmableLight.h" #include "ep/ZigbeeLight.h" //// Controllers diff --git a/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.cpp new file mode 100644 index 00000000000..d5bb913c020 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.cpp @@ -0,0 +1,178 @@ + +// 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 "ZigbeeTemperatureDimmableLight.h" +#if CONFIG_ZB_ENABLED + +ZigbeeTemperatureDimmableLight::ZigbeeTemperatureDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; // Use the correct device ID for color temperature light + + zigbee_temperature_dimmable_light_cfg_t light_cfg = ZIGBEE_DEFAULT_TEMPERATURE_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = zigbee_temperature_dimmable_light_clusters_create(&light_cfg); + + //Add support for Temperature Color Control cluster + esp_zb_attribute_list_t *color_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + uint16_t color_attr = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_DEF_VALUE; + uint16_t min_temp = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_DEFAULT_VALUE; + uint16_t max_temp = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_DEFAULT_VALUE; + uint8_t color_mode = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_MODE_DEFAULT_VALUE; + + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, &color_attr); + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID, &min_temp); + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID, &max_temp); + esp_zb_color_control_cluster_add_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_MODE_ID, &color_mode); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0 + }; + + // set default values + _current_state = false; + _current_level = 255; + _current_color_temperature = ESP_ZB_ZCL_COLOR_CONTROL_COLOR_TEMPERATURE_DEF_VALUE; // 6500K +} + +bool ZigbeeTemperatureDimmableLight::setMinMaxTemperature(uint16_t min_temp, uint16_t max_temp) { + esp_zb_attribute_list_t *color_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MIN_MIREDS_ID, &min_temp); + if (ret != ESP_OK) { + log_e("Failed to set min value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_update_attr(color_cluster, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMP_PHYSICAL_MAX_MIREDS_ID, &max_temp); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +void ZigbeeTemperatureDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + if (_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Temperature Dimmable Light", message->attribute.id); + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Temperature Dimmable Light", message->attribute.id); + } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + if (_current_color_temperature != *(uint16_t *)message->attribute.data.value) { + _current_color_temperature = *(uint16_t *)message->attribute.data.value; + lightChanged(); + } + return; + + } else { + log_w("Received message ignored. Attribute ID: %d not supported for Temperature Dimmable Light", message->attribute.id); + } + } else { + log_w("Received message ignored. Cluster ID: %d not supported for Temperature Dimmable Light", message->info.cluster); + } +} + +void ZigbeeTemperatureDimmableLight::lightChanged() { + if (_on_light_change) { + _on_light_change(_current_state, _current_level, _current_color_temperature); + } +} + +bool ZigbeeTemperatureDimmableLight::setLight(bool state, uint8_t level, uint16_t mireds) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + _current_state = state; + _current_level = level; + _current_color_temperature = mireds; + lightChanged(); + + log_v("Updating light state: %d, level: %d, color temperature: %d", state, level, mireds); + /* Update light clusters */ + esp_zb_lock_acquire(portMAX_DELAY); + //set on/off state + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, &_current_state, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light state: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set level + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, &_current_level, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light level: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } + //set color temperature + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_COLOR_TEMPERATURE_ID, + &_current_color_temperature, false + ); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set light color temperature: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + goto unlock_and_return; + } +unlock_and_return: + esp_zb_lock_release(); + return ret == ESP_ZB_ZCL_STATUS_SUCCESS; +} + +bool ZigbeeTemperatureDimmableLight::setLightState(bool state) { + return setLight(state, _current_level, _current_color_temperature); +} + +bool ZigbeeTemperatureDimmableLight::setLightLevel(uint8_t level) { + return setLight(_current_state, level, _current_color_temperature); +} + +bool ZigbeeTemperatureDimmableLight::setColorTemperature(uint16_t mireds) { + return setLight(_current_state, _current_level, mireds); +} + +esp_zb_cluster_list_t *ZigbeeTemperatureDimmableLight::zigbee_temperature_dimmable_light_clusters_create(zigbee_temperature_dimmable_light_cfg_t *light_cfg) { + esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(&light_cfg->basic_cfg); + esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(&light_cfg->identify_cfg); + esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_groups_cluster_create(&light_cfg->groups_cfg); + esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(&light_cfg->scenes_cfg); + esp_zb_attribute_list_t *esp_zb_on_off_cluster = esp_zb_on_off_cluster_create(&light_cfg->on_off_cfg); + esp_zb_attribute_list_t *esp_zb_level_cluster = esp_zb_level_cluster_create(&light_cfg->level_cfg); + esp_zb_attribute_list_t *esp_zb_color_cluster = esp_zb_color_control_cluster_create(&light_cfg->color_cfg); + + esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_groups_cluster(esp_zb_cluster_list, esp_zb_groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_scenes_cluster(esp_zb_cluster_list, esp_zb_scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_on_off_cluster(esp_zb_cluster_list, esp_zb_on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_level_cluster(esp_zb_cluster_list, esp_zb_level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_color_control_cluster(esp_zb_cluster_list, esp_zb_color_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + return esp_zb_cluster_list; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.h new file mode 100644 index 00000000000..8ccf135470f --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeTemperatureDimmableLight.h @@ -0,0 +1,117 @@ +// 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. + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +typedef struct zigbee_temperature_dimmable_light_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + esp_zb_groups_cluster_cfg_t groups_cfg; + esp_zb_scenes_cluster_cfg_t scenes_cfg; + esp_zb_on_off_cluster_cfg_t on_off_cfg; + esp_zb_level_cluster_cfg_t level_cfg; + esp_zb_color_cluster_cfg_t color_cfg; +} zigbee_temperature_dimmable_light_cfg_t; + +#define ZIGBEE_DEFAULT_TEMPERATURE_DIMMABLE_LIGHT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .groups_cfg = \ + { \ + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .scenes_cfg = \ + { \ + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, \ + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, \ + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, \ + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, \ + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, \ + }, \ + .on_off_cfg = \ + { \ + .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE, \ + }, \ + .level_cfg = \ + { \ + .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, \ + }, \ + .color_cfg = { \ + .current_x = ESP_ZB_ZCL_COLOR_CONTROL_CURRENT_X_DEF_VALUE, /*!< The current value of the normalized chromaticity value x */ \ + .current_y = ESP_ZB_ZCL_COLOR_CONTROL_CURRENT_Y_DEF_VALUE, /*!< The current value of the normalized chromaticity value y */ \ + .color_mode = 0x0002, /*!< The mode which attribute determines the color of the device */ \ + .options = ESP_ZB_ZCL_COLOR_CONTROL_OPTIONS_DEFAULT_VALUE, /*!< The bitmap determines behavior of some cluster commands */ \ + .enhanced_color_mode = \ + ESP_ZB_ZCL_COLOR_CONTROL_ENHANCED_COLOR_MODE_DEFAULT_VALUE, /*!< The enhanced-mode which attribute determines the color of the device */ \ + .color_capabilities = 0x0010, /*!< Specifying the color capabilities of the device support the color control cluster */ \ + }, \ + } + +class ZigbeeTemperatureDimmableLight : public ZigbeeEP { +public: + ZigbeeTemperatureDimmableLight(uint8_t endpoint); + ~ZigbeeTemperatureDimmableLight() {} + + bool setMinMaxTemperature(uint16_t min_temp, uint16_t max_temp); + + void onLightChange(void (*callback)(bool, uint8_t, uint16_t)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + + bool setLightState(bool state); + bool setLightLevel(uint8_t level); + bool setColorTemperature(uint16_t mireds); + bool setLight(bool state, uint8_t level, uint16_t mireds); + + bool getLightState() { + return _current_state; + } + uint8_t getLightLevel() { + return _current_level; + } + uint16_t getColorTemperature() { + return _current_color_temperature; + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + void lightChanged(); + void (*_on_light_change)(bool, uint8_t, uint16_t); + + bool _current_state; + uint8_t _current_level; + uint16_t _current_color_temperature; + + esp_zb_cluster_list_t *zigbee_temperature_dimmable_light_clusters_create(zigbee_temperature_dimmable_light_cfg_t *light_cfg); +}; + +#endif // CONFIG_ZB_ENABLED From 78a489e59cfae50a7a4d38f70a1b134f0875c534 Mon Sep 17 00:00:00 2001 From: Hannes-Beckmann Date: Sat, 15 Nov 2025 11:33:49 +0100 Subject: [PATCH 4/5] Add example --- .../README.md | 55 +++++++++ .../Zigbee_Temperature_Dimmable_Light.ino | 114 ++++++++++++++++++ .../Zigbee_Temperature_Dimmable_Light/ci.yml | 5 + 3 files changed, 174 insertions(+) create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/Zigbee_Temperature_Dimmable_Light.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/ci.yml diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/README.md new file mode 100644 index 00000000000..de864497a88 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/README.md @@ -0,0 +1,55 @@ +# Arduino-ESP32 Zigbee Temperature Dimmable Light Example + +This example shows how to configure a Zigbee end device and use it as a Home Automation (HA) temperature dimmable light (white tunable). + +## Supported Targets + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +Set the LED GPIO by changing the `led` definition. By default, the LED is `RGB_BUILTIN`. + +#### Using Arduino IDE + +* Select the correct board: `Tools -> Board`. +* Select Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where `xxx` is the detected COM port. +* Optional: Set debug level to verbose: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/Zigbee_Temperature_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/Zigbee_Temperature_Dimmable_Light.ino new file mode 100644 index 00000000000..37260d2371a --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/Zigbee_Temperature_Dimmable_Light.ino @@ -0,0 +1,114 @@ +// 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. + +/** + * @brief This example demonstrates Zigbee Temperature Dimmable light bulb. + * + * The example demonstrates how to use Zigbee library to create an end device with + * temperature dimmable light end point. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + * + * Created by Hannes Beckmann + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +#define ZIGBEE_TEMP_LIGHT_ENDPOINT 11 +uint8_t led = RGB_BUILTIN; +uint8_t button = BOOT_PIN; + +ZigbeeTemperatureDimmableLight zbTempLight = ZigbeeTemperatureDimmableLight(ZIGBEE_TEMP_LIGHT_ENDPOINT); + +/********************* LED functions **************************/ +uint16_t kelvinToMireds(uint16_t kelvin) { + return 1000000 / kelvin; +} + +uint16_t miredsToKelvin(uint16_t mireds) { + return 1000000 / mireds; +} + +void setTempLight(bool state, uint8_t level, uint16_t mireds) { + if (!state) { + rgbLedWrite(led, 0, 0, 0); + return; + } + float brightness = (float)level / 255; + // Convert mireds to color temperature (K) and map to white/yellow + uint16_t kelvin = miredsToKelvin(mireds); + uint8_t warm = constrain(map(kelvin, 2000, 6500, 255, 0), 0, 255); + uint8_t cold = constrain(map(kelvin, 2000, 6500, 0, 255), 0, 255); + rgbLedWrite(led, warm * brightness, warm * brightness, cold * brightness); +} + +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + zbTempLight.restoreLight(); + return; + } + rgbLedWrite(led, 255 * blink, 255 * blink, 255 * blink); + blink = !blink; +} + +void setup() { + Serial.begin(115200); + rgbLedWrite(led, 0, 0, 0); + pinMode(button, INPUT_PULLUP); + zbTempLight.onLightChange(setTempLight); + zbTempLight.onIdentify(identify); + zbTempLight.setManufacturerAndModel("Espressif", "ZBTempLightBulb"); + // High Kelvin -> Low Mireds: Min and Max is switched + zbTempLight.setMinMaxTemperature(kelvinToMireds(6500), kelvinToMireds(2000)); + Serial.println("Adding ZigbeeTemperatureDimmableLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbTempLight); + if (!Zigbee.begin()) { + Serial.println("Zigbee failed to start!"); + Serial.println("Rebooting..."); + ESP.restart(); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println(); +} + +void loop() { + if (digitalRead(button) == LOW) { + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + zbTempLight.setLightLevel(zbTempLight.getLightLevel() + 50); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/ci.yml b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/ci.yml new file mode 100644 index 00000000000..22315a90f3b --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/ci.yml @@ -0,0 +1,5 @@ +fqbn_append: PartitionScheme=zigbee,ZigbeeMode=ed + +requires: + - CONFIG_SOC_IEEE802154_SUPPORTED=y + - CONFIG_ZB_ENABLED=y From e0469981150c7b45f77db4af736f3aa38924f8fe Mon Sep 17 00:00:00 2001 From: Hannes-Beckmann Date: Sat, 15 Nov 2025 12:38:52 +0100 Subject: [PATCH 5/5] Add documentation --- .../zigbee/ep_temperature_dimmable_light.rst | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/en/zigbee/ep_temperature_dimmable_light.rst diff --git a/docs/en/zigbee/ep_temperature_dimmable_light.rst b/docs/en/zigbee/ep_temperature_dimmable_light.rst new file mode 100644 index 00000000000..3ade211eb30 --- /dev/null +++ b/docs/en/zigbee/ep_temperature_dimmable_light.rst @@ -0,0 +1,184 @@ +############################### +ZigbeeTemperatureDimmableLight +############################### + +About +----- + +The ``ZigbeeTemperatureDimmableLight`` class provides an endpoint for tunable white (temperature dimmable) lights in Zigbee networks. This endpoint implements the Zigbee Home Automation (HA) standard for color temperature lighting devices, supporting on/off, dimming, color temperature control, and scene management. + +**Features:** +* On/off control +* Brightness level control (0-100%) +* Color temperature control (mireds) +* Scene and group support +* Automatic state restoration +* Min/max color temperature configuration +* Integration with common endpoint features (binding, OTA, etc.) +* Zigbee HA standard compliance + +**Use Cases:** +* Smart tunable white bulbs +* Adjustable white LED panels +* Human-centric lighting +* Office and home white lighting +* Smart home white ambiance lighting + +API Reference +------------- + +Constructor +*********** + +ZigbeeTemperatureDimmableLight +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Creates a new Zigbee temperature dimmable light endpoint. + +.. code-block:: arduino + + ZigbeeTemperatureDimmableLight(uint8_t endpoint); + +* ``endpoint`` - Endpoint number (1-254) + +Callback Functions +****************** + +onLightChange +^^^^^^^^^^^^^ + +Sets the callback function for light state changes. + +.. code-block:: arduino + + void onLightChange(void (*callback)(bool, uint8_t, uint16_t)); + +* ``callback`` - Function pointer to the light change callback (state, level, mireds) + +Control Methods +*************** + +setLightState +^^^^^^^^^^^^^ + +Sets the light on/off state. + +.. code-block:: arduino + + bool setLightState(bool state); + +* ``state`` - Light state (true = on, false = off) + +Returns ``true`` if successful, ``false`` otherwise. + +setLightLevel +^^^^^^^^^^^^^ + +Sets the light brightness level. + +.. code-block:: arduino + + bool setLightLevel(uint8_t level); + +* ``level`` - Brightness level (0-255, where 0 is off, 255 is full brightness) + +Returns ``true`` if successful, ``false`` otherwise. + +setColorTemperature +^^^^^^^^^^^^^^^^^^^ + +Sets the light color temperature (in mireds). + +.. code-block:: arduino + + bool setColorTemperature(uint16_t mireds); + +* ``mireds`` - Color temperature in mireds (153 = 6500K, 500 = 2000K) + +Returns ``true`` if successful, ``false`` otherwise. + +setLight +^^^^^^^^ + +Sets all light parameters at once. + +.. code-block:: arduino + + bool setLight(bool state, uint8_t level, uint16_t mireds); + +* ``state`` - Light state (true/false) +* ``level`` - Brightness level (0-255) +* ``mireds`` - Color temperature in mireds + +Returns ``true`` if successful, ``false`` otherwise. + +setMinMaxTemperature +^^^^^^^^^^^^^^^^^^^^ + +Sets the minimum and maximum allowed color temperature (in mireds). + +.. code-block:: arduino + + bool setMinMaxTemperature(uint16_t min_temp, uint16_t max_temp); + +* ``min_temp`` - Minimum color temperature in mireds (e.g., 153 for 6500K) +* ``max_temp`` - Maximum color temperature in mireds (e.g., 500 for 2000K) + +Returns ``true`` if successful, ``false`` otherwise. + +State Retrieval Methods +*********************** + +getLightState +^^^^^^^^^^^^^ + +Gets the current light state. + +.. code-block:: arduino + + bool getLightState(); + +Returns current light state (true = on, false = off). + +getLightLevel +^^^^^^^^^^^^^ + +Gets the current brightness level. + +.. code-block:: arduino + + uint8_t getLightLevel(); + +Returns current brightness level (0-255). + +getColorTemperature +^^^^^^^^^^^^^^^^^^^ + +Gets the current color temperature (in mireds). + +.. code-block:: arduino + + uint16_t getColorTemperature(); + +Returns current color temperature in mireds. + +Utility Methods +*************** + +restoreLight +^^^^^^^^^^^^ + +Restores the light to its last known state. + +.. code-block:: arduino + + void restoreLight(); + +Example +------- + +Temperature Dimmable Light Implementation +***************************************** + +.. literalinclude:: ../../../libraries/Zigbee/examples/Zigbee_Temperature_Dimmable_Light/Zigbee_Temperature_Dimmable_Light.ino + :language: arduino