From 9a9cba68855433614e809f0b431de548be41e336 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, 2 Jun 2025 13:30:21 +0200
Subject: [PATCH 1/4] feat(zigbee): Add endpoint identification in read
 handlers

---
 .../Zigbee_Thermostat/Zigbee_Thermostat.ino   |  43 ++-
 libraries/Zigbee/src/ZigbeeEP.h               |   2 +-
 libraries/Zigbee/src/ZigbeeHandlers.cpp       |   4 +-
 libraries/Zigbee/src/ep/ZigbeeThermostat.cpp  | 251 +++++++++++++++++-
 libraries/Zigbee/src/ep/ZigbeeThermostat.h    |  17 +-
 5 files changed, 307 insertions(+), 10 deletions(-)

diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
index 7cdf45ef711..ee548b1a993 100644
--- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
+++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
@@ -34,7 +34,8 @@
 #include "Zigbee.h"
 
 /* Zigbee thermostat configuration */
-#define THERMOSTAT_ENDPOINT_NUMBER 5
+#define THERMOSTAT_ENDPOINT_NUMBER 1
+#define USE_RECIEVE_TEMP_WITH_SOURCE 1
 uint8_t button = BOOT_PIN;
 
 ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER);
@@ -48,10 +49,21 @@ float sensor_tolerance;
 struct tm timeinfo = {};  // Time structure for Time cluster
 
 /****************** Temperature sensor handling *******************/
+#if USE_RECIEVE_TEMP_WITH_SOURCE == 0
 void recieveSensorTemp(float temperature) {
   Serial.printf("Temperature sensor value: %.2f°C\n", temperature);
   sensor_temp = temperature;
 }
+#else
+void recieveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {
+  if (src_address.addr_type == ESP_ZB_ZCL_ADDR_TYPE_SHORT) {
+    Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address 0x%04x\n", temperature, src_endpoint, src_address.u.short_addr);
+  } else {
+    Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", temperature, src_endpoint, src_address.u.ieee_addr[7], src_address.u.ieee_addr[6], src_address.u.ieee_addr[5], src_address.u.ieee_addr[4], src_address.u.ieee_addr[3], src_address.u.ieee_addr[2], src_address.u.ieee_addr[1], src_address.u.ieee_addr[0]);
+  }
+  sensor_temp = temperature;
+}
+#endif
 
 void recieveSensorConfig(float min_temp, float max_temp, float tolerance) {
   Serial.printf("Temperature sensor settings: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
@@ -66,8 +78,14 @@ void setup() {
   // Init button switch
   pinMode(button, INPUT_PULLUP);
 
-  // Set callback functions for temperature and configuration receive
-  zbThermostat.onTempRecieve(recieveSensorTemp);
+  // Set callback function for recieving temperature from sensor - Use only one option
+  #if USE_RECIEVE_TEMP_WITH_SOURCE == 0
+    zbThermostat.onTempRecieve(recieveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature
+  #else
+    zbThermostat.onTempRecieveWithSource(recieveSensorTempWithSource);
+  #endif
+
+  // Set callback function for recieving sensor configuration
   zbThermostat.onConfigRecieve(recieveSensorConfig);
 
   //Optional: set Zigbee device name and model
@@ -107,7 +125,22 @@ void setup() {
 
   Serial.println();
 
-  // Get temperature sensor configuration
+  // Get temperature sensor configuration for each bound sensor
+  std::list<zb_device_params_t *> boundLights = zbThermostat.getBoundDevices();
+  for (const auto &device : boundLights) {
+    Serial.println("--------------------------------");
+    if(device->short_addr == 0x0000 || device->short_addr == 0xFFFF) { //End devices never have 0x0000 short address or 0xFFFF group address
+      Serial.printf("Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4],
+      device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]);
+      zbThermostat.getSensorSettings(device->endpoint, device->ieee_addr);
+    } else {
+      Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
+      zbThermostat.getSensorSettings(device->endpoint, device->short_addr);
+    }
+  }
+
+  Serial.println("--------------------------------");
+  Serial.println("Getting sensor settings for all bound sensors");
   zbThermostat.getSensorSettings();
 }
 
@@ -130,5 +163,7 @@ void loop() {
     last_print = millis();
     int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100);
     Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent);
+    Serial.println("Bound devices:");
+    zbThermostat.printBoundDevices(Serial);
   }
 }
diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h
index fe22f31faaf..ae75ef0dd6e 100644
--- a/libraries/Zigbee/src/ZigbeeEP.h
+++ b/libraries/Zigbee/src/ZigbeeEP.h
@@ -131,7 +131,7 @@ class ZigbeeEP {
 
   // list of all handlers function calls, to be override by EPs implementation
   virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {};
-  virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {};
+  virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {};
   virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute);  //already implemented
   virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message);
   virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {};
diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp
index eeeb1e8013a..d41cdf79ab5 100644
--- a/libraries/Zigbee/src/ZigbeeHandlers.cpp
+++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp
@@ -108,7 +108,7 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes
   // List through all Zigbee EPs and call the callback function, with the message
   for (std::list<ZigbeeEP *>::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) {
     if (message->dst_endpoint == (*it)->getEndpoint()) {
-      (*it)->zbAttributeRead(message->cluster, &message->attribute);  //method zbAttributeRead must be implemented in specific EP class
+      (*it)->zbAttributeRead(message->cluster, &message->attribute, message->src_endpoint, message->src_address);  //method zbAttributeRead must be implemented in specific EP class
     }
   }
   return ESP_OK;
@@ -142,7 +142,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re
           } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) {
             (*it)->zbReadTimeCluster(&variable->attribute);  //method zbReadTimeCluster implemented in the common EP class
           } else {
-            (*it)->zbAttributeRead(message->info.cluster, &variable->attribute);  //method zbAttributeRead must be implemented in specific EP class
+            (*it)->zbAttributeRead(message->info.cluster, &variable->attribute, message->info.src_endpoint, message->info.src_address);  //method zbAttributeRead must be implemented in specific EP class
           }
         }
         variable = variable->next;
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
index 633a60d0ff9..6971ea2664e 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
@@ -115,7 +115,7 @@ void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) {
   esp_zb_zdo_match_cluster(param, ZigbeeThermostat::findCbWrapper, this);
 }
 
-void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {
+void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {
   static uint8_t read_config = 0;
   if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) {
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) {
@@ -123,23 +123,30 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att
       if (_on_temp_recieve) {
         _on_temp_recieve(zb_s16_to_temperature(value));
       }
+      if (_on_temp_recieve_with_source) {
+        _on_temp_recieve_with_source(zb_s16_to_temperature(value), src_endpoint, src_address);
+      }
     }
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) {
       int16_t min_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0;
       _min_temp = zb_s16_to_temperature(min_value);
       read_config++;
+      log_d("Received min temperature: %.2f°C from endpoint %d", _min_temp, src_endpoint);
     }
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) {
       int16_t max_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0;
       _max_temp = zb_s16_to_temperature(max_value);
       read_config++;
+      log_d("Received max temperature: %.2f°C from endpoint %d", _max_temp, src_endpoint);
     }
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
       uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
       _tolerance = 1.0 * tolerance / 100;
       read_config++;
+      log_d("Received tolerance: %.2f°C from endpoint %d", _tolerance, src_endpoint);
     }
     if (read_config == 3) {
+      log_d("All config attributes processed");
       read_config = 0;
       xSemaphoreGive(lock);
     }
@@ -163,6 +170,65 @@ void ZigbeeThermostat::getTemperature() {
   esp_zb_lock_release();
 }
 
+void ZigbeeThermostat::getTemperature(uint16_t group_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i("Sending 'read temperature' command to group address 0x%x", group_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+}
+
+void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_endpoint = endpoint;
+  read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i("Sending 'read temperature' command to endpoint %d, address 0x%x", endpoint, short_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+}
+
+void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_endpoint = endpoint;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+  memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t));
+
+  uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i(
+    "Sending 'read temperature' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
+    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+  );
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+}
+
 void ZigbeeThermostat::getSensorSettings() {
   /* Send "read attributes" command to the bound sensor */
   esp_zb_zcl_read_attr_cmd_t read_req;
@@ -176,7 +242,99 @@ void ZigbeeThermostat::getSensorSettings() {
   read_req.attr_number = ZB_ARRAY_LENTH(attributes);
   read_req.attr_field = attributes;
 
-  log_i("Sending 'read temperature' command");
+  log_i("Sending 'read sensor settings' command");
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+
+  //Take semaphore to wait for response of all attributes
+  if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) {
+    log_e("Error while reading attributes");
+    return;
+  } else {
+    //Call the callback function when all attributes are read
+    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+  }
+}
+
+void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  uint16_t attributes[] = {
+    ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
+  };
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i("Sending 'read sensor settings' command to group address 0x%x", group_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+
+  //Take semaphore to wait for response of all attributes
+  if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) {
+    log_e("Error while reading attributes");
+    return;
+  } else {
+    //Call the callback function when all attributes are read
+    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+  }
+}
+
+void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_endpoint = endpoint;
+  read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  uint16_t attributes[] = {
+    ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
+  };
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i("Sending 'read sensor settings' command to endpoint %d, address 0x%x", endpoint, short_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_read_attr_cmd_req(&read_req);
+  esp_zb_lock_release();
+
+  //Take semaphore to wait for response of all attributes
+  if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) {
+    log_e("Error while reading attributes");
+    return;
+  } else {
+    //Call the callback function when all attributes are read
+    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+  }
+}
+
+void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
+  /* Send "read attributes" command to the bound sensor */
+  esp_zb_zcl_read_attr_cmd_t read_req;
+  read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
+  read_req.zcl_basic_cmd.src_endpoint = _endpoint;
+  read_req.zcl_basic_cmd.dst_endpoint = endpoint;
+  read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+  memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t));
+
+  uint16_t attributes[] = {
+    ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
+  };
+  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_field = attributes;
+
+  log_i(
+    "Sending 'read sensor settings' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
+    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+  );
   esp_zb_lock_acquire(portMAX_DELAY);
   esp_zb_zcl_read_attr_cmd_req(&read_req);
   esp_zb_lock_release();
@@ -218,4 +376,93 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m
   esp_zb_lock_release();
 }
 
+void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
+  /* Send "configure report attribute" command to the bound sensor */
+  esp_zb_zcl_config_report_cmd_t report_cmd;
+  report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
+  report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
+  report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
+  report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  int16_t report_change = (int16_t)delta * 100;
+  esp_zb_zcl_config_report_record_t records[] = {
+    {
+      .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND,
+      .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
+      .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
+      .min_interval = min_interval,
+      .max_interval = max_interval,
+      .reportable_change = &report_change,
+    },
+  };
+  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_field = records;
+
+  log_i("Sending 'configure reporting' command to group address 0x%x", group_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_config_report_cmd_req(&report_cmd);
+  esp_zb_lock_release();
+}
+
+void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
+  /* Send "configure report attribute" command to the bound sensor */
+  esp_zb_zcl_config_report_cmd_t report_cmd;
+  report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
+  report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
+  report_cmd.zcl_basic_cmd.dst_endpoint = endpoint;
+  report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
+  report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+
+  int16_t report_change = (int16_t)delta * 100;
+  esp_zb_zcl_config_report_record_t records[] = {
+    {
+      .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND,
+      .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
+      .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
+      .min_interval = min_interval,
+      .max_interval = max_interval,
+      .reportable_change = &report_change,
+    },
+  };
+  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_field = records;
+
+  log_i("Sending 'configure reporting' command to endpoint %d, address 0x%x", endpoint, short_addr);
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_config_report_cmd_req(&report_cmd);
+  esp_zb_lock_release();
+}
+
+void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
+  /* Send "configure report attribute" command to the bound sensor */
+  esp_zb_zcl_config_report_cmd_t report_cmd;
+  report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
+  report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
+  report_cmd.zcl_basic_cmd.dst_endpoint = endpoint;
+  report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+  memcpy(report_cmd.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t));
+
+  int16_t report_change = (int16_t)delta * 100;
+  esp_zb_zcl_config_report_record_t records[] = {
+    {
+      .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND,
+      .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
+      .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
+      .min_interval = min_interval,
+      .max_interval = max_interval,
+      .reportable_change = &report_change,
+    },
+  };
+  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_field = records;
+
+  log_i(
+    "Sending 'configure reporting' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
+    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+  );
+  esp_zb_lock_acquire(portMAX_DELAY);
+  esp_zb_zcl_config_report_cmd_req(&report_cmd);
+  esp_zb_lock_release();
+}
+
 #endif  // CONFIG_ZB_ENABLED
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h
index acdcd68e512..7cf8ba0334a 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h
@@ -37,13 +37,27 @@ class ZigbeeThermostat : public ZigbeeEP {
   void onTempRecieve(void (*callback)(float)) {
     _on_temp_recieve = callback;
   }
+  void onTempRecieveWithSource(void (*callback)(float, uint8_t, esp_zb_zcl_addr_t)) {
+    _on_temp_recieve_with_source = callback;
+  }
   void onConfigRecieve(void (*callback)(float, float, float)) {
     _on_config_recieve = callback;
   }
 
   void getTemperature();
+  void getTemperature(uint16_t group_addr);
+  void getTemperature(uint8_t endpoint, uint16_t short_addr);
+  void getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);
+
   void getSensorSettings();
+  void getSensorSettings(uint16_t group_addr);
+  void getSensorSettings(uint8_t endpoint, uint16_t short_addr);
+  void getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr);
+
   void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta);
+  void setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta);
+  void setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta);
+  void setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta);
 
 private:
   // save instance of the class in order to use it in static functions
@@ -51,6 +65,7 @@ class ZigbeeThermostat : public ZigbeeEP {
   zb_device_params_t *_device;
 
   void (*_on_temp_recieve)(float);
+  void (*_on_temp_recieve_with_source)(float, uint8_t, esp_zb_zcl_addr_t);
   void (*_on_config_recieve)(float, float, float);
   float _min_temp;
   float _max_temp;
@@ -62,7 +77,7 @@ class ZigbeeThermostat : public ZigbeeEP {
   static void bindCbWrapper(esp_zb_zdp_status_t zdo_status, void *user_ctx);
   static void findCbWrapper(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx);
 
-  void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override;
+  void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) override;
 };
 
 #endif  // CONFIG_ZB_ENABLED

From 7fd9c4610714472087fb288f5bde38892ad5fcc8 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: Tue, 3 Jun 2025 15:01:22 +0200
Subject: [PATCH 2/4] fix(zigbee): initialize Zigbee command structures with
 zeros

---
 .../Zigbee_Thermostat/Zigbee_Thermostat.ino   | 15 ++---
 libraries/Zigbee/src/ZigbeeEP.cpp             | 12 ++--
 .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 48 +++++++--------
 libraries/Zigbee/src/ep/ZigbeeSwitch.cpp      | 32 +++++-----
 libraries/Zigbee/src/ep/ZigbeeThermostat.cpp  | 58 +++++++++----------
 5 files changed, 79 insertions(+), 86 deletions(-)

diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
index ee548b1a993..aa358f643e9 100644
--- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
+++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
@@ -66,7 +66,7 @@ void recieveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb
 #endif
 
 void recieveSensorConfig(float min_temp, float max_temp, float tolerance) {
-  Serial.printf("Temperature sensor settings: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
+  Serial.printf("Temperature sensor config: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
   sensor_min_temp = min_temp;
   sensor_max_temp = max_temp;
   sensor_tolerance = tolerance;
@@ -125,9 +125,9 @@ void setup() {
 
   Serial.println();
 
-  // Get temperature sensor configuration for each bound sensor
-  std::list<zb_device_params_t *> boundLights = zbThermostat.getBoundDevices();
-  for (const auto &device : boundLights) {
+  // Get temperature sensor configuration for all bound sensors by endpoint number and address
+  std::list<zb_device_params_t *> boundSensors = zbThermostat.getBoundDevices();
+  for (const auto &device : boundSensors) {
     Serial.println("--------------------------------");
     if(device->short_addr == 0x0000 || device->short_addr == 0xFFFF) { //End devices never have 0x0000 short address or 0xFFFF group address
       Serial.printf("Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4],
@@ -138,21 +138,15 @@ void setup() {
       zbThermostat.getSensorSettings(device->endpoint, device->short_addr);
     }
   }
-
-  Serial.println("--------------------------------");
-  Serial.println("Getting sensor settings for all bound sensors");
-  zbThermostat.getSensorSettings();
 }
 
 void loop() {
   // Handle button switch in loop()
   if (digitalRead(button) == LOW) {  // Push button pressed
-
     // Key debounce handling
     while (digitalRead(button) == LOW) {
       delay(50);
     }
-
     // Set reporting interval for temperature sensor
     zbThermostat.setTemperatureReporting(0, 10, 2);
   }
@@ -163,7 +157,6 @@ void loop() {
     last_print = millis();
     int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100);
     Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent);
-    Serial.println("Bound devices:");
     zbThermostat.printBoundDevices(Serial);
   }
 }
diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp
index 1d3df126ce8..edfc01a00e6 100644
--- a/libraries/Zigbee/src/ZigbeeEP.cpp
+++ b/libraries/Zigbee/src/ZigbeeEP.cpp
@@ -145,7 +145,7 @@ bool ZigbeeEP::setBatteryVoltage(uint8_t voltage) {
 
 bool ZigbeeEP::reportBatteryPercentage() {
   /* Send report attributes command */
-  esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
+  esp_zb_zcl_report_attr_cmd_t report_attr_cmd = {0};
   report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
   report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID;
   report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI;
@@ -166,7 +166,7 @@ bool ZigbeeEP::reportBatteryPercentage() {
 
 char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
   /* Read peer Manufacture Name & Model Identifier */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
 
   if (short_addr != 0) {
     read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -204,7 +204,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
 
 char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
   /* Read peer Manufacture Name & Model Identifier */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
 
   if (short_addr != 0) {
     read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -375,7 +375,7 @@ bool ZigbeeEP::setTimezone(int32_t gmt_offset) {
 
 tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
   /* Read peer time */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
 
   if (short_addr >= 0) {
     read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -427,7 +427,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie
 
 int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
   /* Read peer timezone */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
 
   if (short_addr >= 0) {
     read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -543,7 +543,7 @@ static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t
 }
 
 void ZigbeeEP::requestOTAUpdate() {
-  esp_zb_zdo_match_desc_req_param_t req;
+  esp_zb_zdo_match_desc_req_param_t req = {0};
   uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_OTA_UPGRADE};
 
   /* Match the OTA server of coordinator */
diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp
index 935d638324f..f795ed1a3c8 100644
--- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp
@@ -53,7 +53,7 @@ void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t ad
   ZigbeeColorDimmerSwitch *instance = static_cast<ZigbeeColorDimmerSwitch *>(user_ctx);
   if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
     log_d("Found light endpoint");
-    esp_zb_zdo_bind_req_param_t bind_req;
+    esp_zb_zdo_bind_req_param_t bind_req = {0};
     zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t));
     light->endpoint = endpoint;
     light->short_addr = addr;
@@ -97,7 +97,7 @@ void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cm
 // Methods to control the light
 void ZigbeeColorDimmerSwitch::lightToggle() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID;
@@ -112,7 +112,7 @@ void ZigbeeColorDimmerSwitch::lightToggle() {
 
 void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -128,7 +128,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) {
 
 void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -145,7 +145,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr)
 
 void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -165,7 +165,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t i
 
 void ZigbeeColorDimmerSwitch::lightOn() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID;
@@ -180,7 +180,7 @@ void ZigbeeColorDimmerSwitch::lightOn() {
 
 void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -196,7 +196,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) {
 
 void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -213,7 +213,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) {
 
 void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -233,7 +233,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_
 
 void ZigbeeColorDimmerSwitch::lightOff() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID;
@@ -248,7 +248,7 @@ void ZigbeeColorDimmerSwitch::lightOff() {
 
 void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -264,7 +264,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) {
 
 void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -281,7 +281,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) {
 
 void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -301,7 +301,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee
 
 void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req;
+    esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.effect_id = effect_id;
@@ -317,7 +317,7 @@ void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effe
 
 void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req;
+    esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     log_v("Sending 'light on with scene recall' command");
@@ -331,7 +331,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() {
 
 void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_control = on_off_control;  //TODO: Test how it works, then maybe change API
@@ -348,7 +348,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16
 
 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) {
   if (_is_bound) {
-    esp_zb_zcl_move_to_level_cmd_t cmd_req;
+    esp_zb_zcl_move_to_level_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.level = level;
@@ -364,7 +364,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) {
 
 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_move_to_level_cmd_t cmd_req;
+    esp_zb_zcl_move_to_level_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -381,7 +381,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr)
 
 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_move_to_level_cmd_t cmd_req;
+    esp_zb_zcl_move_to_level_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -399,7 +399,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uin
 
 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_move_to_level_cmd_t cmd_req;
+    esp_zb_zcl_move_to_level_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -422,7 +422,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t
   if (_is_bound) {
     espXyColor_t xy_color = espRgbToXYColor(red, green, blue);
 
-    esp_zb_zcl_color_move_to_color_cmd_t cmd_req;
+    esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.color_x = xy_color.x;
@@ -441,7 +441,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t
   if (_is_bound) {
     espXyColor_t xy_color = espRgbToXYColor(red, green, blue);
 
-    esp_zb_zcl_color_move_to_color_cmd_t cmd_req;
+    esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -461,7 +461,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t
   if (_is_bound) {
     espXyColor_t xy_color = espRgbToXYColor(red, green, blue);
 
-    esp_zb_zcl_color_move_to_color_cmd_t cmd_req;
+    esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -482,7 +482,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t
   if (_is_bound) {
     espXyColor_t xy_color = espRgbToXYColor(red, green, blue);
 
-    esp_zb_zcl_color_move_to_color_cmd_t cmd_req;
+    esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp
index 38fd7d370fb..68e7a7430cc 100644
--- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp
@@ -52,7 +52,7 @@ void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t
   ZigbeeSwitch *instance = static_cast<ZigbeeSwitch *>(user_ctx);
   if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
     log_d("Found light endpoint");
-    esp_zb_zdo_bind_req_param_t bind_req;
+    esp_zb_zdo_bind_req_param_t bind_req = {0};
     zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t));
     light->endpoint = endpoint;
     light->short_addr = addr;
@@ -94,7 +94,7 @@ void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {
 // Methods to control the light
 void ZigbeeSwitch::lightToggle() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID;
@@ -109,7 +109,7 @@ void ZigbeeSwitch::lightToggle() {
 
 void ZigbeeSwitch::lightToggle(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -125,7 +125,7 @@ void ZigbeeSwitch::lightToggle(uint16_t group_addr) {
 
 void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -142,7 +142,7 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) {
 
 void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -162,7 +162,7 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
 
 void ZigbeeSwitch::lightOn() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID;
@@ -177,7 +177,7 @@ void ZigbeeSwitch::lightOn() {
 
 void ZigbeeSwitch::lightOn(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -193,7 +193,7 @@ void ZigbeeSwitch::lightOn(uint16_t group_addr) {
 
 void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -210,7 +210,7 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) {
 
 void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -230,7 +230,7 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
 
 void ZigbeeSwitch::lightOff() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID;
@@ -245,7 +245,7 @@ void ZigbeeSwitch::lightOff() {
 
 void ZigbeeSwitch::lightOff(uint16_t group_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
@@ -261,7 +261,7 @@ void ZigbeeSwitch::lightOff(uint16_t group_addr) {
 
 void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr;
@@ -278,7 +278,7 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) {
 
 void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.zcl_basic_cmd.dst_endpoint = endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
@@ -298,7 +298,7 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
 
 void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req;
+    esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.effect_id = effect_id;
@@ -314,7 +314,7 @@ void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant)
 
 void ZigbeeSwitch::lightOnWithSceneRecall() {
   if (_is_bound) {
-    esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req;
+    esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     log_v("Sending 'light on with scene recall' command");
@@ -327,7 +327,7 @@ void ZigbeeSwitch::lightOnWithSceneRecall() {
 }
 void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) {
   if (_is_bound) {
-    esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req;
+    esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0};
     cmd_req.zcl_basic_cmd.src_endpoint = _endpoint;
     cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
     cmd_req.on_off_control = on_off_control;  //TODO: Test how it works, then maybe change API
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
index 6971ea2664e..2529f4b1a64 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
@@ -65,7 +65,7 @@ void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uin
   ZigbeeThermostat *instance = static_cast<ZigbeeThermostat *>(user_ctx);
   if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
     log_i("Found temperature sensor");
-    esp_zb_zdo_bind_req_param_t bind_req;
+    esp_zb_zdo_bind_req_param_t bind_req = {0};
     /* Store the information of the remote device */
     zb_device_params_t *sensor = (zb_device_params_t *)malloc(sizeof(zb_device_params_t));
     sensor->endpoint = endpoint;
@@ -154,8 +154,8 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att
 }
 
 void ZigbeeThermostat::getTemperature() {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to all bound sensors */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
@@ -171,8 +171,8 @@ void ZigbeeThermostat::getTemperature() {
 }
 
 void ZigbeeThermostat::getTemperature(uint16_t group_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to the group */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
@@ -189,8 +189,8 @@ void ZigbeeThermostat::getTemperature(uint16_t group_addr) {
 }
 
 void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to specific endpoint */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -208,8 +208,8 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) {
 }
 
 void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to specific endpoint */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -230,8 +230,8 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_
 }
 
 void ZigbeeThermostat::getSensorSettings() {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to all bound sensors */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
@@ -258,8 +258,8 @@ void ZigbeeThermostat::getSensorSettings() {
 }
 
 void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to the group */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
@@ -287,8 +287,8 @@ void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) {
 }
 
 void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to specific endpoint */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -317,8 +317,8 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr)
 }
 
 void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) {
-  /* Send "read attributes" command to the bound sensor */
-  esp_zb_zcl_read_attr_cmd_t read_req;
+  /* Send "read attributes" command to specific endpoint */
+  esp_zb_zcl_read_attr_cmd_t read_req = {0};
   read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
   read_req.zcl_basic_cmd.src_endpoint = _endpoint;
   read_req.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -350,8 +350,8 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ie
 }
 
 void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
-  /* Send "configure report attribute" command to the bound sensor */
-  esp_zb_zcl_config_report_cmd_t report_cmd;
+  /* Send "configure report attribute" command to all bound sensors */
+  esp_zb_zcl_config_report_cmd_t report_cmd = {0};
   report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
   report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
   report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
@@ -364,7 +364,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = &report_change,
+      .reportable_change = (void*)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENTH(records);
@@ -377,8 +377,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m
 }
 
 void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
-  /* Send "configure report attribute" command to the bound sensor */
-  esp_zb_zcl_config_report_cmd_t report_cmd;
+  /* Send "configure report attribute" command to the group */
+  esp_zb_zcl_config_report_cmd_t report_cmd = {0};
   report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
   report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
   report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = group_addr;
@@ -392,7 +392,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = &report_change,
+      .reportable_change = (void*)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENTH(records);
@@ -405,8 +405,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min
 }
 
 void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
-  /* Send "configure report attribute" command to the bound sensor */
-  esp_zb_zcl_config_report_cmd_t report_cmd;
+  /* Send "configure report attribute" command to specific endpoint */
+  esp_zb_zcl_config_report_cmd_t report_cmd = {0};
   report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
   report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
   report_cmd.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -421,7 +421,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = &report_change,
+      .reportable_change = (void*)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENTH(records);
@@ -434,8 +434,8 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_
 }
 
 void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta) {
-  /* Send "configure report attribute" command to the bound sensor */
-  esp_zb_zcl_config_report_cmd_t report_cmd;
+  /* Send "configure report attribute" command to specific endpoint */
+  esp_zb_zcl_config_report_cmd_t report_cmd = {0};
   report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
   report_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
   report_cmd.zcl_basic_cmd.dst_endpoint = endpoint;
@@ -450,7 +450,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_add
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = &report_change,
+      .reportable_change = (void*)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENTH(records);

From 12e993de0dd02d67cf48234b996285ade0ccccb9 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: Tue, 3 Jun 2025 16:26:52 +0200
Subject: [PATCH 3/4] fix(zigbee): Spelling correction

---
 .../Zigbee_Thermostat/Zigbee_Thermostat.ino   | 22 +++++-----
 libraries/Zigbee/keywords.txt                 |  3 +-
 libraries/Zigbee/src/ZigbeeEP.cpp             |  8 ++--
 libraries/Zigbee/src/ZigbeeEP.h               |  2 +-
 libraries/Zigbee/src/ep/ZigbeeThermostat.cpp  | 40 +++++++++----------
 libraries/Zigbee/src/ep/ZigbeeThermostat.h    | 18 ++++-----
 6 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
index aa358f643e9..bda47377afb 100644
--- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
+++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
@@ -35,7 +35,7 @@
 
 /* Zigbee thermostat configuration */
 #define THERMOSTAT_ENDPOINT_NUMBER 1
-#define USE_RECIEVE_TEMP_WITH_SOURCE 1
+#define USE_RECEIVE_TEMP_WITH_SOURCE 1
 uint8_t button = BOOT_PIN;
 
 ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER);
@@ -49,13 +49,13 @@ float sensor_tolerance;
 struct tm timeinfo = {};  // Time structure for Time cluster
 
 /****************** Temperature sensor handling *******************/
-#if USE_RECIEVE_TEMP_WITH_SOURCE == 0
-void recieveSensorTemp(float temperature) {
+#if USE_RECEIVE_TEMP_WITH_SOURCE == 0
+void receiveSensorTemp(float temperature) {
   Serial.printf("Temperature sensor value: %.2f°C\n", temperature);
   sensor_temp = temperature;
 }
 #else
-void recieveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {
+void receiveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {
   if (src_address.addr_type == ESP_ZB_ZCL_ADDR_TYPE_SHORT) {
     Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address 0x%04x\n", temperature, src_endpoint, src_address.u.short_addr);
   } else {
@@ -65,7 +65,7 @@ void recieveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb
 }
 #endif
 
-void recieveSensorConfig(float min_temp, float max_temp, float tolerance) {
+void receiveSensorConfig(float min_temp, float max_temp, float tolerance) {
   Serial.printf("Temperature sensor config: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
   sensor_min_temp = min_temp;
   sensor_max_temp = max_temp;
@@ -78,15 +78,15 @@ void setup() {
   // Init button switch
   pinMode(button, INPUT_PULLUP);
 
-  // Set callback function for recieving temperature from sensor - Use only one option
-  #if USE_RECIEVE_TEMP_WITH_SOURCE == 0
-    zbThermostat.onTempRecieve(recieveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature
+  // Set callback function for receiving temperature from sensor - Use only one option
+  #if USE_RECEIVE_TEMP_WITH_SOURCE == 0
+    zbThermostat.onTempReceive(receiveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature
   #else
-    zbThermostat.onTempRecieveWithSource(recieveSensorTempWithSource);
+    zbThermostat.onTempReceiveWithSource(receiveSensorTempWithSource);
   #endif
 
-  // Set callback function for recieving sensor configuration
-  zbThermostat.onConfigRecieve(recieveSensorConfig);
+  // Set callback function for receiving sensor configuration
+  zbThermostat.onConfigReceive(receiveSensorConfig);
 
   //Optional: set Zigbee device name and model
   zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat");
diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt
index 4d4cd7d0606..5ce1e8f6f51 100644
--- a/libraries/Zigbee/keywords.txt
+++ b/libraries/Zigbee/keywords.txt
@@ -107,6 +107,7 @@ setLightColor	KEYWORD2
 # ZigbeeThermostat
 onTempRecieve	KEYWORD2
 onConfigRecieve	KEYWORD2
+onTempReceiveWithSource	KEYWORD2
 getTemperature	KEYWORD2
 getSensorSettings	KEYWORD2
 setTemperatureReporting	KEYWORD2
@@ -191,4 +192,4 @@ ZIGBEE_DEFAULT_COORDINATOR_CONFIG	LITERAL1
 ZIGBEE_DEFAULT_RADIO_CONFIG	LITERAL1
 ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG	LITERAL1
 ZIGBEE_DEFAULT_HOST_CONFIG	LITERAL1
-ZB_ARRAY_LENTH	LITERAL1
+ZB_ARRAY_LENGHT	LITERAL1
diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp
index edfc01a00e6..efddbdd0368 100644
--- a/libraries/Zigbee/src/ZigbeeEP.cpp
+++ b/libraries/Zigbee/src/ZigbeeEP.cpp
@@ -183,7 +183,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   if (_read_manufacturer != NULL) {
@@ -221,7 +221,7 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_add
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   if (_read_model != NULL) {
@@ -386,7 +386,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie
   }
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
@@ -438,7 +438,7 @@ int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_
   }
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h
index ae75ef0dd6e..a3217cbd066 100644
--- a/libraries/Zigbee/src/ZigbeeEP.h
+++ b/libraries/Zigbee/src/ZigbeeEP.h
@@ -12,7 +12,7 @@
 #define ZB_CMD_TIMEOUT             10000     // 10 seconds
 #define OTA_UPGRADE_QUERY_INTERVAL (1 * 60)  // 1 hour = 60 minutes
 
-#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0]))
+#define ZB_ARRAY_LENGHT(arr) (sizeof(arr) / sizeof(arr[0]))
 
 #define RGB_TO_XYZ(r, g, b, X, Y, Z)                               \
   {                                                                \
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
index 2529f4b1a64..737e74c7ac3 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
@@ -120,11 +120,11 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att
   if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) {
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) {
       int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0;
-      if (_on_temp_recieve) {
-        _on_temp_recieve(zb_s16_to_temperature(value));
+      if (_on_temp_receive) {
+        _on_temp_receive(zb_s16_to_temperature(value));
       }
-      if (_on_temp_recieve_with_source) {
-        _on_temp_recieve_with_source(zb_s16_to_temperature(value), src_endpoint, src_address);
+      if (_on_temp_receive_with_source) {
+        _on_temp_receive_with_source(zb_s16_to_temperature(value), src_endpoint, src_address);
       }
     }
     if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) {
@@ -161,7 +161,7 @@ void ZigbeeThermostat::getTemperature() {
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read temperature' command");
@@ -179,7 +179,7 @@ void ZigbeeThermostat::getTemperature(uint16_t group_addr) {
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read temperature' command to group address 0x%x", group_addr);
@@ -198,7 +198,7 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) {
   read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read temperature' command to endpoint %d, address 0x%x", endpoint, short_addr);
@@ -217,7 +217,7 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_
   memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t));
 
   uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID};
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i(
@@ -239,7 +239,7 @@ void ZigbeeThermostat::getSensorSettings() {
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read sensor settings' command");
@@ -253,7 +253,7 @@ void ZigbeeThermostat::getSensorSettings() {
     return;
   } else {
     //Call the callback function when all attributes are read
-    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+    _on_config_receive(_min_temp, _max_temp, _tolerance);
   }
 }
 
@@ -268,7 +268,7 @@ void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) {
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read sensor settings' command to group address 0x%x", group_addr);
@@ -282,7 +282,7 @@ void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) {
     return;
   } else {
     //Call the callback function when all attributes are read
-    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+    _on_config_receive(_min_temp, _max_temp, _tolerance);
   }
 }
 
@@ -298,7 +298,7 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr)
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i("Sending 'read sensor settings' command to endpoint %d, address 0x%x", endpoint, short_addr);
@@ -312,7 +312,7 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr)
     return;
   } else {
     //Call the callback function when all attributes are read
-    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+    _on_config_receive(_min_temp, _max_temp, _tolerance);
   }
 }
 
@@ -328,7 +328,7 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ie
   uint16_t attributes[] = {
     ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID
   };
-  read_req.attr_number = ZB_ARRAY_LENTH(attributes);
+  read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
   read_req.attr_field = attributes;
 
   log_i(
@@ -345,7 +345,7 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ie
     return;
   } else {
     //Call the callback function when all attributes are read
-    _on_config_recieve(_min_temp, _max_temp, _tolerance);
+    _on_config_receive(_min_temp, _max_temp, _tolerance);
   }
 }
 
@@ -367,7 +367,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m
       .reportable_change = (void*)&report_change,
     },
   };
-  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_number = ZB_ARRAY_LENGHT(records);
   report_cmd.record_field = records;
 
   log_i("Sending 'configure reporting' command");
@@ -395,7 +395,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min
       .reportable_change = (void*)&report_change,
     },
   };
-  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_number = ZB_ARRAY_LENGHT(records);
   report_cmd.record_field = records;
 
   log_i("Sending 'configure reporting' command to group address 0x%x", group_addr);
@@ -424,7 +424,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_
       .reportable_change = (void*)&report_change,
     },
   };
-  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_number = ZB_ARRAY_LENGHT(records);
   report_cmd.record_field = records;
 
   log_i("Sending 'configure reporting' command to endpoint %d, address 0x%x", endpoint, short_addr);
@@ -453,7 +453,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_add
       .reportable_change = (void*)&report_change,
     },
   };
-  report_cmd.record_number = ZB_ARRAY_LENTH(records);
+  report_cmd.record_number = ZB_ARRAY_LENGHT(records);
   report_cmd.record_field = records;
 
   log_i(
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h
index 7cf8ba0334a..c10a9d7f974 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h
@@ -34,14 +34,14 @@ class ZigbeeThermostat : public ZigbeeEP {
   ZigbeeThermostat(uint8_t endpoint);
   ~ZigbeeThermostat() {}
 
-  void onTempRecieve(void (*callback)(float)) {
-    _on_temp_recieve = callback;
+  void onTempReceive(void (*callback)(float)) {
+    _on_temp_receive = callback;
   }
-  void onTempRecieveWithSource(void (*callback)(float, uint8_t, esp_zb_zcl_addr_t)) {
-    _on_temp_recieve_with_source = callback;
+  void onTempReceiveWithSource(void (*callback)(float, uint8_t, esp_zb_zcl_addr_t)) {
+    _on_temp_receive_with_source = callback;
   }
-  void onConfigRecieve(void (*callback)(float, float, float)) {
-    _on_config_recieve = callback;
+  void onConfigReceive(void (*callback)(float, float, float)) {
+    _on_config_receive = callback;
   }
 
   void getTemperature();
@@ -64,9 +64,9 @@ class ZigbeeThermostat : public ZigbeeEP {
   static ZigbeeThermostat *_instance;
   zb_device_params_t *_device;
 
-  void (*_on_temp_recieve)(float);
-  void (*_on_temp_recieve_with_source)(float, uint8_t, esp_zb_zcl_addr_t);
-  void (*_on_config_recieve)(float, float, float);
+  void (*_on_temp_receive)(float);
+  void (*_on_temp_receive_with_source)(float, uint8_t, esp_zb_zcl_addr_t);
+  void (*_on_config_receive)(float, float, float);
   float _min_temp;
   float _max_temp;
   float _tolerance;

From 4eee08f930776bce9f5cbcbeb606c64297f6f10c Mon Sep 17 00:00:00 2001
From: "pre-commit-ci-lite[bot]"
 <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Date: Wed, 4 Jun 2025 13:35:49 +0000
Subject: [PATCH 4/4] ci(pre-commit): Apply automatic fixes

---
 .../Zigbee_Thermostat/Zigbee_Thermostat.ino   | 28 +++++++++++--------
 libraries/Zigbee/src/ZigbeeHandlers.cpp       |  8 ++++--
 libraries/Zigbee/src/ep/ZigbeeThermostat.cpp  | 20 ++++++-------
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
index bda47377afb..6f5934f791d 100644
--- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
+++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino
@@ -34,7 +34,7 @@
 #include "Zigbee.h"
 
 /* Zigbee thermostat configuration */
-#define THERMOSTAT_ENDPOINT_NUMBER 1
+#define THERMOSTAT_ENDPOINT_NUMBER   1
 #define USE_RECEIVE_TEMP_WITH_SOURCE 1
 uint8_t button = BOOT_PIN;
 
@@ -59,7 +59,11 @@ void receiveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb
   if (src_address.addr_type == ESP_ZB_ZCL_ADDR_TYPE_SHORT) {
     Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address 0x%04x\n", temperature, src_endpoint, src_address.u.short_addr);
   } else {
-    Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", temperature, src_endpoint, src_address.u.ieee_addr[7], src_address.u.ieee_addr[6], src_address.u.ieee_addr[5], src_address.u.ieee_addr[4], src_address.u.ieee_addr[3], src_address.u.ieee_addr[2], src_address.u.ieee_addr[1], src_address.u.ieee_addr[0]);
+    Serial.printf(
+      "Temperature sensor value: %.2f°C from endpoint %d, address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", temperature, src_endpoint,
+      src_address.u.ieee_addr[7], src_address.u.ieee_addr[6], src_address.u.ieee_addr[5], src_address.u.ieee_addr[4], src_address.u.ieee_addr[3],
+      src_address.u.ieee_addr[2], src_address.u.ieee_addr[1], src_address.u.ieee_addr[0]
+    );
   }
   sensor_temp = temperature;
 }
@@ -78,12 +82,12 @@ void setup() {
   // Init button switch
   pinMode(button, INPUT_PULLUP);
 
-  // Set callback function for receiving temperature from sensor - Use only one option
-  #if USE_RECEIVE_TEMP_WITH_SOURCE == 0
-    zbThermostat.onTempReceive(receiveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature
-  #else
-    zbThermostat.onTempReceiveWithSource(receiveSensorTempWithSource);
-  #endif
+// Set callback function for receiving temperature from sensor - Use only one option
+#if USE_RECEIVE_TEMP_WITH_SOURCE == 0
+  zbThermostat.onTempReceive(receiveSensorTemp);  // If you bound only one sensor or you don't need to know the source of the temperature
+#else
+  zbThermostat.onTempReceiveWithSource(receiveSensorTempWithSource);
+#endif
 
   // Set callback function for receiving sensor configuration
   zbThermostat.onConfigReceive(receiveSensorConfig);
@@ -129,9 +133,11 @@ void setup() {
   std::list<zb_device_params_t *> boundSensors = zbThermostat.getBoundDevices();
   for (const auto &device : boundSensors) {
     Serial.println("--------------------------------");
-    if(device->short_addr == 0x0000 || device->short_addr == 0xFFFF) { //End devices never have 0x0000 short address or 0xFFFF group address
-      Serial.printf("Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6], device->ieee_addr[5], device->ieee_addr[4],
-      device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]);
+    if (device->short_addr == 0x0000 || device->short_addr == 0xFFFF) {  //End devices never have 0x0000 short address or 0xFFFF group address
+      Serial.printf(
+        "Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6],
+        device->ieee_addr[5], device->ieee_addr[4], device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]
+      );
       zbThermostat.getSensorSettings(device->endpoint, device->ieee_addr);
     } else {
       Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp
index d41cdf79ab5..5d54e459058 100644
--- a/libraries/Zigbee/src/ZigbeeHandlers.cpp
+++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp
@@ -108,7 +108,9 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes
   // List through all Zigbee EPs and call the callback function, with the message
   for (std::list<ZigbeeEP *>::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) {
     if (message->dst_endpoint == (*it)->getEndpoint()) {
-      (*it)->zbAttributeRead(message->cluster, &message->attribute, message->src_endpoint, message->src_address);  //method zbAttributeRead must be implemented in specific EP class
+      (*it)->zbAttributeRead(
+        message->cluster, &message->attribute, message->src_endpoint, message->src_address
+      );  //method zbAttributeRead must be implemented in specific EP class
     }
   }
   return ESP_OK;
@@ -142,7 +144,9 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re
           } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) {
             (*it)->zbReadTimeCluster(&variable->attribute);  //method zbReadTimeCluster implemented in the common EP class
           } else {
-            (*it)->zbAttributeRead(message->info.cluster, &variable->attribute, message->info.src_endpoint, message->info.src_address);  //method zbAttributeRead must be implemented in specific EP class
+            (*it)->zbAttributeRead(
+              message->info.cluster, &variable->attribute, message->info.src_endpoint, message->info.src_address
+            );  //method zbAttributeRead must be implemented in specific EP class
           }
         }
         variable = variable->next;
diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
index 737e74c7ac3..f3bfd7d981b 100644
--- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
+++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp
@@ -221,8 +221,8 @@ void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_
   read_req.attr_field = attributes;
 
   log_i(
-    "Sending 'read temperature' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
-    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+    "Sending 'read temperature' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6],
+    ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
   );
   esp_zb_lock_acquire(portMAX_DELAY);
   esp_zb_zcl_read_attr_cmd_req(&read_req);
@@ -332,8 +332,8 @@ void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ie
   read_req.attr_field = attributes;
 
   log_i(
-    "Sending 'read sensor settings' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
-    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+    "Sending 'read sensor settings' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6],
+    ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
   );
   esp_zb_lock_acquire(portMAX_DELAY);
   esp_zb_zcl_read_attr_cmd_req(&read_req);
@@ -364,7 +364,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = (void*)&report_change,
+      .reportable_change = (void *)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENGHT(records);
@@ -392,7 +392,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = (void*)&report_change,
+      .reportable_change = (void *)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENGHT(records);
@@ -421,7 +421,7 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = (void*)&report_change,
+      .reportable_change = (void *)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENGHT(records);
@@ -450,15 +450,15 @@ void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_add
       .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
       .min_interval = min_interval,
       .max_interval = max_interval,
-      .reportable_change = (void*)&report_change,
+      .reportable_change = (void *)&report_change,
     },
   };
   report_cmd.record_number = ZB_ARRAY_LENGHT(records);
   report_cmd.record_field = records;
 
   log_i(
-    "Sending 'configure reporting' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], ieee_addr[5],
-    ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
+    "Sending 'configure reporting' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6],
+    ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]
   );
   esp_zb_lock_acquire(portMAX_DELAY);
   esp_zb_zcl_config_report_cmd_req(&report_cmd);