Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(zigbee): Support min max for Analog EP
  • Loading branch information
P-R-O-C-H-Y committed Jun 9, 2025
commit 91bf6c7282f73e04352e733d37f6748cceeb9bad
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
84 changes: 84 additions & 0 deletions libraries/Zigbee/src/ep/ZigbeeAnalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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));
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions libraries/Zigbee/src/ep/ZigbeeAnalog.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading