From 91bf6c7282f73e04352e733d37f6748cceeb9bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 9 Jun 2025 09:40:17 +0200 Subject: [PATCH 1/3] feat(zigbee): Support min max for Analog EP --- .../Zigbee_Analog_Input_Output.ino | 3 + libraries/Zigbee/src/ep/ZigbeeAnalog.cpp | 84 +++++++++++++++++++ libraries/Zigbee/src/ep/ZigbeeAnalog.h | 4 + 3 files changed, 91 insertions(+) diff --git a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino index 59c4b514db1..e7968a21122 100644 --- a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino @@ -72,6 +72,9 @@ void setup() { zbAnalogDevice.setAnalogOutputDescription("Fan Speed (RPM)"); zbAnalogDevice.setAnalogOutputResolution(1); + // Set the min and max values for the analog output which is used by HA to limit the range of the analog output + zbAnalogDevice.setAnalogOutputMinMax(-10000, 10000); //-10000 to 10000 RPM + // If analog output cluster is added, set callback function for analog output change zbAnalogDevice.onAnalogOutputChange(onAnalogOutputChange); diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp index 893a9854ecc..a98687bd732 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp @@ -20,6 +20,8 @@ bool ZigbeeAnalog::addAnalogInput() { "Analog Input"; uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AI_GROUP_ID << 24); float resolution = 0.1; // Default resolution of 0.1 + float min = -3.402823e+38; // Default min value for float + float max = 3.402823e+38; // Default max value for float esp_err_t ret = esp_zb_analog_input_cluster_add_attr(esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_DESCRIPTION_ID, (void *)default_description); if (ret != ESP_OK) { @@ -39,11 +41,24 @@ bool ZigbeeAnalog::addAnalogInput() { return false; } + ret = esp_zb_analog_input_cluster_add_attr(esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_MIN_PRESENT_VALUE_ID, (void *)&min); + 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_analog_input_cluster_add_attr(esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_MAX_PRESENT_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); if (ret != ESP_OK) { log_e("Failed to add Analog Input cluster: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } + _analog_clusters |= ANALOG_INPUT; return true; } @@ -76,6 +91,8 @@ bool ZigbeeAnalog::addAnalogOutput() { "Analog Output"; uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AO_GROUP_ID << 24); float resolution = 1; // Default resolution of 1 + float min = -3.402823e+38; // Default min value for float + float max = 3.402823e+38; // Default max value for float esp_err_t ret = esp_zb_analog_output_cluster_add_attr(esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (void *)default_description); @@ -96,6 +113,19 @@ bool ZigbeeAnalog::addAnalogOutput() { return false; } + ret = esp_zb_analog_output_cluster_add_attr(esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID, (void *)&min); + 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_analog_output_cluster_add_attr(esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); if (ret != ESP_OK) { log_e("Failed to add Analog Output cluster: 0x%x: %s", ret, esp_err_to_name(ret)); @@ -376,4 +406,58 @@ bool ZigbeeAnalog::setAnalogOutputResolution(float resolution) { return true; } +bool ZigbeeAnalog::setAnalogOutputMinMax(float min, float max) { + if (!(_analog_clusters & ANALOG_OUTPUT)) { + log_e("Analog Output cluster not added"); + return false; + } + + esp_zb_attribute_list_t *analog_output_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_output_cluster == nullptr) { + log_e("Failed to get analog output cluster"); + return false; + } + + esp_err_t ret = esp_zb_cluster_update_attr(analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID, (void *)&min); + 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(analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeAnalog::setAnalogInputMinMax(float min, float max) { + if (!(_analog_clusters & ANALOG_INPUT)) { + log_e("Analog Input cluster not added"); + return false; + } + + esp_zb_attribute_list_t *analog_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_input_cluster == nullptr) { + log_e("Failed to get analog input cluster"); + return false; + } + + esp_err_t ret = esp_zb_cluster_update_attr(analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_MIN_PRESENT_VALUE_ID, (void *)&min); + 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(analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_MAX_PRESENT_VALUE_ID, (void *)&max); + if (ret != ESP_OK) { + log_e("Failed to set max value: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.h b/libraries/Zigbee/src/ep/ZigbeeAnalog.h index bbc5f6d6fc2..5218a0b7d60 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.h +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.h @@ -41,6 +41,10 @@ class ZigbeeAnalog : public ZigbeeEP { bool setAnalogOutputDescription(const char *description); bool setAnalogOutputResolution(float resolution); + // Set the min and max values for the analog Input/Output + bool setAnalogOutputMinMax(float min, float max); + bool setAnalogInputMinMax(float min, float max); + // Use to set a cb function to be called on analog output change void onAnalogOutputChange(void (*callback)(float analog)) { _on_analog_output_change = callback; From 0c8b1d25fbd3bf0c659fbef1da49ea0a69cca20f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:10:50 +0200 Subject: [PATCH 2/3] feat(zigbee): Use cfloat FLT_MAX --- libraries/Zigbee/src/ep/ZigbeeAnalog.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp index a98687bd732..b8def148540 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp @@ -1,5 +1,6 @@ #include "ZigbeeAnalog.h" #if CONFIG_ZB_ENABLED +#include ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; @@ -20,8 +21,8 @@ bool ZigbeeAnalog::addAnalogInput() { "Analog Input"; uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AI_GROUP_ID << 24); float resolution = 0.1; // Default resolution of 0.1 - float min = -3.402823e+38; // Default min value for float - float max = 3.402823e+38; // Default max value for float + float min = -FLT_MAX; // Default min value for float + float max = FLT_MAX; // Default max value for float esp_err_t ret = esp_zb_analog_input_cluster_add_attr(esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_DESCRIPTION_ID, (void *)default_description); if (ret != ESP_OK) { @@ -91,8 +92,8 @@ bool ZigbeeAnalog::addAnalogOutput() { "Analog Output"; uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AO_GROUP_ID << 24); float resolution = 1; // Default resolution of 1 - float min = -3.402823e+38; // Default min value for float - float max = 3.402823e+38; // Default max value for float + float min = -FLT_MAX; // Default min value for float + float max = FLT_MAX; // Default max value for float esp_err_t ret = esp_zb_analog_output_cluster_add_attr(esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (void *)default_description); From ec747bb029aec933eb0502c1ed3ab4d088ff1702 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 07:58:13 +0000 Subject: [PATCH 3/3] ci(pre-commit): Apply automatic fixes --- .../Zigbee_Analog_Input_Output.ino | 2 +- libraries/Zigbee/src/ep/ZigbeeAnalog.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino index e7968a21122..f1cc54bda64 100644 --- a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino @@ -73,7 +73,7 @@ void setup() { zbAnalogDevice.setAnalogOutputResolution(1); // Set the min and max values for the analog output which is used by HA to limit the range of the analog output - zbAnalogDevice.setAnalogOutputMinMax(-10000, 10000); //-10000 to 10000 RPM + zbAnalogDevice.setAnalogOutputMinMax(-10000, 10000); //-10000 to 10000 RPM // If analog output cluster is added, set callback function for analog output change zbAnalogDevice.onAnalogOutputChange(onAnalogOutputChange); diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp index b8def148540..309739d54c9 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp @@ -21,8 +21,8 @@ bool ZigbeeAnalog::addAnalogInput() { "Analog Input"; uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AI_GROUP_ID << 24); float resolution = 0.1; // Default resolution of 0.1 - float min = -FLT_MAX; // Default min value for float - float max = FLT_MAX; // Default max value for float + float min = -FLT_MAX; // Default min value for float + float max = FLT_MAX; // Default max value for float esp_err_t ret = esp_zb_analog_input_cluster_add_attr(esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_DESCRIPTION_ID, (void *)default_description); if (ret != ESP_OK) { @@ -93,7 +93,7 @@ bool ZigbeeAnalog::addAnalogOutput() { uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AO_GROUP_ID << 24); float resolution = 1; // Default resolution of 1 float min = -FLT_MAX; // Default min value for float - float max = FLT_MAX; // Default max value for float + float max = FLT_MAX; // Default max value for float esp_err_t ret = esp_zb_analog_output_cluster_add_attr(esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (void *)default_description); @@ -126,7 +126,6 @@ bool ZigbeeAnalog::addAnalogOutput() { return false; } - ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); if (ret != ESP_OK) { log_e("Failed to add Analog Output cluster: 0x%x: %s", ret, esp_err_to_name(ret));