From a8be5fbbf06638427a6cfcdcec0d1670f38b417b 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, 5 May 2025 14:06:39 +0200 Subject: [PATCH 1/3] feat(zigbee): Add binary input and analog extension --- CMakeLists.txt | 1 + .../Zigbee_Analog_Input_Output.ino | 39 ++- .../examples/Zigbee_Binary_Input/README.md | 75 ++++++ .../Zigbee_Binary_Input.ino | 121 +++++++++ .../examples/Zigbee_Binary_Input/ci.json | 7 + libraries/Zigbee/src/Zigbee.h | 1 + libraries/Zigbee/src/ep/ZigbeeAnalog.cpp | 229 +++++++++++++++++- libraries/Zigbee/src/ep/ZigbeeAnalog.h | 10 + libraries/Zigbee/src/ep/ZigbeeBinary.cpp | 173 +++++++++++++ libraries/Zigbee/src/ep/ZigbeeBinary.h | 88 +++++++ 10 files changed, 741 insertions(+), 3 deletions(-) create mode 100644 libraries/Zigbee/examples/Zigbee_Binary_Input/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Binary_Input/ci.json create mode 100644 libraries/Zigbee/src/ep/ZigbeeBinary.cpp create mode 100644 libraries/Zigbee/src/ep/ZigbeeBinary.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14fcb19b6da..61534abbd5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS libraries/Zigbee/src/ep/ZigbeeWindSpeedSensor.cpp libraries/Zigbee/src/ep/ZigbeeIlluminanceSensor.cpp libraries/Zigbee/src/ep/ZigbeePM25Sensor.cpp + libraries/Zigbee/src/ep/ZigbeeBinary.cpp ) set(ARDUINO_LIBRARY_BLE_SRCS diff --git a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino index e31407cc8be..472bdcd50bf 100644 --- a/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino +++ b/libraries/Zigbee/examples/Zigbee_Analog_Input_Output/Zigbee_Analog_Input_Output.ino @@ -39,6 +39,9 @@ uint8_t analogPin = A0; uint8_t button = BOOT_PIN; ZigbeeAnalog zbAnalogDevice = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER); +ZigbeeAnalog zbAnalogTemp = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER + 1); +ZigbeeAnalog zbAnalogFan = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER + 2); +ZigbeeAnalog zbAnalogPercent = ZigbeeAnalog(ANALOG_DEVICE_ENDPOINT_NUMBER + 3); void onAnalogOutputChange(float analog_output) { Serial.printf("Received analog output change: %.1f\r\n", analog_output); @@ -57,15 +60,43 @@ void setup() { // Optional: set Zigbee device name and model zbAnalogDevice.setManufacturerAndModel("Espressif", "ZigbeeAnalogDevice"); - // Add analog clusters to Zigbee Analog according your needs + // Set up analog input zbAnalogDevice.addAnalogInput(); + zbAnalogDevice.setAnalogInputApplication(ESP_ZB_ZCL_AI_POWER_IN_WATTS_CONSUMPTION); + zbAnalogDevice.setAnalogInputDescription("Power Consumption (Watts)"); + zbAnalogDevice.setAnalogInputResolution(0.01); + + // Set up analog output zbAnalogDevice.addAnalogOutput(); + zbAnalogDevice.setAnalogOutputApplication(ESP_ZB_ZCL_AI_RPM_OTHER); + zbAnalogDevice.setAnalogOutputDescription("Fan Speed (RPM)"); // If analog output cluster is added, set callback function for analog output change zbAnalogDevice.onAnalogOutputChange(onAnalogOutputChange); + // Set up analog input + zbAnalogTemp.addAnalogInput(); + zbAnalogTemp.setAnalogInputApplication(ESP_ZB_ZCL_AI_TEMPERATURE_OTHER); + zbAnalogTemp.setAnalogInputDescription("Temperature"); + zbAnalogTemp.setAnalogInputResolution(0.1); + + // Set up analog input + zbAnalogFan.addAnalogInput(); + zbAnalogFan.setAnalogInputApplication(ESP_ZB_ZCL_AI_RPM_OTHER); + zbAnalogFan.setAnalogInputDescription("RPM"); + zbAnalogFan.setAnalogInputResolution(1); + + // Set up analog input + zbAnalogPercent.addAnalogInput(); + zbAnalogPercent.setAnalogInputApplication(ESP_ZB_ZCL_AI_PERCENTAGE_OTHER); + zbAnalogPercent.setAnalogInputDescription("Percentage"); + zbAnalogPercent.setAnalogInputResolution(0.01); + // Add endpoints to Zigbee Core Zigbee.addEndpoint(&zbAnalogDevice); + Zigbee.addEndpoint(&zbAnalogTemp); + Zigbee.addEndpoint(&zbAnalogFan); + Zigbee.addEndpoint(&zbAnalogPercent); Serial.println("Starting Zigbee..."); // When all EPs are registered, start Zigbee in End Device mode @@ -95,9 +126,15 @@ void loop() { float analog = (float)analogRead(analogPin); Serial.printf("Updating analog input to %.1f\r\n", analog); zbAnalogDevice.setAnalogInput(analog); + zbAnalogTemp.setAnalogInput(analog/100); + zbAnalogFan.setAnalogInput(analog); + zbAnalogPercent.setAnalogInput(analog/10); // Analog input supports reporting zbAnalogDevice.reportAnalogInput(); + zbAnalogTemp.reportAnalogInput(); + zbAnalogFan.reportAnalogInput(); + zbAnalogPercent.reportAnalogInput(); } // Checking button for factory reset and reporting diff --git a/libraries/Zigbee/examples/Zigbee_Binary_Input/README.md b/libraries/Zigbee/examples/Zigbee_Binary_Input/README.md new file mode 100644 index 00000000000..6ca3aac7119 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Binary_Input/README.md @@ -0,0 +1,75 @@ +# Arduino-ESP32 Zigbee Binary Input Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) binary input device with two different applications: HVAC fan status and security zone armed status. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Binary Input Functions + + * The example implements two binary inputs: + - HVAC Fan Status: Reports the current state of a fan + - Security Zone Armed: Reports the armed state of a security zone + * By clicking the button (BOOT) on this board, it will toggle both binary inputs and immediately send a report of their states to the network. + * Holding the button for more than 3 seconds will trigger a factory reset of the Zigbee device. + +## Hardware Required + +* A USB cable for power supply and programming + +### Configure the Project + +The example uses the following default pins: +* Button: `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2) + +#### Using Arduino IDE + +To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). + +* Before Compile/Verify, select the correct board: `Tools -> Board`. +* Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` +* Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` +* Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash of the End device before flashing the example to the board. It is recommended to do this if you re-flash the coordinator. +You can do the following: + +* In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. + +By default, the coordinator network is closed after rebooting or flashing new firmware. +To open the network you have 2 options: + +* Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. +* In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. + +***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** + +* **LED not blinking:** Check the wiring connection and the IO selection. +* **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. +* **COM port not detected:** Check the USB cable and the USB to Serial driver installation. + +If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). + +## Contribute + +To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) + +If you have any **feedback** or **issue** to report on this example/library, please open an issue or fix it by creating a new PR. Contributions are more than welcome! + +Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. + +## Resources + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) +* ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino b/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino new file mode 100644 index 00000000000..779e29f39b2 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino @@ -0,0 +1,121 @@ +// Copyright 2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates Zigbee analog input / output device. + * + * The example demonstrates how to use Zigbee library to create a end device analog device. + * + * 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/) + * Modified by Pat Clay + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee.h" + +/* Zigbee analog device configuration */ +#define BINARY_DEVICE_ENDPOINT_NUMBER 1 + +uint8_t binaryPin = A0; +uint8_t button = BOOT_PIN; + +ZigbeeBinary zbBinaryFan = ZigbeeBinary(BINARY_DEVICE_ENDPOINT_NUMBER); +ZigbeeBinary zbBinaryZone = ZigbeeBinary(BINARY_DEVICE_ENDPOINT_NUMBER + 1); + +bool binaryStatus = false; + +void onAnalogOutputChange(float analog_output) { + Serial.printf("Received analog output change: %.1f\r\n", analog_output); +} + +void setup() { + Serial.begin(115200); + Serial.println("Starting..."); + + // Init button switch + pinMode(button, INPUT_PULLUP); + + // Set analog resolution to 10 bits + analogReadResolution(10); + + // Optional: set Zigbee device name and model + zbBinaryFan.setManufacturerAndModel("Espressif", "ZigbeeBinarySensor"); + + // Set up binary fan status input (HVAC) + zbBinaryFan.addBinaryInput(); + zbBinaryFan.setBinaryInputApplication(BINARY_INPUT_APPLICATION_TYPE_HVAC_FAN_STATUS); + zbBinaryFan.setBinaryInputDescription("Fan Status"); + + // Set up binary zone armed input (Security) + zbBinaryZone.addBinaryInput(); + zbBinaryZone.setBinaryInputApplication(BINARY_INPUT_APPLICATION_TYPE_SECURITY_ZONE_ARMED); + zbBinaryZone.setBinaryInputDescription("Zone Armed"); + + // Add endpoints to Zigbee Core + Zigbee.addEndpoint(&zbBinaryFan); + Zigbee.addEndpoint(&zbBinaryZone); + + Serial.println("Starting Zigbee..."); + // 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(); + } else { + Serial.println("Zigbee started successfully!"); + } + Serial.println("Connecting to network"); + while (!Zigbee.connected()) { + Serial.print("."); + delay(100); + } + Serial.println("Connected"); + + // // Optional: Add reporting for analog input + // zbBinaryFan.setBinaryInputReporting(0, 30, 10); // report every 30 seconds if value changes by 10 + // zbBinaryZone.setBinaryInputReporting(0, 30, 10); // report every 30 seconds if value changes by 10 +} + +void loop() { + // Checking button for factory reset and reporting + if (digitalRead(button) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(button) == LOW) { + delay(50); + if ((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.println("Resetting Zigbee to factory and rebooting in 1s."); + delay(1000); + Zigbee.factoryReset(); + } + } + // Toggle binary input + binaryStatus = !binaryStatus; + zbBinaryFan.setBinaryInput(binaryStatus); + zbBinaryZone.setBinaryInput(binaryStatus); + zbBinaryFan.reportBinaryInput(); + zbBinaryZone.reportBinaryInput(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Binary_Input/ci.json b/libraries/Zigbee/examples/Zigbee_Binary_Input/ci.json new file mode 100644 index 00000000000..ceacc367801 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Binary_Input/ci.json @@ -0,0 +1,7 @@ +{ + "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", + "requires": [ + "CONFIG_SOC_IEEE802154_SUPPORTED=y", + "CONFIG_ZB_ENABLED=y" + ] +} diff --git a/libraries/Zigbee/src/Zigbee.h b/libraries/Zigbee/src/Zigbee.h index 7f44d7813af..176d7452b7f 100644 --- a/libraries/Zigbee/src/Zigbee.h +++ b/libraries/Zigbee/src/Zigbee.h @@ -18,6 +18,7 @@ #include "ep/ZigbeeThermostat.h" //// Sensors #include "ep/ZigbeeAnalog.h" +#include "ep/ZigbeeBinary.h" #include "ep/ZigbeeCarbonDioxideSensor.h" #include "ep/ZigbeeContactSwitch.h" #include "ep/ZigbeeDoorWindowHandle.h" diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp index a95668b7afe..5dfab0d219a 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.cpp @@ -13,7 +13,38 @@ ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) { } bool ZigbeeAnalog::addAnalogInput() { - esp_err_t ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_attribute_list_t *esp_zb_analog_input_cluster = esp_zb_analog_input_cluster_create(NULL); + + // Create default description for Analog Input + char default_description[] = "\x0C""Analog Input"; + uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AI_GROUP_ID << 24); + float resolution = 0.1; // Default resolution of 0.1 + + esp_err_t ret = esp_zb_analog_input_cluster_add_attr( + esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_DESCRIPTION_ID, (void *)default_description + ); + if (ret != ESP_OK) { + log_e("Failed to add description attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_analog_input_cluster_add_attr( + esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_APPLICATION_TYPE_ID, (void *)&application_type + ); + if (ret != ESP_OK) { + log_e("Failed to add application type attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_analog_input_cluster_add_attr( + esp_zb_analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_RESOLUTION_ID, (void *)&resolution + ); + if (ret != ESP_OK) { + log_e("Failed to add resolution attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); if (ret != ESP_OK) { log_e("Failed to add Analog Input cluster: 0x%x: %s", ret, esp_err_to_name(ret)); return false; @@ -22,8 +53,59 @@ bool ZigbeeAnalog::addAnalogInput() { return true; } +// Check esp_zigbee_zcl_analog_input.h for application type values +bool ZigbeeAnalog::setAnalogInputApplication(uint32_t application_type) { + if (!(_analog_clusters & ANALOG_INPUT)) { + log_e("Analog Input cluster not added"); + return false; + } + + // Add the Analog Input group ID (0x00) to the application type + uint32_t application_type_value = (ESP_ZB_ZCL_AI_GROUP_ID << 24) | application_type; + + esp_zb_attribute_list_t *analog_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_APPLICATION_TYPE_ID, (void *)&application_type_value); + if (ret != ESP_OK) { + log_e("Failed to set AI application type: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + bool ZigbeeAnalog::addAnalogOutput() { - esp_err_t ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_attribute_list_t *esp_zb_analog_output_cluster = esp_zb_analog_output_cluster_create(NULL); + + // Create default description for Analog Output + char default_description[] = "\x0D""Analog Output"; + uint32_t application_type = 0x00000000 | (ESP_ZB_ZCL_AO_GROUP_ID << 24); + float resolution = 1; // Default resolution of 1 + + esp_err_t ret = esp_zb_analog_output_cluster_add_attr( + esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (void *)default_description + ); + if (ret != ESP_OK) { + log_e("Failed to add description attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_analog_output_cluster_add_attr( + esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_APPLICATION_TYPE_ID, (void *)&application_type + ); + if (ret != ESP_OK) { + log_e("Failed to add application type attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_analog_output_cluster_add_attr( + esp_zb_analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID, (void *)&resolution + ); + if (ret != ESP_OK) { + log_e("Failed to add resolution attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); if (ret != ESP_OK) { log_e("Failed to add Analog Output cluster: 0x%x: %s", ret, esp_err_to_name(ret)); return false; @@ -32,6 +114,26 @@ bool ZigbeeAnalog::addAnalogOutput() { return true; } +// Check esp_zigbee_zcl_analog_output.h for application type values +bool ZigbeeAnalog::setAnalogOutputApplication(uint32_t application_type) { + if (!(_analog_clusters & ANALOG_OUTPUT)) { + log_e("Analog Output cluster not added"); + return false; + } + + // Add the Analog Output group ID (0x00) to the application type + uint32_t application_type_value = (ESP_ZB_ZCL_AO_GROUP_ID << 24) | application_type; + + esp_zb_attribute_list_t *analog_output_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_APPLICATION_TYPE_ID, (void *)&application_type_value); + if (ret != ESP_OK) { + log_e("Failed to set AO application type: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + //set attribute method -> method overridden in child class void ZigbeeAnalog::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT) { @@ -120,4 +222,127 @@ bool ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_i return true; } +bool ZigbeeAnalog::setAnalogInputDescription(const char *description) { + if (!(_analog_clusters & ANALOG_INPUT)) { + log_e("Analog Input cluster not added"); + return false; + } + + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char zb_description[ZB_MAX_NAME_LENGTH + 2]; + + // Convert description to ZCL string + size_t description_length = strlen(description); + if (description_length > ZB_MAX_NAME_LENGTH) { + log_e("Description is too long"); + return false; + } + + // Get and check the analog input cluster + esp_zb_attribute_list_t *analog_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_input_cluster == nullptr) { + log_e("Failed to get analog input cluster"); + return false; + } + + // Store the length as the first element + zb_description[0] = static_cast(description_length); // Cast size_t to char + // Use memcpy to copy the characters to the result array + memcpy(zb_description + 1, description, description_length); + // Null-terminate the array + zb_description[description_length + 1] = '\0'; + + // Update the description attribute + esp_err_t ret = esp_zb_cluster_update_attr(analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_DESCRIPTION_ID, (void *)zb_description); + if (ret != ESP_OK) { + log_e("Failed to set description: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeAnalog::setAnalogOutputDescription(const char *description) { + if (!(_analog_clusters & ANALOG_OUTPUT)) { + log_e("Analog Output cluster not added"); + return false; + } + + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char zb_description[ZB_MAX_NAME_LENGTH + 2]; + + // Convert description to ZCL string + size_t description_length = strlen(description); + if (description_length > ZB_MAX_NAME_LENGTH) { + log_e("Description is too long"); + return false; + } + + // Get and check the analog output cluster + esp_zb_attribute_list_t *analog_output_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_output_cluster == nullptr) { + log_e("Failed to get analog output cluster"); + return false; + } + + // Store the length as the first element + zb_description[0] = static_cast(description_length); // Cast size_t to char + // Use memcpy to copy the characters to the result array + memcpy(zb_description + 1, description, description_length); + // Null-terminate the array + zb_description[description_length + 1] = '\0'; + + // Update the description attribute + esp_err_t ret = esp_zb_cluster_update_attr(analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (void *)zb_description); + if (ret != ESP_OK) { + log_e("Failed to set description: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeAnalog::setAnalogInputResolution(float resolution) { + if (!(_analog_clusters & ANALOG_INPUT)) { + log_e("Analog Input cluster not added"); + return false; + } + + esp_zb_attribute_list_t *analog_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_input_cluster == nullptr) { + log_e("Failed to get analog input cluster"); + return false; + } + + esp_err_t ret = esp_zb_cluster_update_attr(analog_input_cluster, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_RESOLUTION_ID, (void *)&resolution); + if (ret != ESP_OK) { + log_e("Failed to set resolution: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeAnalog::setAnalogOutputResolution(float resolution) { + if (!(_analog_clusters & ANALOG_OUTPUT)) { + log_e("Analog Output cluster not added"); + return false; + } + + esp_zb_attribute_list_t *analog_output_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (analog_output_cluster == nullptr) { + log_e("Failed to get analog output cluster"); + return false; + } + + esp_err_t ret = esp_zb_cluster_update_attr(analog_output_cluster, ESP_ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID, (void *)&resolution); + if (ret != ESP_OK) { + log_e("Failed to set resolution: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + + #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeAnalog.h b/libraries/Zigbee/src/ep/ZigbeeAnalog.h index 03fbc678b6e..35e509fac30 100644 --- a/libraries/Zigbee/src/ep/ZigbeeAnalog.h +++ b/libraries/Zigbee/src/ep/ZigbeeAnalog.h @@ -31,6 +31,16 @@ class ZigbeeAnalog : public ZigbeeEP { bool addAnalogInput(); bool addAnalogOutput(); + // Set the application type and description for the analog input + bool setAnalogInputApplication(uint32_t application_type); // Check esp_zigbee_zcl_analog_input.h for application type values + bool setAnalogInputDescription(const char *description); + bool setAnalogInputResolution(float resolution); + + // Set the application type and description for the analog output + bool setAnalogOutputApplication(uint32_t application_type); // Check esp_zigbee_zcl_analog_output.h for application type values + bool setAnalogOutputDescription(const char *description); + bool setAnalogOutputResolution(float resolution); + // Use to set a cb function to be called on analog output change void onAnalogOutputChange(void (*callback)(float analog)) { _on_analog_output_change = callback; diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.cpp b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp new file mode 100644 index 00000000000..97947de2250 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp @@ -0,0 +1,173 @@ +#include "ZigbeeBinary.h" +#if CONFIG_ZB_ENABLED + +ZigbeeBinary::ZigbeeBinary(uint8_t endpoint) : ZigbeeEP(endpoint) { + _device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; + + //Create basic binary sensor clusters without configuration + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0}; +} + +bool ZigbeeBinary::addBinaryInput() { + esp_zb_attribute_list_t *esp_zb_binary_input_cluster = esp_zb_binary_input_cluster_create(NULL); + + // Create default description for Binary Input + char default_description[] = "\x0C""Binary Input"; + uint32_t application_type = 0x00000000 | (0x03 << 24); // Group ID 0x03 + + esp_err_t ret = esp_zb_binary_input_cluster_add_attr( + esp_zb_binary_input_cluster, ESP_ZB_ZCL_ATTR_BINARY_INPUT_DESCRIPTION_ID, (void *)default_description + ); + if (ret != ESP_OK) { + log_e("Failed to add description attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_binary_input_cluster_add_attr( + esp_zb_binary_input_cluster, ESP_ZB_ZCL_ATTR_BINARY_INPUT_APPLICATION_TYPE_ID, (void *)&application_type + ); + if (ret != ESP_OK) { + log_e("Failed to add application type attribute: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + + ret = esp_zb_cluster_list_add_binary_input_cluster(_cluster_list, esp_zb_binary_input_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (ret != ESP_OK) { + log_e("Failed to add Binary Input cluster: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + _binary_clusters |= BINARY_INPUT; + return true; +} + +// Check Zigbee Cluster Specification 3.14.11.19.4 Binary Inputs (BI) Types for application type values +bool ZigbeeBinary::setBinaryInputApplication(uint32_t application_type) { + if (!(_binary_clusters & BINARY_INPUT)) { + log_e("Binary Input cluster not added"); + return false; + } + + // Add the Binary Input group ID (0x03) to the application type + uint32_t application_type_value = (0x03 << 24) | application_type; + + esp_zb_attribute_list_t *binary_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_err_t ret = esp_zb_cluster_update_attr(binary_input_cluster, ESP_ZB_ZCL_ATTR_BINARY_INPUT_APPLICATION_TYPE_ID, (void *)&application_type_value); + if (ret != ESP_OK) { + log_e("Failed to set AI application type: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeBinary::setBinaryInput(bool binary) { + esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; + if (!(_binary_clusters & BINARY_INPUT)) { + log_e("Binary Input cluster not added"); + return false; + } + log_d("Setting binary input to %d", binary); + esp_zb_lock_acquire(portMAX_DELAY); + ret = esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, &binary, false + ); + esp_zb_lock_release(); + if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Failed to set binary input: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeBinary::reportBinaryInput() { + /* Send report attributes command */ + esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID; + report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to send Binary Input report: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + log_v("Binary Input report sent"); + return true; +} + +bool ZigbeeBinary::setBinaryInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info; + memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); + reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; + reporting_info.ep = _endpoint; + reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT; + reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + reporting_info.attr_id = ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID; + reporting_info.u.send_info.min_interval = min_interval; + reporting_info.u.send_info.max_interval = max_interval; + reporting_info.u.send_info.def_min_interval = min_interval; + reporting_info.u.send_info.def_max_interval = max_interval; + reporting_info.u.send_info.delta.s32 = delta; // TODO: Check if this is correct + reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; + reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); + if (ret != ESP_OK) { + log_e("Failed to set Binary Input reporting: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +bool ZigbeeBinary::setBinaryInputDescription(const char *description) { + if (!(_binary_clusters & BINARY_INPUT)) { + log_e("Binary Input cluster not added"); + return false; + } + + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char zb_description[ZB_MAX_NAME_LENGTH + 2]; + + // Convert description to ZCL string + size_t description_length = strlen(description); + if (description_length > ZB_MAX_NAME_LENGTH) { + log_e("Description is too long"); + return false; + } + + // Get and check the binary input cluster + esp_zb_attribute_list_t *binary_input_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + if (binary_input_cluster == nullptr) { + log_e("Failed to get binary input cluster"); + return false; + } + + // Store the length as the first element + zb_description[0] = static_cast(description_length); // Cast size_t to char + // Use memcpy to copy the characters to the result array + memcpy(zb_description + 1, description, description_length); + // Null-terminate the array + zb_description[description_length + 1] = '\0'; + + // Update the description attribute + esp_err_t ret = esp_zb_cluster_update_attr(binary_input_cluster, ESP_ZB_ZCL_ATTR_BINARY_INPUT_DESCRIPTION_ID, (void *)zb_description); + if (ret != ESP_OK) { + log_e("Failed to set description: 0x%x: %s", ret, esp_err_to_name(ret)); + return false; + } + return true; +} + +#endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.h b/libraries/Zigbee/src/ep/ZigbeeBinary.h new file mode 100644 index 00000000000..1c958e8d533 --- /dev/null +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.h @@ -0,0 +1,88 @@ +/* Class of Zigbee Analog sensor endpoint inherited from common EP class */ + +#pragma once + +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#if CONFIG_ZB_ENABLED + +#include "ZigbeeEP.h" +#include "ha/esp_zigbee_ha_standard.h" + +//enum for bits set to check what analog cluster were added +enum zigbee_binary_clusters { + BINARY_INPUT = 1, + BINARY_OUTPUT = 2 +}; + +// HVAC application types for Binary Input (more can be found in Zigbee Cluster Specification 3.14.11.19.4 Binary Inputs (BI) Types) +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_BOILER_STATUS 0x00000003 // Type 0x00, Index 0x0003 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_CHILLER_STATUS 0x00000013 // Type 0x00, Index 0x0013 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_OCCUPANCY 0x00000031 // Type 0x00, Index 0x0031 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_FAN_STATUS 0x00000035 // Type 0x00, Index 0x0035 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_FILTER_STATUS 0x00000036 // Type 0x00, Index 0x0036 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_HEATING_ALARM 0x0000003E // Type 0x00, Index 0x003E +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_COOLING_ALARM 0x0000001D // Type 0x00, Index 0x001D +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_UNIT_ENABLE 0x00000090 // Type 0x00, Index 0x0090 +#define BINARY_INPUT_APPLICATION_TYPE_HVAC_OTHER 0x0000FFFF // Type 0x00, Index 0xFFFF + +// Security application types for Binary Input +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_GLASS_BREAKAGE_DETECTION_0 0x01000000 // Type 0x01, Index 0x0000 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_INTRUSION_DETECTION 0x01000001 // Type 0x01, Index 0x0001 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_MOTION_DETECTION 0x01000002 // Type 0x01, Index 0x0002 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_GLASS_BREAKAGE_DETECTION_1 0x01000003 // Type 0x01, Index 0x0003 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_ZONE_ARMED 0x01000004 // Type 0x01, Index 0x0004 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_GLASS_BREAKAGE_DETECTION_2 0x01000005 // Type 0x01, Index 0x0005 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_SMOKE_DETECTION 0x01000006 // Type 0x01, Index 0x0006 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_CARBON_DIOXIDE_DETECTION 0x01000007 // Type 0x01, Index 0x0007 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_HEAT_DETECTION 0x01000008 // Type 0x01, Index 0x0008 +#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_OTHER 0x0100FFFF // Type 0x01, Index 0xFFFF + +typedef struct zigbee_binary_cfg_s { + esp_zb_basic_cluster_cfg_t basic_cfg; + esp_zb_identify_cluster_cfg_t identify_cfg; + // esp_zb_binary_output_cluster_cfg_t binary_output_cfg; + esp_zb_binary_input_cluster_cfg_t binary_input_cfg; +} zigbee_binary_cfg_t; + +class ZigbeeBinary : public ZigbeeEP { +public: + ZigbeeBinary(uint8_t endpoint); + ~ZigbeeBinary() {} + + // Add binary cluster + bool addBinaryInput(); + // bool addBinaryOutput(); + + // Set the application type and description for the binary input + bool setBinaryInputApplication(uint32_t application_type); // Check esp_zigbee_zcl_binary_input.h for application type values + bool setBinaryInputDescription(const char *description); + + // Set the application type and description for the binary output + // bool setBinaryOutputApplication(uint32_t application_type); // Check esp_zigbee_zcl_binary_output.h for application type values + // bool setBinaryOutputDescription(const char *description); + + // Use to set a cb function to be called on binary output change + // void onBinaryOutputChange(void (*callback)(bool binary_output)) { + // _on_binary_output_change = callback; + // } + + // Set the binary input value + bool setBinaryInput(bool binary); + + // Report Binary Input value + bool reportBinaryInput(); + + // Set reporting for Binary Input + bool setBinaryInputReporting(uint16_t min_interval, uint16_t max_interval, float delta); + +private: + // void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + + // void (*_on_binary_output_change)(bool); + // void binaryOutputChanged(bool binary_output); + + uint8_t _binary_clusters; +}; + +#endif // CONFIG_ZB_ENABLED From 03fff975ff30ebc03208ea788dc324093b2cfe99 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, 5 May 2025 17:11:30 +0200 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Zigbee_Binary_Input/Zigbee_Binary_Input.ino | 15 +++------------ libraries/Zigbee/src/ep/ZigbeeBinary.cpp | 2 +- libraries/Zigbee/src/ep/ZigbeeBinary.h | 2 +- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino b/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino index 779e29f39b2..de0cf606dcd 100644 --- a/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino +++ b/libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino @@ -13,9 +13,9 @@ // limitations under the License. /** - * @brief This example demonstrates Zigbee analog input / output device. + * @brief This example demonstrates Zigbee binary input device. * - * The example demonstrates how to use Zigbee library to create a end device analog device. + * The example demonstrates how to use Zigbee library to create an end device binary sensor device. * * Proper Zigbee mode must be selected in Tools->Zigbee mode * and also the correct partition scheme must be selected in Tools->Partition Scheme. @@ -23,7 +23,6 @@ * 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/) - * Modified by Pat Clay */ #ifndef ZIGBEE_MODE_ED @@ -32,7 +31,7 @@ #include "Zigbee.h" -/* Zigbee analog device configuration */ +/* Zigbee binary sensor device configuration */ #define BINARY_DEVICE_ENDPOINT_NUMBER 1 uint8_t binaryPin = A0; @@ -43,10 +42,6 @@ ZigbeeBinary zbBinaryZone = ZigbeeBinary(BINARY_DEVICE_ENDPOINT_NUMBER + 1); bool binaryStatus = false; -void onAnalogOutputChange(float analog_output) { - Serial.printf("Received analog output change: %.1f\r\n", analog_output); -} - void setup() { Serial.begin(115200); Serial.println("Starting..."); @@ -89,10 +84,6 @@ void setup() { delay(100); } Serial.println("Connected"); - - // // Optional: Add reporting for analog input - // zbBinaryFan.setBinaryInputReporting(0, 30, 10); // report every 30 seconds if value changes by 10 - // zbBinaryZone.setBinaryInputReporting(0, 30, 10); // report every 30 seconds if value changes by 10 } void loop() { diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.cpp b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp index 97947de2250..69802d0b6b3 100644 --- a/libraries/Zigbee/src/ep/ZigbeeBinary.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp @@ -58,7 +58,7 @@ bool ZigbeeBinary::setBinaryInputApplication(uint32_t application_type) { esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); esp_err_t ret = esp_zb_cluster_update_attr(binary_input_cluster, ESP_ZB_ZCL_ATTR_BINARY_INPUT_APPLICATION_TYPE_ID, (void *)&application_type_value); if (ret != ESP_OK) { - log_e("Failed to set AI application type: 0x%x: %s", ret, esp_err_to_name(ret)); + log_e("Failed to set Binary Input application type: 0x%x: %s", ret, esp_err_to_name(ret)); return false; } return true; diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.h b/libraries/Zigbee/src/ep/ZigbeeBinary.h index 1c958e8d533..6fbdf357ce1 100644 --- a/libraries/Zigbee/src/ep/ZigbeeBinary.h +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.h @@ -1,4 +1,4 @@ -/* Class of Zigbee Analog sensor endpoint inherited from common EP class */ +/* Class of Zigbee Binary sensor endpoint inherited from common EP class */ #pragma once From 6392dd3004c0aa0d86b04458fd555b79347710fb 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, 5 May 2025 18:17:32 +0200 Subject: [PATCH 3/3] feat(zigbee): Remove setBinaryInputReporting --- libraries/Zigbee/src/ep/ZigbeeBinary.cpp | 32 +++--------------------- libraries/Zigbee/src/ep/ZigbeeBinary.h | 5 +--- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.cpp b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp index 69802d0b6b3..639b55c8972 100644 --- a/libraries/Zigbee/src/ep/ZigbeeBinary.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.cpp @@ -64,16 +64,16 @@ bool ZigbeeBinary::setBinaryInputApplication(uint32_t application_type) { return true; } -bool ZigbeeBinary::setBinaryInput(bool binary) { +bool ZigbeeBinary::setBinaryInput(bool input) { esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS; if (!(_binary_clusters & BINARY_INPUT)) { log_e("Binary Input cluster not added"); return false; } - log_d("Setting binary input to %d", binary); + log_d("Setting binary input to %d", input); esp_zb_lock_acquire(portMAX_DELAY); ret = esp_zb_zcl_set_attribute_val( - _endpoint, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, &binary, false + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, &input, false ); esp_zb_lock_release(); if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) { @@ -104,32 +104,6 @@ bool ZigbeeBinary::reportBinaryInput() { return true; } -bool ZigbeeBinary::setBinaryInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) { - esp_zb_zcl_reporting_info_t reporting_info; - memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t)); - reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; - reporting_info.ep = _endpoint; - reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_BINARY_INPUT; - reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; - reporting_info.attr_id = ESP_ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID; - reporting_info.u.send_info.min_interval = min_interval; - reporting_info.u.send_info.max_interval = max_interval; - reporting_info.u.send_info.def_min_interval = min_interval; - reporting_info.u.send_info.def_max_interval = max_interval; - reporting_info.u.send_info.delta.s32 = delta; // TODO: Check if this is correct - reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; - reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; - - esp_zb_lock_acquire(portMAX_DELAY); - esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info); - esp_zb_lock_release(); - if (ret != ESP_OK) { - log_e("Failed to set Binary Input reporting: 0x%x: %s", ret, esp_err_to_name(ret)); - return false; - } - return true; -} - bool ZigbeeBinary::setBinaryInputDescription(const char *description) { if (!(_binary_clusters & BINARY_INPUT)) { log_e("Binary Input cluster not added"); diff --git a/libraries/Zigbee/src/ep/ZigbeeBinary.h b/libraries/Zigbee/src/ep/ZigbeeBinary.h index 6fbdf357ce1..e16daedb353 100644 --- a/libraries/Zigbee/src/ep/ZigbeeBinary.h +++ b/libraries/Zigbee/src/ep/ZigbeeBinary.h @@ -68,14 +68,11 @@ class ZigbeeBinary : public ZigbeeEP { // } // Set the binary input value - bool setBinaryInput(bool binary); + bool setBinaryInput(bool input); // Report Binary Input value bool reportBinaryInput(); - // Set reporting for Binary Input - bool setBinaryInputReporting(uint16_t min_interval, uint16_t max_interval, float delta); - private: // void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;