Skip to content

Conversation

@P-R-O-C-H-Y
Copy link
Member

Description of Change

This pull request introduces improvements to the ZigbeeThermostat EP, primarily by expanding support for humidity measurement and refactoring temperature configuration methods for clarity and consistency. The changes also ensure backward compatibility for deprecated methods.

Refactoring and Backward Compatibility

  • Refactored temperature configuration and settings methods in ZigbeeThermostat to use onTempConfigReceive and getTemperatureSettings instead of the older onConfigReceive and getSensorSettings. Deprecated methods now act as aliases to the new ones to maintain backward compatibility. (libraries/Zigbee/src/ep/ZigbeeThermostat.h, libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino, libraries/Zigbee/keywords.txt) [1] [2] [3] [4]

Humidity Measurement Feature

  • Added comprehensive humidity measurement support to ZigbeeThermostat, including new callback setters, getter and setter methods, configuration retrieval, and reporting functions. Also updated the keywords file to reflect these additions. (libraries/Zigbee/src/ep/ZigbeeThermostat.h, libraries/Zigbee/keywords.txt) [1] [2]

Data Type Consistency

  • Changed internal representation of humidity values from int16_t to uint16_t and updated conversion logic to multiply by 100 for precision, ensuring consistency with Zigbee cluster attribute requirements. (libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp) [1] [2]

These changes make the codebase easier to maintain, extend functionality for humidity sensors, and ensure smooth migration for existing users of the temperature sensor API.

Test Scenarios

Tested using two ESP32-C6 with following examples:
Temp + Humidity sensor - ED:

// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @brief This example demonstrates Zigbee temperature and humidity sensor Sleepy device.
 *
 * The example demonstrates how to use Zigbee library to create an end device temperature and humidity sensor.
 * The sensor is a Zigbee end device, which is reporting data to the Zigbee network.
 *
 * Proper Zigbee mode must be selected in Tools->Zigbee mode
 * and also the correct partition scheme must be selected in Tools->Partition Scheme.
 *
 * Please check the README.md for instructions and more detailed description.
 *
 * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
 */

#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"

/* Zigbee temperature + humidity sensor configuration */
#define TEMP_SENSOR_ENDPOINT_NUMBER 10

uint8_t button = BOOT_PIN;

ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);

/********************* Arduino functions **************************/
void setup() {
  Serial.begin(115200);

  // Init button switch
  pinMode(button, INPUT_PULLUP);

  // Optional: set Zigbee device name and model
  zbTempSensor.setManufacturerAndModel("Espressif", "ZigbeeTempSensor");

  // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
  zbTempSensor.setMinMaxValue(10, 50);

  // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C)
  zbTempSensor.setTolerance(1);

  // Add humidity cluster to the temperature sensor device with min, max and tolerance values
  //zbTempSensor.addHumiditySensor(0, 100, 1);

  // Add endpoint to Zigbee Core
  Zigbee.addEndpoint(&zbTempSensor);

  // When all EPs are registered, start Zigbee in End Device mode
  if (!Zigbee.begin()) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();  // If Zigbee failed to start, reboot the device and try again
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  Serial.println("Successfully connected to Zigbee network");

}

void loop() {
  // Checking button for factory reset
  if (digitalRead(button) == LOW) {  // Push button pressed
    // Key debounce handling
    delay(100);
    int startTime = millis();
    while (digitalRead(button) == LOW) {
      delay(50);
      if ((millis() - startTime) > 10000) {
        // If key pressed for more than 10secs, factory reset Zigbee and reboot
        Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
        delay(1000);
        // Optional set reset in factoryReset to false, to not restart device after erasing nvram, but set it to endless sleep manually instead
        Zigbee.factoryReset();
      }
    }
    // Report temperature and humidity values
    zbTempSensor.report();  // reports temperature and humidity values (if humidity sensor is not added, only temperature is reported)
    Serial.printf("Reported temperature and humidity");
  }

  // Meassure temperature sensor data every 2 seconds
  static uint32_t last_meassure = 0;
  if (millis() - last_meassure > 2000) {
    last_meassure = millis();
    // Measure temperature sensor value
    float temperature = temperatureRead();
    // Use temperature value as humidity value to demonstrate both temperature and humidity
    float humidity = temperature;

    // Update temperature and humidity values in Temperature sensor EP
    zbTempSensor.setTemperature(temperature);
    //zbTempSensor.setHumidity(humidity);
    Serial.printf("Meassured temperature: %.2f°C, Humidity: %.2f%%\r\n", temperature, humidity);
  }
}

Thermostat - Coordinator:

// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @brief This example demonstrates simple Zigbee thermostat.
 *
 * The example demonstrates how to use Zigbee library to get data from temperature
 * sensor end device and act as an thermostat.
 * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator (thermostat).
 *
 * Proper Zigbee mode must be selected in Tools->Zigbee mode
 * and also the correct partition scheme must be selected in Tools->Partition Scheme.
 *
 * Please check the README.md for instructions and more detailed description.
 *
 * Created by Jan Procházka (https://github.com/P-R-O-C-H-Y/)
 */

#ifndef ZIGBEE_MODE_ZCZR
#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode"
#endif

#include "Zigbee.h"

/* Zigbee thermostat configuration */
#define THERMOSTAT_ENDPOINT_NUMBER   1
uint8_t button = BOOT_PIN;

ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER);

// Save temperature sensor data
float sensor_temp;
float sensor_max_temp;
float sensor_min_temp;
float sensor_tolerance_temp;

float sensor_hum;
float sensor_max_hum;
float sensor_min_hum;
float sensor_tolerance_hum;

/****************** Temperature sensor handling *******************/
void receiveSensorTemp(float temperature) {
  Serial.printf("Temperature sensor value: %.2f°C\n", temperature);
  sensor_temp = temperature;
}
void receiveSensorHumidity(float humidity) {
  Serial.printf("Humidity sensor value: %.2f°C\n", humidity);
  sensor_hum = humidity;
}
void receiveTemperatureConfig(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;
  sensor_tolerance_temp = tolerance;
}
void receiveHumidityConfig(float min_hum, float max_hum, float tolerance) {
  Serial.printf("Humidity sensor config: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_hum, max_hum, tolerance);
  sensor_min_hum = min_hum;
  sensor_max_hum = max_hum;
  sensor_tolerance_hum = tolerance;
}


/********************* Arduino functions **************************/
void setup() {
  Serial.begin(115200);

  // Init button switch
  pinMode(button, INPUT_PULLUP);

  zbThermostat.onTempReceive(receiveSensorTemp);
  zbThermostat.onHumidityReceive(receiveSensorHumidity);

  // Set callback function for receiving sensor configuration
  zbThermostat.onTempConfigReceive(receiveTemperatureConfig);
  zbThermostat.onHumidityConfigReceive(receiveHumidityConfig);

  //Optional: set Zigbee device name and model
  zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat");

  //Add endpoint to Zigbee Core
  Zigbee.addEndpoint(&zbThermostat);

  //Open network for 180 seconds after boot
  Zigbee.setRebootOpenNetwork(180);

  // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode
  if (!Zigbee.begin(ZIGBEE_COORDINATOR)) {
    Serial.println("Zigbee failed to start!");
    Serial.println("Rebooting...");
    ESP.restart();
  }

  Serial.println("Waiting for Temperature sensor to bound to the thermostat");
  while (!zbThermostat.bound()) {
    Serial.printf(".");
    delay(500);
  }

  Serial.println();

  // 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], device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]
      );
      zbThermostat.getTemperatureSettings(device->endpoint, device->ieee_addr);
      zbThermostat.getHumiditySettings(device->endpoint, device->ieee_addr);
    } else {
      Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
      zbThermostat.getTemperatureSettings(device->endpoint, device->short_addr);
      zbThermostat.getHumiditySettings(device->endpoint, device->short_addr);
    }
  }
}

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);
    zbThermostat.setHumidityReporting(0, 10, 2);
    zbThermostat.printBoundDevices(Serial);
  }

  // Print temperature sensor data each 10 seconds
  static uint32_t last_print = 0;
  if (millis() - last_print > 10000) {
    last_print = millis();
    int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100);
    int hum_percent = (int)((sensor_hum - sensor_min_hum) / (sensor_max_hum - sensor_min_hum) * 100);
    Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent);
    Serial.printf("Loop humidity info: %.2f°C (%d %%)\n", sensor_hum, hum_percent);
  }
}

Related links

Closes #11665

@P-R-O-C-H-Y P-R-O-C-H-Y self-assigned this Oct 23, 2025
@P-R-O-C-H-Y P-R-O-C-H-Y added Status: Review needed Issue or PR is awaiting review Area: Zigbee Issues and Feature Request about Zigbee labels Oct 23, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 23, 2025

Messages
📖 🎉 Good Job! All checks are passing!

👋 Hello P-R-O-C-H-Y, we appreciate your contribution to this project!


📘 Please review the project's Contributions Guide for key guidelines on code, documentation, testing, and more.

🖊️ Please also make sure you have read and signed the Contributor License Agreement for this project.

Click to see more instructions ...


This automated output is generated by the PR linter DangerJS, which checks if your Pull Request meets the project's requirements and helps you fix potential issues.

DangerJS is triggered with each push event to a Pull Request and modify the contents of this comment.

Please consider the following:
- Danger mainly focuses on the PR structure and formatting and can't understand the meaning behind your code or changes.
- Danger is not a substitute for human code reviews; it's still important to request a code review from your colleagues.
- To manually retry these Danger checks, please navigate to the Actions tab and re-run last Danger workflow.

Review and merge process you can expect ...


We do welcome contributions in the form of bug reports, feature requests and pull requests.

1. An internal issue has been created for the PR, we assign it to the relevant engineer.
2. They review the PR and either approve it or ask you for changes or clarifications.
3. Once the GitHub PR is approved we do the final review, collect approvals from core owners and make sure all the automated tests are passing.
- At this point we may do some adjustments to the proposed change, or extend it by adding tests or documentation.
4. If the change is approved and passes the tests it is merged into the default branch.

Generated by 🚫 dangerJS against 1ab7203

@github-actions
Copy link
Contributor

github-actions bot commented Oct 23, 2025

Test Results

 76 files   76 suites   15m 52s ⏱️
 38 tests  38 ✅ 0 💤 0 ❌
241 runs  241 ✅ 0 💤 0 ❌

Results for commit 1ab7203.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

Memory usage test (comparing PR against master branch)

The table below shows the summary of memory usage change (decrease - increase) in bytes and percentage for each target.

MemoryFLASH [bytes]FLASH [%]RAM [bytes]RAM [%]
TargetDECINCDECINCDECINCDECINC
ESP32C50⚠️ +11400.00⚠️ +0.150⚠️ +320.00⚠️ +0.09
ESP32S30⚠️ +12760.00⚠️ +0.200⚠️ +240.00⚠️ +0.06
ESP32S20⚠️ +12600.00⚠️ +0.200⚠️ +240.00⚠️ +0.08
ESP32C30⚠️ +11320.00⚠️ +0.170⚠️ +160.00⚠️ +0.06
ESP32C60⚠️ +11280.00⚠️ +0.160⚠️ +320.00⚠️ +0.10
ESP32H20⚠️ +11300.00⚠️ +0.160⚠️ +320.00⚠️ +0.10
ESP320⚠️ +12520.00⚠️ +0.190⚠️ +240.00⚠️ +0.06
Click to expand the detailed deltas report [usage change in BYTES]
TargetESP32C5ESP32S3ESP32S2ESP32C3ESP32C6ESP32H2ESP32
ExampleFLASHRAMFLASHRAMFLASHRAMFLASHRAMFLASHRAMFLASHRAMFLASHRAM
libraries/Zigbee/examples/Zigbee_Analog_Input_Output00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Binary_Input_Output00------0000--
libraries/Zigbee/examples/Zigbee_CarbonDioxide_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light00------0000--
libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Contact_Switch00------0000--
libraries/Zigbee/examples/Zigbee_Dimmable_Light00------0000--
libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Electrical_AC_Sensor_MultiPhase00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Electrical_DC_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Fan_Control00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Gateway00⚠️ +3360⚠️ +336000----⚠️ +3360
libraries/Zigbee/examples/Zigbee_Illuminance_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Multistate_Input_Output00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_OTA_Client00------0000--
libraries/Zigbee/examples/Zigbee_Occupancy_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_On_Off_Light00------0000--
libraries/Zigbee/examples/Zigbee_On_Off_MultiSwitch00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_On_Off_Switch00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_PM25_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Power_Outlet00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Pressure_Flow_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Range_Extender00⚠️ +3360⚠️ +3360000000⚠️ +3360
libraries/Zigbee/examples/Zigbee_Scan_Networks00------0000--
libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy00------0000--
libraries/Zigbee/examples/Zigbee_Temperature_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Thermostat⚠️ +1140⚠️ +32⚠️ +1276⚠️ +24⚠️ +1260⚠️ +24⚠️ +1132⚠️ +16⚠️ +1128⚠️ +32⚠️ +1130⚠️ +32⚠️ +1252⚠️ +24
libraries/Zigbee/examples/Zigbee_Vibration_Sensor00------0000--
libraries/Zigbee/examples/Zigbee_Wind_Speed_Sensor00------0000--

Copy link
Member

@pedrominatel pedrominatel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs LGTM! Thanks!

@lucasssvaz lucasssvaz requested a review from Copilot October 25, 2025 01:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds humidity measurement support to the ZigbeeThermostat endpoint and refactors temperature-related methods for improved clarity. The changes maintain backward compatibility through deprecated aliases.

Key changes:

  • Added comprehensive humidity measurement APIs mirroring existing temperature functionality
  • Renamed temperature methods from generic names (e.g., getSensorSettings) to specific ones (e.g., getTemperatureSettings)
  • Fixed data type consistency in humidity handling (changed from int16_t to uint16_t)

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
libraries/Zigbee/src/ep/ZigbeeThermostat.h Added humidity callbacks and methods; renamed temperature methods with deprecated aliases
libraries/Zigbee/src/ep/ZigbeeThermostat.cpp Implemented humidity cluster binding and all humidity-related methods
libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp Fixed humidity data type from signed to unsigned with proper conversion
libraries/Zigbee/keywords.txt Updated keywords to reflect new humidity methods and renamed temperature methods
libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino Updated example to use new temperature method names
docs/en/zigbee/ep_thermostat.rst Added documentation for all humidity APIs and updated temperature method names

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +193 to +205
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format strings incorrectly show '%.2f%' which will display values like '50.00%'. Should be '%.2f%%' to properly escape the percent sign for values like '50.00%'.

Suggested change
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
log_d("Received min humidity: %.2f%% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f%% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f%% from endpoint %d", _tolerance_humidity, src_endpoint);

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +205
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format strings incorrectly show '%.2f%' which will display values like '50.00%'. Should be '%.2f%%' to properly escape the percent sign for values like '50.00%'.

Suggested change
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
log_d("Received min humidity: %.2f%% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f%% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f%% from endpoint %d", _tolerance_humidity, src_endpoint);

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +205
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Format strings incorrectly show '%.2f%' which will display values like '50.00%'. Should be '%.2f%%' to properly escape the percent sign for values like '50.00%'.

Suggested change
log_d("Received min humidity: %.2f% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f% from endpoint %d", _tolerance_humidity, src_endpoint);
log_d("Received min humidity: %.2f%% from endpoint %d", _min_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t max_value = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_max_humidity = 1.0 * max_value / 100;
read_humidity_config++;
log_d("Received max humidity: %.2f%% from endpoint %d", _max_humidity, src_endpoint);
}
if (attribute->id == ESP_ZB_ZCL_ATTR_REL_HUMIDITY_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) {
uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0;
_tolerance_humidity = 1.0 * tolerance / 100;
read_humidity_config++;
log_d("Received tolerance: %.2f%% from endpoint %d", _tolerance_humidity, src_endpoint);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Zigbee Issues and Feature Request about Zigbee Status: Review needed Issue or PR is awaiting review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add humidity readings support for Thermostat endpoint

3 participants