From 94cc558e6da645c155d5d82f74146d96ca94893d Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:28:02 +0200 Subject: [PATCH 01/34] Initial commit - light bulb + switch working --- .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 13 +- .../examples/Zigbee_Light_Bulb/.skip.esp32 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32c3 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32c6 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32h2 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32s2 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32s3 | 0 .../examples/Zigbee_Light_Bulb/README.md | 73 ++++ .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 75 ++++ .../examples/Zigbee_Light_Switch/.skip.esp32 | 0 .../Zigbee_Light_Switch/.skip.esp32c3 | 0 .../Zigbee_Light_Switch/.skip.esp32c6 | 0 .../Zigbee_Light_Switch/.skip.esp32h2 | 0 .../Zigbee_Light_Switch/.skip.esp32s2 | 0 .../Zigbee_Light_Switch/.skip.esp32s3 | 0 .../examples/Zigbee_Light_Switch/README.md | 73 ++++ .../Zigbee_Light_Switch.ino | 171 +++++++++ .../examples/Zigbee_simple/Zigbee_simple.ino | 93 +++++ libraries/Zigbee/keywords.txt | 27 ++ libraries/Zigbee/library.properties | 8 + libraries/Zigbee/src/Zigbee_core.cpp | 337 ++++++++++++++++++ libraries/Zigbee/src/Zigbee_core.h | 113 ++++++ libraries/Zigbee/src/Zigbee_ep.cpp | 19 + libraries/Zigbee/src/Zigbee_ep.h | 41 +++ libraries/Zigbee/src/ep/ep_on_off_light.cpp | 20 ++ libraries/Zigbee/src/ep/ep_on_off_light.h | 15 + libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 76 ++++ libraries/Zigbee/src/ep/ep_on_off_switch.h | 20 ++ .../Zigbee/src/ep/ep_temperature_sensor.cpp | 20 ++ .../Zigbee/src/ep/ep_temperature_sensor.h | 15 + libraries/Zigbee/src/ep/ep_template.cpp | 23 ++ libraries/Zigbee/src/ep/ep_template.h | 15 + 32 files changed, 1243 insertions(+), 4 deletions(-) create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino create mode 100644 libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino create mode 100644 libraries/Zigbee/keywords.txt create mode 100644 libraries/Zigbee/library.properties create mode 100644 libraries/Zigbee/src/Zigbee_core.cpp create mode 100644 libraries/Zigbee/src/Zigbee_core.h create mode 100644 libraries/Zigbee/src/Zigbee_ep.cpp create mode 100644 libraries/Zigbee/src/Zigbee_ep.h create mode 100644 libraries/Zigbee/src/ep/ep_on_off_light.cpp create mode 100644 libraries/Zigbee/src/ep/ep_on_off_light.h create mode 100644 libraries/Zigbee/src/ep/ep_on_off_switch.cpp create mode 100644 libraries/Zigbee/src/ep/ep_on_off_switch.h create mode 100644 libraries/Zigbee/src/ep/ep_temperature_sensor.cpp create mode 100644 libraries/Zigbee/src/ep/ep_temperature_sensor.h create mode 100644 libraries/Zigbee/src/ep/ep_template.cpp create mode 100644 libraries/Zigbee/src/ep/ep_template.h diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino index 67b9123c937..5cc13c07056 100644 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino @@ -38,7 +38,8 @@ /* Default End Device config */ #define ESP_ZB_ZED_CONFIG() \ { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ .nwk_cfg = { \ .zed_cfg = \ { \ @@ -111,8 +112,12 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; switch (callback_id) { - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; - default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: + ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); + break; + default: + log_w("Receive Zigbee action(0x%x) callback", callback_id); + break; } return ret; } @@ -127,7 +132,7 @@ static void esp_zb_task(void *pvParameters) { esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); //Erase NVRAM before creating connection to new Coordinator - esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator + esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator ESP_ERROR_CHECK(esp_zb_start(false)); esp_zb_main_loop_iteration(); diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md b/libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md new file mode 100644 index 00000000000..cccc97aec98 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md @@ -0,0 +1,73 @@ +# Arduino-ESP32 Zigbee Light Bulb Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. + +**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. +By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. + +#### 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. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` +* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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 + +The ESP Zigbee SDK provides more examples: +* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) +* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino new file mode 100644 index 00000000000..e773dfb966c --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino @@ -0,0 +1,75 @@ +// Copyright 2023 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 light bulb. + * + * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * 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. + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee_core.h" +#include "ep/ep_on_off_light.h" + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define LED_PIN RGB_BUILTIN +#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ + +/* Handle the light attribute */ +// User callback for Zigbee actions to handle turning on/off the light called by Zigbee stack in zb_attribute_handler() + +static void light_cb(const esp_zb_zcl_set_attr_value_message_t *message) { + bool light_state = 0; + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; + log_i("Light sets to %s", light_state ? "On" : "Off"); + neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light + } + } + return; +} + +ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT, light_cb); + +/********************* Arduino functions **************************/ +void setup() { + // Init RMT and leave light OFF + neopixelWrite(LED_PIN, 0, 0, 0); + + //Add endpoint to Zigbee Core + log_d("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbLight); + + // When all EPs are registered, start Zigbee. By default acts as Zigbee_End_Device + log_d("Calling Zigbee.begin()"); + Zigbee.begin(); +} + +void loop() { + //empty, zigbee running in task +} \ No newline at end of file diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Light_Switch/README.md new file mode 100644 index 00000000000..81f9354a6a0 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Light_Switch/README.md @@ -0,0 +1,73 @@ +# Arduino-ESP32 Zigbee Light Switch Example + +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. + +**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). +* A USB cable for power supply and programming. +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Light_switch example). + +### Configure the Project + +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, the LED_PIN is `GPIO_NUM_9`. + +#### 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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. + +## Troubleshooting + +If the End device flashed with the example `Zigbee_Light_Bulb` 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`. +* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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 + +The ESP Zigbee SDK provides more examples: +* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) +* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino new file mode 100644 index 00000000000..56a8f921831 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino @@ -0,0 +1,171 @@ +// Copyright 2023 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 light switch. + * + * The example demonstrates how to use ESP Zigbee stack to control a light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * Button switch and Zigbee runs in separate tasks. + * + * 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. + */ + +#ifndef ZIGBEE_MODE_ZCZR +#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee_core.h" +#include "ep/ep_on_off_switch.h" + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define SWITCH_ENDPOINT_NUMBER 5 + +/* Switch configuration */ +#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 +#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) + +typedef enum { + SWITCH_ON_CONTROL, + SWITCH_OFF_CONTROL, + SWITCH_ONOFF_TOGGLE_CONTROL, + SWITCH_LEVEL_UP_CONTROL, + SWITCH_LEVEL_DOWN_CONTROL, + SWITCH_LEVEL_CYCLE_CONTROL, + SWITCH_COLOR_CONTROL, +} switch_func_t; + +typedef struct { + uint8_t pin; + switch_func_t func; +} switch_func_pair_t; + +typedef enum { + SWITCH_IDLE, + SWITCH_PRESS_ARMED, + SWITCH_PRESS_DETECTED, + SWITCH_PRESSED, + SWITCH_RELEASE_DETECTED, +} switch_state_t; + +static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; + +/********************* Zigbee functions **************************/ +static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { + if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { + /* implemented light switch toggle functionality */ + esp_zb_zcl_on_off_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = SWITCH_ENDPOINT_NUMBER; + 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; + log_i("Send 'on_off toggle' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } +} + +/********************* GPIO functions **************************/ +static QueueHandle_t gpio_evt_queue = NULL; + +static void IRAM_ATTR gpio_isr_handler(void *arg) { + xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); +} + +static void switch_gpios_intr_enabled(bool enabled) { + for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { + if (enabled) { + enableInterrupt((button_func_pair[i]).pin); + } else { + disableInterrupt((button_func_pair[i]).pin); + } + } +} + +ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER,NULL); + +/********************* Arduino functions **************************/ +void setup() { + + Serial.begin(115200); + + //Add endpoint to Zigbee Core + log_d("Adding ZigbeeSwitch endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbSwitch); + + // Init button switch + for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { + pinMode(button_func_pair[i].pin, INPUT_PULLUP); + /* create a queue to handle gpio event from isr */ + gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); + if (gpio_evt_queue == 0) { + log_e("Queue was not created and must not be used"); + while (1); + } + attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); + } + + // When all EPs are registered, start Zigbee. By default acts as Zigbee_End_Device + log_d("Calling Zigbee.begin()"); + Zigbee.begin(Zigbee_Coordinator); + + Serial.println("Waiting for Light to bound to the switch"); + //Wait for switch to bound to a light: + while(!zbSwitch.is_bound()) + { + Serial.printf("."); + delay(500); + } + Serial.println(); +} + +void loop() { + // Handle button switch in loop() + uint8_t pin = 0; + switch_func_pair_t button_func_pair; + static switch_state_t switch_state = SWITCH_IDLE; + bool evt_flag = false; + + + /* check if there is any queue received, if yes read out the button_func_pair */ + if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { + pin = button_func_pair.pin; + switch_gpios_intr_enabled(false); + evt_flag = true; + } + while (evt_flag) { + bool value = digitalRead(pin); + switch (switch_state) { + case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; + case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; + case SWITCH_RELEASE_DETECTED: + switch_state = SWITCH_IDLE; + /* callback to button_handler */ + (*esp_zb_buttons_handler)(&button_func_pair); + break; + default: break; + } + if (switch_state == SWITCH_IDLE) { + switch_gpios_intr_enabled(true); + evt_flag = false; + break; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino b/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino new file mode 100644 index 00000000000..adc2a942878 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino @@ -0,0 +1,93 @@ +// Copyright 2023 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 light bulb. + * + * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * 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. + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define LED_PIN RGB_BUILTIN + +/* Zigbee configuration */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ + +/* Handle the light attribute */ +// User callback for Zigbee actions to handle turning on/off the light called by Zigbee stack in zb_attribute_handler() + +static esp_err_t zigbee_callback(const esp_zb_zcl_set_attr_value_message_t *message) { + esp_err_t ret = ESP_OK; + bool light_state = 0; + + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + + log_i( + "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, + message->attribute.data.size + ); + if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; + log_i("Light sets to %s", light_state ? "On" : "Off"); + neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light + } + } + } + return ret; +} + +ZigbeeEP ZigbeeLight(10,zigbee_callback); + +/********************* Arduino functions **************************/ +void setup() { + // Init RMT and leave light OFF + neopixelWrite(LED_PIN, 0, 0, 0); + + //Setup endpoint + ZigbeeLight.addCluster(ESP_ZB_ZCL_CLUSTER_ID_ON_OFF); + ZigbeeLight.addCluster(ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL); + ZigbeeLight.begin(); //??? + + // When all EPs are registered, start Zigbee stack + Zigbee.begin(); +} + +void loop() { + //empty, zigbee running in task +} diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt new file mode 100644 index 00000000000..da8f18cc2f1 --- /dev/null +++ b/libraries/Zigbee/keywords.txt @@ -0,0 +1,27 @@ +####################################### +# Syntax Coloring Map For Zigbee +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +#TODO: + +####################################### +# Datatypes (KEYWORD1) +####################################### + +#TODO: + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +#TODO: + +####################################### +# Constants (LITERAL1) +####################################### + +#TODO: \ No newline at end of file diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties new file mode 100644 index 00000000000..0c5028b21db --- /dev/null +++ b/libraries/Zigbee/library.properties @@ -0,0 +1,8 @@ +name=Zigbee +version=1.0.0 +author=P-R-O-C-H-Y +maintainer=Jan Procházka +sentence=Enables zigbee connection with the ESP32 +paragraph=With this library you can create zigbee end devices, routers, coordinators and connect them to the zigbee network. +url= +architectures=esp32 diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp new file mode 100644 index 00000000000..24a5948362f --- /dev/null +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -0,0 +1,337 @@ +/* Zigbee Common Functions */ +#include "Zigbee_core.h" +#include "Arduino.h" + +Zigbee_Core::Zigbee_Core() { + _radio_config = ZIGBEE_DEFAULT_RADIO_CONFIG(); + _host_config = ZIGBEE_DEFAULT_HOST_CONFIG(); + _zb_ep_list = esp_zb_ep_list_create(); + _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; + _open_network = 0; +} +Zigbee_Core::~Zigbee_Core() {} + +bool Zigbee_Core::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { + zigbeeInit(role_cfg, erase_nvs); + _role = (zigbee_role_t)role_cfg->esp_zb_role; +} + +bool Zigbee_Core::begin(zigbee_role_t role, bool erase_nvs) { + switch (role) + { + case Zigbee_Coordinator: { + _role = Zigbee_Coordinator; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_COORDINATOR_CONFIG(); + zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + case Zigbee_Router: { + _role = Zigbee_Router; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ROUTER_CONFIG(); + zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + case Zigbee_End_Device: { + _role = Zigbee_End_Device; + esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ED_CONFIG(); + zigbeeInit(&zb_nwk_cfg, erase_nvs); + break; + } + default: + log_e("Invalid Zigbee Role"); + return false; + } + return true; +} + +void Zigbee_Core::addEndpoint(Zigbee_EP *ep) { + ep_objects.push_back(ep); + + log_d("Endpoint: %d, Device ID: 0x%04x", ep->_endpoint, ep->_device_id); + //Register clusters and ep_list to the Zigbee_Core class's ep_list + if (ep->_ep_config.endpoint == 0 || ep->_cluster_list == nullptr) { + log_e("Endpoint config or Cluster list is not initialized, EP not added to Zigbee_Core's EP list"); + return; + } + + esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config); +} + +static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { + esp_err_t ret = ESP_OK; + bool light_state = 0; + + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + + log_i( + "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, + message->attribute.data.size + ); + + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->_endpoint) { + //TODO: implement argument passing to the callback function + //if Zigbee_EP argument is set, pass it to the callback function + // if ((*it)->_arg) { + // (*it)->_cb(message, (*it)->_arg); + // } + // else { + (*it)->_cb(message); + // } + } + } + return ret; +} + + +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { + esp_err_t ret = ESP_OK; + /* TODO: + Implement handlers for different Zigbee actions (callback_id's) + */ + switch (callback_id) { + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; + case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; + default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; + } + return ret; +} + +static void esp_zb_task(void *pvParameters) { + /* initialize Zigbee stack */ + ESP_ERROR_CHECK(esp_zb_start(false)); + esp_zb_main_loop_iteration(); +} + +// Zigbee core init function +void Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { + // Zigbee platform configuration + esp_zb_platform_config_t platform_config = { + .radio_config = _radio_config, + .host_config = _host_config, + }; + ESP_ERROR_CHECK(esp_zb_platform_config(&platform_config)); + + // Initialize Zigbee stack + log_d("Initialize Zigbee stack"); + esp_zb_init(zb_cfg); + + // Register all Zigbee EPs in list + log_d("Register all Zigbee EPs in list"); + esp_zb_device_register(_zb_ep_list); + + //print the list of Zigbee EPs from ep_objects + log_i("List of registered Zigbee EPs:"); + for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { + log_i("Endpoint: %d, Device ID: 0x%04x", (*it)->_endpoint, (*it)->_device_id); //TODO: Idea device id -> device name + } + + // Register Zigbee action handler + esp_zb_core_action_handler_register(zb_action_handler); + esp_zb_set_primary_network_channel_set(_primary_channel_mask); + + //Erase NVRAM before creating connection to new Coordinator + if (erase_nvs) { + esp_zb_nvram_erase_at_start(true); + } + + // Create Zigbee task and start Zigbee stack + xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); +} + +void Zigbee_Core::setRadioConfig(esp_zb_radio_config_t config) { + _radio_config = config; +} + +esp_zb_radio_config_t Zigbee_Core::getRadioConfig() { + return _radio_config; +} + +void Zigbee_Core::setHostConfig(esp_zb_host_config_t config) { + _host_config = config; +} + +esp_zb_host_config_t Zigbee_Core::getHostConfig() { + return _host_config; +} + +void Zigbee_Core::setPrimaryChannelMask(uint32_t mask) { + _primary_channel_mask = mask; +} + +void Zigbee_Core::setRebootOpenNetwork(uint8_t time) { + _open_network = time; +} + +static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { + ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); +} + +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { + //common variables + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + //coordinator variables + esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; + + log_d("Zigbee role: %d", Zigbee._role); + //main switch + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Common + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: // Common + if (err_status == ESP_OK) { + log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); + if (esp_zb_bdb_is_factory_new()) { + // Role specific code + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + log_i("Start network formation"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); + } else { + log_i("Start network steering"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } + //----------------- + + } else { + log_i("Device rebooted"); + + // Implement opening network for joining after reboot if set + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator && Zigbee._open_network > 0) { + log_i("Openning network for joining for %d seconds", Zigbee._open_network); + esp_zb_bdb_open_network(Zigbee._open_network); + } + } + } else { + /* commissioning failed */ + log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i( + "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], + extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() + ); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); + } + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if (err_status == ESP_OK) { + log_i("Network steering started"); + } + } + else { + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i( + "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], + extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() + ); + } else { + log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); + } + } + break; + case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); + log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); + esp_zb_zdo_match_desc_req_param_t cmd_req; + cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; + cmd_req.addr_of_interest = dev_annce_params->device_short_addr; + log_i("Device capabilities: 0x%02x", dev_annce_params->capability); + /* + capability: + Bit 0 – Alternate PAN Coordinator + Bit 1 – Device type: 1- ZigBee Router; 0 – End Device + Bit 2 – Power Source: 1 Main powered + Bit 3 – Receiver on when Idle + Bit 4 – Reserved + Bit 5 – Reserved + Bit 6 – Security capability + Bit 7 – Reserved + */ + + //TODO: Save the device short address and endpoint to the list ???????? + + // for each endpoint in the list call the find_endpoint function if not bounded + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (!(*it)->_is_bound) { + (*it)->find_endpoint(&cmd_req); + } + } + } + break; + case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator + if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if (err_status == ESP_OK) { + if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { + log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); + } else { + log_i("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); + } + } + } + break; + default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; + } +} + +// TODO: Implement scanning network +// /** +// * @brief Active scan available network. +// * +// * Network discovery service for scanning available network +// * +// * @param[in] channel_mask Valid channel mask is from 0x00000800 (only channel 11) to 0x07FFF800 (all channels from 11 to 26) +// * @param[in] scan_duration Time to spend scanning each channel +// * @param[in] user_cb A user callback to get the active scan result please refer to esp_zb_zdo_scan_complete_callback_t +// */ +// void esp_zb_zdo_active_scan_request(uint32_t channel_mask, uint8_t scan_duration, esp_zb_zdo_scan_complete_callback_t user_cb); + +// NOTE: Binding functions to not forget +// void esp_zb_zdo_device_bind_req(esp_zb_zdo_bind_req_param_t *cmd_req, esp_zb_zdo_bind_callback_t user_cb, void *user_ctx) +// { +// uint8_t output = 0; +// uint16_t outlen = sizeof(uint8_t); + +// typedef struct { +// esp_zb_zdo_bind_req_param_t bind_req; +// esp_zb_user_cb_t bind_usr; +// } esp_zb_zdo_bind_req_t; + +// esp_zb_zdo_bind_req_t zdo_data = { +// .bind_usr = { +// .user_ctx = (uint32_t)user_ctx, +// .user_cb = (uint32_t)user_cb, +// }, +// }; + +// memcpy(&zdo_data.bind_req, cmd_req, sizeof(esp_zb_zdo_bind_req_param_t)); +// esp_host_zb_output(ESP_ZNSP_ZDO_BIND_SET, &zdo_data, sizeof(esp_zb_zdo_bind_req_t), &output, &outlen); +// } + +Zigbee_Core Zigbee = Zigbee_Core(); diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h new file mode 100644 index 00000000000..45b1da6c2d3 --- /dev/null +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -0,0 +1,113 @@ +/* Zigbee core class */ + +#pragma once + +#include "esp_zigbee_core.h" +#include "zdo/esp_zigbee_zdo_common.h" +#include +#include +#include "Zigbee_ep.h" +class Zigbee_EP; + +typedef void (*voidFuncPtr)(void); +typedef void (*voidFuncPtrArg)(void *); + +// structure to store callback function and argument +typedef struct { + voidFuncPtr fn; + void *arg; +} zigbee_cb_t; + +// enum of Zigbee Roles +typedef enum { + Zigbee_Coordinator = 0, + Zigbee_Router = 1, + Zigbee_End_Device = 2 +} zigbee_role_t; + +// default Zigbee configuration for each role +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define MAX_CHILDREN 10 + +#define ZIGBEE_DEFAULT_ED_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zed_cfg = \ + { \ + .ed_timeout = ED_AGING_TIMEOUT, \ + .keep_alive = ED_KEEP_ALIVE, \ + }, \ + }, \ + } + +#define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = MAX_CHILDREN, \ + }, \ + } \ + } + + +#define ZIGBEE_DEFAULT_COORDINATOR_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = MAX_CHILDREN, \ + }, \ + } \ + } + +// default Zigbee radio and host configuration +#define ZIGBEE_DEFAULT_RADIO_CONFIG() \ + { .radio_mode = ZB_RADIO_MODE_NATIVE, } + +#define ZIGBEE_DEFAULT_HOST_CONFIG() \ + { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } + +class Zigbee_Core { + private: + esp_zb_radio_config_t _radio_config; + esp_zb_host_config_t _host_config; + uint32_t _primary_channel_mask; + + void zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + + public: + esp_zb_ep_list_t *_zb_ep_list; + zigbee_role_t _role; + uint8_t _open_network; + std::list ep_objects; + + Zigbee_Core(); + ~Zigbee_Core(); + + bool begin(zigbee_role_t role = Zigbee_End_Device, bool erase_nvs = false); + bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); + // bool end(); + + void addEndpoint(Zigbee_EP *ep); + //void removeEndpoint(Zigbee_EP *ep); + + void setRadioConfig(esp_zb_radio_config_t config); + esp_zb_radio_config_t getRadioConfig(); + + void setHostConfig(esp_zb_host_config_t config); + esp_zb_host_config_t getHostConfig(); + + void setPrimaryChannelMask(uint32_t mask); + void setRebootOpenNetwork(uint8_t time); +}; + +extern Zigbee_Core Zigbee; diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp new file mode 100644 index 00000000000..5967badacb2 --- /dev/null +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -0,0 +1,19 @@ +/* Common Class for Zigbee End Point */ + +#include "Zigbee_ep.h" +#include "Arduino.h" + +uint8_t Zigbee_EP::_endpoint = 0; +bool Zigbee_EP::_is_bound = false; + +/* Zigbee End Device Class */ +Zigbee_EP::Zigbee_EP(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) { + _endpoint = endpoint; + _cb = cb; + _ep_config.endpoint = 0; + _cluster_list = nullptr; +} + +Zigbee_EP::~Zigbee_EP() { + +} diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h new file mode 100644 index 00000000000..f9428d995f0 --- /dev/null +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -0,0 +1,41 @@ +/* Common Class for Zigbee End Device */ + +#pragma once + +#include "Zigbee_core.h" + +/* Zigbee End Device Class */ +class Zigbee_EP { + public: + Zigbee_EP(uint8_t endpoint = 10, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message) = NULL); + //Zigbee_EP(uint8_t endpoint = 10, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message) = NULL, void *arg = NULL); + ~Zigbee_EP(); + + virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) = 0; + + void (*_cb)(const esp_zb_zcl_set_attr_value_message_t *message); + //void *_arg; + + static uint8_t _endpoint; + esp_zb_ha_standard_devices_t _device_id; //type of device + uint8_t _version; + + esp_zb_endpoint_config_t _ep_config; + esp_zb_cluster_list_t *_cluster_list; + + // Set ep config and cluster list + void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { + _ep_config = ep_config; + _cluster_list = cluster_list; + } + + static bool _is_bound; + static bool is_bound() { return _is_bound; } + + friend class ZigbeeCore; + + // List of Zigbee EP classes + friend class ZigbeeLight; + +}; + diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp new file mode 100644 index 00000000000..f621ddc25fe --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -0,0 +1,20 @@ +#include "ep_on_off_light.h" + +ZigbeeLight::ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { + _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; + _version = 0; + + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, + .app_device_version = _version + }; +} + +void ZigbeeLight::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + //TODO: Light is looking for switch? + return; +} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.h b/libraries/Zigbee/src/ep/ep_on_off_light.h new file mode 100644 index 00000000000..9c2f60531be --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_on_off_light.h @@ -0,0 +1,15 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeLight : public Zigbee_EP { + public: + ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); + //ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeLight(endpoint, cb, NULL) {} + ~ZigbeeLight(); + + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); +}; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp new file mode 100644 index 00000000000..f52f16c1eb6 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -0,0 +1,76 @@ +#include "ep_on_off_switch.h" +#include +//#include "esp_zigbee_zcl_common.h" + +typedef struct light_bulb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} light_bulb_device_params_t; + +// Definition and initialization of the static member variables + + +ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { + _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; + _version = 0; + + esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); + _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); + + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, + .app_device_version = _version + }; +} + +void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + free(light); + } + _is_bound = true; + } +} + +void ZigbeeSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = _endpoint; //_dev_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_i("Try to bind On/Off"); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); + } else { + log_d("No light endpoint found"); + } +} + +// find on_off light endpoint +void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF}; + esp_zb_zdo_match_desc_req_param_t on_off_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 1, + .num_out_clusters = 1, + .cluster_list = cluster_list, + }; + + esp_zb_zdo_match_cluster(&on_off_req, find_cb, NULL); +} diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h new file mode 100644 index 00000000000..449b31ffaa9 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -0,0 +1,20 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeSwitch : public Zigbee_EP { + public: + ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message));//, void *arg); + // ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeSwitch(endpoint, cb, NULL) {} + ~ZigbeeSwitch(); + + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + + static uint8_t get_endpoint() { return _endpoint; } + +}; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp new file mode 100644 index 00000000000..9d85d5d1202 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -0,0 +1,20 @@ +#include "ep_temperature_sensor.h" + +ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { + _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; + _version = 0; + + esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); + _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, + .app_device_version = _version + }; +} + +void ZigbeeTempSensor::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + //empty function, not used for this type of device + return; +} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.h b/libraries/Zigbee/src/ep/ep_temperature_sensor.h new file mode 100644 index 00000000000..ccb9a168d30 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.h @@ -0,0 +1,15 @@ +/* Class of Zigbee Temperature sensor endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeTempSensor : public Zigbee_EP { + public: + ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); + //ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeTempSensor(endpoint, cb, NULL) {} + ~ZigbeeTempSensor(); + + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); +}; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_template.cpp b/libraries/Zigbee/src/ep/ep_template.cpp new file mode 100644 index 00000000000..417db53265b --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_template.cpp @@ -0,0 +1,23 @@ +#include "ep_template.h" + +ZigbeeDevice::ZigbeeDevice(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { + _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; //TODO: Change to correct device ID + _version = 0; + + //TODO: Change to correct config + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); + + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, //TODO: Change to correct device ID + .app_device_version = _version + }; +} + +void ZigbeeDevice::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + // If device is looking for a endpoint, implement this function + find_cb and bind_cb callbacks + // for reference check ZigbeeSwitch::find_endpoint, ZigbeeSwitch::find_cb and ZigbeeSwitch::bind_cb + return; +} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_template.h b/libraries/Zigbee/src/ep/ep_template.h new file mode 100644 index 00000000000..8272797715e --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_template.h @@ -0,0 +1,15 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeDevice : public Zigbee_EP { + public: + ZigbeeDevice(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); + //ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeLight(endpoint, cb, NULL) {} + ~ZigbeeDevice(); + + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); +}; \ No newline at end of file From 7776aa53c2ab932ced140afb1bc4e471d6af00ea Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:28:34 +0200 Subject: [PATCH 02/34] Add Thermostat + fix enum --- libraries/Zigbee/src/Zigbee_core.cpp | 12 +-- libraries/Zigbee/src/Zigbee_core.h | 6 +- libraries/Zigbee/src/ep/ep_thermostat.cpp | 108 ++++++++++++++++++++++ libraries/Zigbee/src/ep/ep_thermostat.h | 18 ++++ 4 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 libraries/Zigbee/src/ep/ep_thermostat.cpp create mode 100644 libraries/Zigbee/src/ep/ep_thermostat.h diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 24a5948362f..97d304afd0a 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -194,7 +194,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); if (esp_zb_bdb_is_factory_new()) { // Role specific code - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { log_i("Start network formation"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); } else { @@ -207,7 +207,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { log_i("Device rebooted"); // Implement opening network for joining after reboot if set - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator && Zigbee._open_network > 0) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { log_i("Openning network for joining for %d seconds", Zigbee._open_network); esp_zb_bdb_open_network(Zigbee._open_network); } @@ -218,7 +218,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { esp_zb_ieee_addr_t extended_pan_id; esp_zb_get_extended_pan_id(extended_pan_id); @@ -235,7 +235,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { log_i("Network steering started"); } @@ -256,7 +256,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); esp_zb_zdo_match_desc_req_param_t cmd_req; @@ -286,7 +286,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator - if ((zigbee_role_t)Zigbee._role == Zigbee_Coordinator) { + if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h index 45b1da6c2d3..1904013e44f 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -20,9 +20,9 @@ typedef struct { // enum of Zigbee Roles typedef enum { - Zigbee_Coordinator = 0, - Zigbee_Router = 1, - Zigbee_End_Device = 2 + ZIGBEE_COORDINATOR = 0, + ZIGBEE_ROUTER = 1, + ZIGBEE_END_DEVICE = 2 } zigbee_role_t; // default Zigbee configuration for each role diff --git a/libraries/Zigbee/src/ep/ep_thermostat.cpp b/libraries/Zigbee/src/ep/ep_thermostat.cpp new file mode 100644 index 00000000000..969244515f6 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_thermostat.cpp @@ -0,0 +1,108 @@ +#include "ep_temperature_sensor.h" + +ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { + _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; + _version = 0; + + esp_zb_thermostat_cfg_t thermostat_cfg = ESP_ZB_DEFAULT_THERMOSTAT_CONFIG(); + _cluster_list = esp_zb_thermostat_clusters_create(&thermostat_cfg); + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, + .app_device_version = _version + }; +} + +static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)user_ctx; + + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + /* Local binding succeeds */ + if (bind_req->req_dst_addr == esp_zb_get_short_address()) { + log_i("Successfully bind the temperature sensor from address(0x%x) on endpoint(%d)", temp_sensor.short_addr, temp_sensor.endpoint); + + /* Read peer Manufacture Name & Model Identifier */ + 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 = HA_THERMOSTAT_ENDPOINT; + read_req.zcl_basic_cmd.dst_endpoint = temp_sensor.endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = temp_sensor.short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, + ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, + }; + read_req.attr_number = ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + esp_zb_zcl_read_attr_cmd_req(&read_req); + } + if (bind_req->req_dst_addr == temp_sensor.short_addr) { + log_i("The temperature sensor from address(0x%x) on endpoint(%d) successfully binds us", temp_sensor.short_addr, temp_sensor.endpoint); + } + free(bind_req); + } else { + /* Bind failed, maybe retry the binding ? */ + + // esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + } +} + +static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Found temperature sensor"); + /* Store the information of the remote device */ + temp_sensor_device_params_t *sensor = (temp_sensor_device_params_t *)user_ctx; + sensor->endpoint = endpoint; + sensor->short_addr = addr; + esp_zb_ieee_address_by_short(sensor->short_addr, sensor->ieee_addr); + log_d("Temperature sensor found: short address(0x%x), endpoint(%d)", sensor->short_addr, sensor->endpoint); + + /* 1. Send binding request to the sensor */ + esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); + bind_req->req_dst_addr = addr; + log_d("Request temperature sensor to bind us"); + + /* populate the src information of the binding */ + memcpy(bind_req->src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req->src_endp = endpoint; + bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + log_d("Bind temperature sensor"); + + /* populate the dst information of the binding */ + bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + esp_zb_get_long_address(bind_req->dst_address_u.addr_long); + bind_req->dst_endp = HA_THERMOSTAT_ENDPOINT; + + log_i("Request temperature sensor to bind us"); + esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + + /* 2. Send binding request to self */ + bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); + bind_req->req_dst_addr = esp_zb_get_short_address(); + + /* populate the src information of the binding */ + esp_zb_get_long_address(bind_req->src_address); + bind_req->src_endp = HA_THERMOSTAT_ENDPOINT; + bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + /* populate the dst information of the binding */ + bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req->dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req->dst_endp = endpoint; + + log_i("Bind temperature sensor"); + esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + } +} + +void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; + param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; + param->num_in_clusters = 1; + param->num_out_clusters = 0; + param->cluster_list = cluster_list; + esp_zb_zdo_match_cluster(param, user_cb, (void *)&temp_sensor); +} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_thermostat.h b/libraries/Zigbee/src/ep/ep_thermostat.h new file mode 100644 index 00000000000..3ca06cad604 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_thermostat.h @@ -0,0 +1,18 @@ +/* Class of Zigbee Temperature sensor endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeThermostat : public Zigbee_EP { + public: + ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); + //ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeTempSensor(endpoint, cb, NULL) {} + ~ZigbeeThermostat(); + + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + +}; \ No newline at end of file From 8ce22e119f7c49c8915f5cc5da1e2188b88284a0 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:38:51 +0200 Subject: [PATCH 03/34] Dev update: roles, cb removal, handlers Fixed ep_thermostat to compile successfully Removed cb from all EP, as it have been removed, virtual methods will be used instead. Moved zigbee handlers out of Zigbee_core to Zigbee_handlers for better readability. Fixed zigbeeInit to be bool and return status of initialization for begin function. Updated examples with edited roles and custom method for on_off light --- .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 25 ++- .../Zigbee_Light_Switch.ino | 9 +- libraries/Zigbee/src/Zigbee_core.cpp | 182 ++++++++++++------ libraries/Zigbee/src/Zigbee_core.h | 8 +- libraries/Zigbee/src/Zigbee_ep.cpp | 4 +- libraries/Zigbee/src/Zigbee_ep.h | 60 +++++- libraries/Zigbee/src/Zigbee_handlers.cpp | 82 ++++++++ libraries/Zigbee/src/ep/ep_on_off_light.cpp | 32 ++- libraries/Zigbee/src/ep/ep_on_off_light.h | 10 +- libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 7 +- libraries/Zigbee/src/ep/ep_on_off_switch.h | 3 +- .../Zigbee/src/ep/ep_temperature_sensor.cpp | 2 +- .../Zigbee/src/ep/ep_temperature_sensor.h | 3 +- libraries/Zigbee/src/ep/ep_template.cpp | 2 +- libraries/Zigbee/src/ep/ep_template.h | 3 +- libraries/Zigbee/src/ep/ep_thermostat.cpp | 32 +-- libraries/Zigbee/src/ep/ep_thermostat.h | 24 ++- 17 files changed, 367 insertions(+), 121 deletions(-) create mode 100644 libraries/Zigbee/src/Zigbee_handlers.cpp diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino index e773dfb966c..5c0d8470321 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino @@ -39,22 +39,19 @@ #define LED_PIN RGB_BUILTIN #define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ -/* Handle the light attribute */ -// User callback for Zigbee actions to handle turning on/off the light called by Zigbee stack in zb_attribute_handler() +class MyZigbeeLight : public ZigbeeLight { +public: + // Constructor that passes parameters to the base class constructor + MyZigbeeLight(uint8_t endpoint) : ZigbeeLight(endpoint) {} -static void light_cb(const esp_zb_zcl_set_attr_value_message_t *message) { - bool light_state = 0; - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; - log_i("Light sets to %s", light_state ? "On" : "Off"); - neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light + // Override the set_on_off function + void set_on_off(bool value) override { + log_v("Overwritten method, set on/off: %d", value); + neopixelWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light } - } - return; -} +}; -ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT, light_cb); +MyZigbeeLight zbLight = MyZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); /********************* Arduino functions **************************/ void setup() { @@ -65,7 +62,7 @@ void setup() { log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); - // When all EPs are registered, start Zigbee. By default acts as Zigbee_End_Device + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE log_d("Calling Zigbee.begin()"); Zigbee.begin(); } diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino index 56a8f921831..aeb95a0799f 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino @@ -98,7 +98,7 @@ static void switch_gpios_intr_enabled(bool enabled) { } } -ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER,NULL); +ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); /********************* Arduino functions **************************/ void setup() { @@ -108,6 +108,9 @@ void setup() { //Add endpoint to Zigbee Core log_d("Adding ZigbeeSwitch endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbSwitch); + + //Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); // Init button switch for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { @@ -121,9 +124,9 @@ void setup() { attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); } - // When all EPs are registered, start Zigbee. By default acts as Zigbee_End_Device + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode log_d("Calling Zigbee.begin()"); - Zigbee.begin(Zigbee_Coordinator); + Zigbee.begin(ZIGBEE_COORDINATOR); Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 97d304afd0a..714a1e1c41b 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -1,5 +1,6 @@ /* Zigbee Common Functions */ #include "Zigbee_core.h" +#include "Zigbee_handlers.cpp" #include "Arduino.h" Zigbee_Core::Zigbee_Core() { @@ -11,37 +12,44 @@ Zigbee_Core::Zigbee_Core() { } Zigbee_Core::~Zigbee_Core() {} +//forward declaration +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message); + bool Zigbee_Core::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { - zigbeeInit(role_cfg, erase_nvs); + if (!zigbeeInit(role_cfg, erase_nvs)){ + return false; + } _role = (zigbee_role_t)role_cfg->esp_zb_role; + return true; } bool Zigbee_Core::begin(zigbee_role_t role, bool erase_nvs) { + bool status = true; switch (role) { - case Zigbee_Coordinator: { - _role = Zigbee_Coordinator; + case ZIGBEE_COORDINATOR: { + _role = ZIGBEE_COORDINATOR; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_COORDINATOR_CONFIG(); - zigbeeInit(&zb_nwk_cfg, erase_nvs); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } - case Zigbee_Router: { - _role = Zigbee_Router; + case ZIGBEE_ROUTER: { + _role = ZIGBEE_ROUTER; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ROUTER_CONFIG(); - zigbeeInit(&zb_nwk_cfg, erase_nvs); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } - case Zigbee_End_Device: { - _role = Zigbee_End_Device; + case ZIGBEE_END_DEVICE: { + _role = ZIGBEE_END_DEVICE; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ED_CONFIG(); - zigbeeInit(&zb_nwk_cfg, erase_nvs); + status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } default: log_e("Invalid Zigbee Role"); return false; } - return true; + return status; } void Zigbee_Core::addEndpoint(Zigbee_EP *ep) { @@ -57,52 +65,6 @@ void Zigbee_Core::addEndpoint(Zigbee_EP *ep) { esp_zb_ep_list_add_ep(_zb_ep_list, ep->_cluster_list, ep->_ep_config); } -static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { - esp_err_t ret = ESP_OK; - bool light_state = 0; - - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - - log_i( - "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, - message->attribute.data.size - ); - - // List through all Zigbee EPs and call the callback function, with the message - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (message->info.dst_endpoint == (*it)->_endpoint) { - //TODO: implement argument passing to the callback function - //if Zigbee_EP argument is set, pass it to the callback function - // if ((*it)->_arg) { - // (*it)->_cb(message, (*it)->_arg); - // } - // else { - (*it)->_cb(message); - // } - } - } - return ret; -} - - -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { - esp_err_t ret = ESP_OK; - /* TODO: - Implement handlers for different Zigbee actions (callback_id's) - */ - switch (callback_id) { - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; - case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; - default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; - } - return ret; -} - static void esp_zb_task(void *pvParameters) { /* initialize Zigbee stack */ ESP_ERROR_CHECK(esp_zb_start(false)); @@ -110,13 +72,18 @@ static void esp_zb_task(void *pvParameters) { } // Zigbee core init function -void Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { +bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { // Zigbee platform configuration esp_zb_platform_config_t platform_config = { .radio_config = _radio_config, .host_config = _host_config, }; - ESP_ERROR_CHECK(esp_zb_platform_config(&platform_config)); + + esp_err_t err = esp_zb_platform_config(&platform_config); + if (err != ESP_OK) { + log_e("Failed to configure Zigbee platform"); + return false; + } // Initialize Zigbee stack log_d("Initialize Zigbee stack"); @@ -124,7 +91,11 @@ void Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { // Register all Zigbee EPs in list log_d("Register all Zigbee EPs in list"); - esp_zb_device_register(_zb_ep_list); + err = esp_zb_device_register(_zb_ep_list); + if (err != ESP_OK) { + log_e("Failed to register Zigbee EPs"); + return false; + } //print the list of Zigbee EPs from ep_objects log_i("List of registered Zigbee EPs:"); @@ -134,7 +105,11 @@ void Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { // Register Zigbee action handler esp_zb_core_action_handler_register(zb_action_handler); - esp_zb_set_primary_network_channel_set(_primary_channel_mask); + err = esp_zb_set_primary_network_channel_set(_primary_channel_mask); + if (err != ESP_OK) { + log_e("Failed to set primary network channel mask"); + return false; + } //Erase NVRAM before creating connection to new Coordinator if (erase_nvs) { @@ -143,6 +118,8 @@ void Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { // Create Zigbee task and start Zigbee stack xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); + + return true; } void Zigbee_Core::setRadioConfig(esp_zb_radio_config_t config) { @@ -300,6 +277,89 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } +// // Zigbee action handlers +// static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { +// esp_err_t ret = ESP_OK; +// /* TODO: +// Implement handlers for different Zigbee actions (callback_id's) +// */ +// // NOTE: Implement all Zigbee actions that can be handled by the Zigbee_Core class, or just call user defined callback function and let the user handle the action and read the message properly +// // NOTE: This may me harder for users, to know what callback_id's are available and what message type is received +// switch (callback_id) { +// case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; +// case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; +// case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; +// case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; +// case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; +// default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; +// } + +// //TODO: get destination endpoint from the message: +// uint8_t dst_endpoint = ((esp_zb_zcl_set_attr_value_message_t *)message)->info.dst_endpoint; + + + +// return ret; +// } + +// static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { +// if (!message) { +// log_e("Empty message"); +// } +// if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { +// log_e("Received message: error status(%d)", message->info.status); +// } + +// log_i( +// "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, +// message->attribute.data.size +// ); + +// // List through all Zigbee EPs and call the callback function, with the message +// for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { +// if (message->info.dst_endpoint == (*it)->_endpoint) { +// //TODO: implement argument passing to the callback function +// //if Zigbee_EP argument is set, pass it to the callback function +// // if ((*it)->_arg) { +// // (*it)->_cb(message, (*it)->_arg); +// // } +// // else { +// (*it)->_cb(message); //method zb_attribute_set_handler in the LIGHT EP +// // } +// } +// } +// return ESP_OK; +// } + +// static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { +// if (!message) { +// log_e("Empty message"); +// } +// if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { +// log_e("Received message: error status(%d)", message->status); +// } +// log_i( +// "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, +// message->dst_endpoint, message->cluster +// ); +// // List through all Zigbee EPs and call the callback function, with the message +// for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { +// if (message->info.dst_endpoint == (*it)->_endpoint) { +// //TODO: implement argument passing to the callback function +// //if Zigbee_EP argument is set, pass it to the callback function +// // if ((*it)->_arg) { +// // (*it)->_cb(message, (*it)->_arg); +// // } +// // else { +// (*it)->_cb(message); +// // } +// } +// } +// return ESP_OK; +// } + + + // TODO: Implement scanning network // /** // * @brief Active scan available network. diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h index 1904013e44f..365d46c9020 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -20,8 +20,8 @@ typedef struct { // enum of Zigbee Roles typedef enum { - ZIGBEE_COORDINATOR = 0, - ZIGBEE_ROUTER = 1, + ZIGBEE_COORDINATOR = 0, + ZIGBEE_ROUTER = 1, ZIGBEE_END_DEVICE = 2 } zigbee_role_t; @@ -82,7 +82,7 @@ class Zigbee_Core { esp_zb_host_config_t _host_config; uint32_t _primary_channel_mask; - void zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); public: esp_zb_ep_list_t *_zb_ep_list; @@ -93,7 +93,7 @@ class Zigbee_Core { Zigbee_Core(); ~Zigbee_Core(); - bool begin(zigbee_role_t role = Zigbee_End_Device, bool erase_nvs = false); + bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); // bool end(); diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index 5967badacb2..df6f4bfa9f2 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -1,15 +1,13 @@ /* Common Class for Zigbee End Point */ #include "Zigbee_ep.h" -#include "Arduino.h" uint8_t Zigbee_EP::_endpoint = 0; bool Zigbee_EP::_is_bound = false; /* Zigbee End Device Class */ -Zigbee_EP::Zigbee_EP(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) { +Zigbee_EP::Zigbee_EP(uint8_t endpoint) { _endpoint = endpoint; - _cb = cb; _ep_config.endpoint = 0; _cluster_list = nullptr; } diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index f9428d995f0..93d361ef09f 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -3,19 +3,19 @@ #pragma once #include "Zigbee_core.h" +#include + +/* Usefull defines */ +#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) /* Zigbee End Device Class */ class Zigbee_EP { public: - Zigbee_EP(uint8_t endpoint = 10, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message) = NULL); - //Zigbee_EP(uint8_t endpoint = 10, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message) = NULL, void *arg = NULL); + Zigbee_EP(uint8_t endpoint = 10); ~Zigbee_EP(); virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) = 0; - void (*_cb)(const esp_zb_zcl_set_attr_value_message_t *message); - //void *_arg; - static uint8_t _endpoint; esp_zb_ha_standard_devices_t _device_id; //type of device uint8_t _version; @@ -32,10 +32,60 @@ class Zigbee_EP { static bool _is_bound; static bool is_bound() { return _is_bound; } + + //list of all handlers function calls, to be overide by EPs implementation + virtual void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) {}; + friend class ZigbeeCore; // List of Zigbee EP classes friend class ZigbeeLight; + /* TODO: create all possible methods for each EP type, that can be overwritten by user to use them + + // NOTE: This is a list of all possible callbacks that can be used in Zigbee_EP class + // typedef enum esp_zb_core_action_callback_id_s { + // ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID = 0x0000, /*!< Set attribute value, refer to esp_zb_zcl_set_attr_value_message_t */ + // ESP_ZB_CORE_SCENES_STORE_SCENE_CB_ID = 0x0001, /*!< Store scene, refer to esp_zb_zcl_store_scene_message_t */ + // ESP_ZB_CORE_SCENES_RECALL_SCENE_CB_ID = 0x0002, /*!< Recall scene, refer to esp_zb_zcl_recall_scene_message_t */ + // ESP_ZB_CORE_IAS_ZONE_ENROLL_RESPONSE_VALUE_CB_ID = 0x0003, /*!< IAS Zone enroll response, refer to esp_zb_zcl_ias_zone_enroll_response_message_t */ + // ESP_ZB_CORE_OTA_UPGRADE_VALUE_CB_ID = 0x0004, /*!< Upgrade OTA, refer to esp_zb_zcl_ota_upgrade_value_message_t */ + // ESP_ZB_CORE_OTA_UPGRADE_SRV_STATUS_CB_ID = 0x0005, /*!< OTA Server status, refer to esp_zb_zcl_ota_upgrade_server_status_message_t */ + // ESP_ZB_CORE_OTA_UPGRADE_SRV_QUERY_IMAGE_CB_ID = 0x0006, /*!< OTA Server query image, refer to esp_zb_zcl_ota_upgrade_server_query_image_message_t */ + // ESP_ZB_CORE_THERMOSTAT_VALUE_CB_ID = 0x0007, /*!< Thermostat value, refer to esp_zb_zcl_thermostat_value_message_t */ + // ESP_ZB_CORE_METERING_GET_PROFILE_CB_ID = 0x0008, /*!< Metering get profile, refer to esp_zb_zcl_metering_get_profile_message_t */ + // ESP_ZB_CORE_METERING_GET_PROFILE_RESP_CB_ID = 0x0009, /*!< Metering get profile response, refer to esp_zb_zcl_metering_get_profile_resp_message_t */ + // ESP_ZB_CORE_METERING_REQ_FAST_POLL_MODE_CB_ID = 0x000a, /*!< Metering request fast poll mode, refer to esp_zb_zcl_metering_request_fast_poll_mode_message_t */ + // ESP_ZB_CORE_METERING_REQ_FAST_POLL_MODE_RESP_CB_ID = 0x000b, /*!< Metering request fast poll mode response, refer to esp_zb_zcl_metering_request_fast_poll_mode_resp_message_t */ + // ESP_ZB_CORE_METERING_GET_SNAPSHOT_CB_ID = 0x000c, /*!< Metering get snapshot, refer to esp_zb_zcl_metering_get_snapshot_message_t */ + // ESP_ZB_CORE_METERING_PUBLISH_SNAPSHOT_CB_ID = 0x000d, /*!< Metering publish snapshot, refer to esp_zb_zcl_metering_publish_snapshot_message_t */ + // ESP_ZB_CORE_METERING_GET_SAMPLED_DATA_CB_ID = 0x000e, /*!< Metering get sampled data, refer to esp_zb_zcl_metering_get_sampled_data_message_t */ + // ESP_ZB_CORE_METERING_GET_SAMPLED_DATA_RESP_CB_ID = 0x000f, /*!< Metering get sampled data response, refer to esp_zb_zcl_metering_get_sampled_data_resp_message_t */ + // ESP_ZB_CORE_DOOR_LOCK_LOCK_DOOR_CB_ID = 0x0010, /*!< Lock/unlock door request, refer to esp_zb_zcl_door_lock_lock_door_message_t */ + // ESP_ZB_CORE_DOOR_LOCK_LOCK_DOOR_RESP_CB_ID = 0x0011, /*!< Lock/unlock door response, refer to esp_zb_zcl_door_lock_lock_door_resp_message_t */ + // ESP_ZB_CORE_IDENTIFY_EFFECT_CB_ID = 0x0012, /*!< Identify triggers effect request, refer to esp_zb_zcl_identify_effect_message_t */ + // ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID = 0x1000, /*!< Read attribute response, refer to esp_zb_zcl_cmd_read_attr_resp_message_t */ + // ESP_ZB_CORE_CMD_WRITE_ATTR_RESP_CB_ID = 0x1001, /*!< Write attribute response, refer to esp_zb_zcl_cmd_write_attr_resp_message_t */ + // ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID = 0x1002, /*!< Configure reprot response, refer to esp_zb_zcl_cmd_config_report_resp_message_t */ + // ESP_ZB_CORE_CMD_READ_REPORT_CFG_RESP_CB_ID = 0x1003, /*!< Read report configuration response, refer to esp_zb_zcl_cmd_read_report_config_resp_message_t */ + // ESP_ZB_CORE_CMD_DISC_ATTR_RESP_CB_ID = 0x1004, /*!< Discover attributes response, refer to esp_zb_zcl_cmd_discover_attributes_resp_message_t */ + // ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID = 0x1005, /*!< Default response, refer to esp_zb_zcl_cmd_default_resp_message_t */ + // ESP_ZB_CORE_CMD_OPERATE_GROUP_RESP_CB_ID = 0x1010, /*!< Group add group response, refer to esp_zb_zcl_groups_operate_group_resp_message_t */ + // ESP_ZB_CORE_CMD_VIEW_GROUP_RESP_CB_ID = 0x1011, /*!< Group view response, refer to esp_zb_zcl_groups_view_group_resp_message_t */ + // ESP_ZB_CORE_CMD_GET_GROUP_MEMBERSHIP_RESP_CB_ID = 0x1012, /*!< Group get membership response, refer to esp_zb_zcl_groups_get_group_membership_resp_message_t */ + // ESP_ZB_CORE_CMD_OPERATE_SCENE_RESP_CB_ID = 0x1020, /*!< Scenes operate response, refer to esp_zb_zcl_scenes_operate_scene_resp_message_t */ + // ESP_ZB_CORE_CMD_VIEW_SCENE_RESP_CB_ID = 0x1021, /*!< Scenes view response, refer to esp_zb_zcl_scenes_view_scene_resp_message_t */ + // ESP_ZB_CORE_CMD_GET_SCENE_MEMBERSHIP_RESP_CB_ID = 0x1022, /*!< Scenes get membership response, refer to esp_zb_zcl_scenes_get_scene_membership_resp_message_t */ + // ESP_ZB_CORE_CMD_IAS_ZONE_ZONE_ENROLL_REQUEST_ID = 0x1030, /*!< IAS Zone enroll request, refer to esp_zb_zcl_ias_zone_enroll_request_message_t */ + // ESP_ZB_CORE_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID = 0x1031, /*!< IAS Zone status change notification, refer to esp_zb_zcl_ias_zone_status_change_notification_message_t */ + // ESP_ZB_CORE_CMD_CUSTOM_CLUSTER_REQ_CB_ID = 0x1040, /*!< Custom Cluster request, refer to esp_zb_zcl_custom_cluster_command_message_t */ + // ESP_ZB_CORE_CMD_CUSTOM_CLUSTER_RESP_CB_ID = 0x1041, /*!< Custom Cluster response, refer to esp_zb_zcl_custom_cluster_command_message_t */ + // ESP_ZB_CORE_CMD_PRIVILEGE_COMMAND_REQ_CB_ID = 0x1050, /*!< Custom Cluster request, refer to esp_zb_zcl_privilege_command_message_t */ + // ESP_ZB_CORE_CMD_PRIVILEGE_COMMAND_RESP_CB_ID = 0x1051, /*!< Custom Cluster response, refer to esp_zb_zcl_privilege_command_message_t */ + // ESP_ZB_CORE_CMD_GREEN_POWER_RECV_CB_ID = 0x1F00, /*!< Green power cluster command receiving, refer to esp_zb_zcl_cmd_green_power_recv_message_t */ + // ESP_ZB_CORE_REPORT_ATTR_CB_ID = 0x2000, /*!< Attribute Report, refer to esp_zb_zcl_report_attr_message_t */ + // } esp_zb_core_action_callback_id_t; + + }; diff --git a/libraries/Zigbee/src/Zigbee_handlers.cpp b/libraries/Zigbee/src/Zigbee_handlers.cpp new file mode 100644 index 00000000000..59594038e8a --- /dev/null +++ b/libraries/Zigbee/src/Zigbee_handlers.cpp @@ -0,0 +1,82 @@ +/* Zigbee Common Functions */ +#include "Zigbee_core.h" +#include "Arduino.h" + +// forward declaration of all implemented handlers +static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); +static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); + +// Zigbee action handlers +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { + esp_err_t ret = ESP_OK; + /* TODO: + Implement handlers for different Zigbee actions (callback_id's) + */ + // NOTE: Implement all Zigbee actions that can be handled by the Zigbee_Core class, or just call user defined callback function and let the user handle the action and read the message properly + // NOTE: This may me harder for users, to know what callback_id's are available and what message type is received + switch (callback_id) { + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; + case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; + // case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; + // case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; + default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; + } + return ret; +} + +static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + + log_i( + "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, + message->attribute.data.size + ); + + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->_endpoint) { + //TODO: implement argument passing to the callback function + //if Zigbee_EP argument is set, pass it to the callback function + // if ((*it)->_arg) { + // (*it)->_cb(message, (*it)->_arg); + // } + // else { + (*it)->attribute_set(message); //method zb_attribute_set_handler in the LIGHT EP + // } + } + } + return ESP_OK; +} + +static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->status); + } + log_i( + "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, + message->dst_endpoint, message->cluster + ); + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->dst_endpoint == (*it)->_endpoint) { + //TODO: implement argument passing to the callback function + //if Zigbee_EP argument is set, pass it to the callback function + // if ((*it)->_arg) { + // (*it)->_cb(message, (*it)->_arg); + // } + // else { + //(*it)->_cb(message); //method zb_attribute_reporting_handler in the EP + // } + } + } + return ESP_OK; +} diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index f621ddc25fe..e9f3fb6a7be 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -1,6 +1,6 @@ #include "ep_on_off_light.h" -ZigbeeLight::ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { +ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; _version = 0; @@ -15,6 +15,34 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_ } void ZigbeeLight::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - //TODO: Light is looking for switch? + //NOTE: Light is looking for switch? return; +} + +//set attribude method -> methon overriden in child class +void ZigbeeLight::attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) { + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + bool light_state = 0; + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; + set_on_off(light_state); + } + } + // if (message->attr_id == ESP_ZB_ON_OFF_LIGHT_ATTR_ON_OFF) { + // //call method to set on/off + // set_on_off(message->attribute.data[0]); + // } + // else if (message->attr_id == ESP_ZB_ON_OFF_LIGHT_ATTR_LEVEL) { + // //call method to set level + // } + else { + //unknown attribute + } +} + +//default method to set on/off +void ZigbeeLight::set_on_off(bool value) { + //set on/off + log_v("Function not overwritten, set on/off: %d", value); } \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.h b/libraries/Zigbee/src/ep/ep_on_off_light.h index 9c2f60531be..4d52ba05f72 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.h +++ b/libraries/Zigbee/src/ep/ep_on_off_light.h @@ -7,9 +7,15 @@ class ZigbeeLight : public Zigbee_EP { public: - ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); - //ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeLight(endpoint, cb, NULL) {} + ZigbeeLight(uint8_t endpoint); ~ZigbeeLight(); + // methods to be implemented by the user by overwritting them + virtual void set_on_off(bool value); + + private: void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + + void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; + }; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index f52f16c1eb6..e025d56dd7a 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -1,6 +1,4 @@ #include "ep_on_off_switch.h" -#include -//#include "esp_zigbee_zcl_common.h" typedef struct light_bulb_device_params_s { esp_zb_ieee_addr_t ieee_addr; @@ -8,10 +6,7 @@ typedef struct light_bulb_device_params_s { uint16_t short_addr; } light_bulb_device_params_t; -// Definition and initialization of the static member variables - - -ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { +ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; _version = 0; diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h index 449b31ffaa9..b1fff42d0ce 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -7,8 +7,7 @@ class ZigbeeSwitch : public Zigbee_EP { public: - ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message));//, void *arg); - // ZigbeeSwitch(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeSwitch(endpoint, cb, NULL) {} + ZigbeeSwitch(uint8_t endpoint); ~ZigbeeSwitch(); void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp index 9d85d5d1202..552556dee26 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -1,6 +1,6 @@ #include "ep_temperature_sensor.h" -ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { +ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; _version = 0; diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.h b/libraries/Zigbee/src/ep/ep_temperature_sensor.h index ccb9a168d30..f05dde0875b 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.h +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.h @@ -7,8 +7,7 @@ class ZigbeeTempSensor : public Zigbee_EP { public: - ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); - //ZigbeeTempSensor(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeTempSensor(endpoint, cb, NULL) {} + ZigbeeTempSensor(uint8_t endpoint); ~ZigbeeTempSensor(); void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); diff --git a/libraries/Zigbee/src/ep/ep_template.cpp b/libraries/Zigbee/src/ep/ep_template.cpp index 417db53265b..404b17d4369 100644 --- a/libraries/Zigbee/src/ep/ep_template.cpp +++ b/libraries/Zigbee/src/ep/ep_template.cpp @@ -1,6 +1,6 @@ #include "ep_template.h" -ZigbeeDevice::ZigbeeDevice(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { +ZigbeeDevice::ZigbeeDevice(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; //TODO: Change to correct device ID _version = 0; diff --git a/libraries/Zigbee/src/ep/ep_template.h b/libraries/Zigbee/src/ep/ep_template.h index 8272797715e..47a779de794 100644 --- a/libraries/Zigbee/src/ep/ep_template.h +++ b/libraries/Zigbee/src/ep/ep_template.h @@ -7,8 +7,7 @@ class ZigbeeDevice : public Zigbee_EP { public: - ZigbeeDevice(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); - //ZigbeeLight(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeLight(endpoint, cb, NULL) {} + ZigbeeDevice(uint8_t endpoint); ~ZigbeeDevice(); void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); diff --git a/libraries/Zigbee/src/ep/ep_thermostat.cpp b/libraries/Zigbee/src/ep/ep_thermostat.cpp index 969244515f6..bd1960ff619 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.cpp +++ b/libraries/Zigbee/src/ep/ep_thermostat.cpp @@ -1,10 +1,20 @@ -#include "ep_temperature_sensor.h" +#include "ep_thermostat.h" -ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : Zigbee_EP(endpoint, cb) { +typedef struct temp_sensor_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} temp_sensor_device_params_t; + +static temp_sensor_device_params_t temp_sensor; + +ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; _version = 0; - esp_zb_thermostat_cfg_t thermostat_cfg = ESP_ZB_DEFAULT_THERMOSTAT_CONFIG(); + //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk + esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); + _cluster_list = esp_zb_thermostat_clusters_create(&thermostat_cfg); _ep_config = { .endpoint = _endpoint, @@ -14,7 +24,7 @@ ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl }; } -static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { +void ZigbeeThermostat::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)user_ctx; if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { @@ -25,7 +35,7 @@ static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { /* Read peer Manufacture Name & Model Identifier */ 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 = HA_THERMOSTAT_ENDPOINT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.zcl_basic_cmd.dst_endpoint = temp_sensor.endpoint; read_req.zcl_basic_cmd.dst_addr_u.addr_short = temp_sensor.short_addr; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; @@ -34,7 +44,7 @@ static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, }; - read_req.attr_number = ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENTH(attributes); read_req.attr_field = attributes; esp_zb_zcl_read_attr_cmd_req(&read_req); @@ -50,7 +60,7 @@ static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { } } -static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { +void ZigbeeThermostat::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Found temperature sensor"); /* Store the information of the remote device */ @@ -74,7 +84,7 @@ static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpo /* populate the dst information of the binding */ bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; esp_zb_get_long_address(bind_req->dst_address_u.addr_long); - bind_req->dst_endp = HA_THERMOSTAT_ENDPOINT; + bind_req->dst_endp = _endpoint; log_i("Request temperature sensor to bind us"); esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); @@ -85,7 +95,7 @@ static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpo /* populate the src information of the binding */ esp_zb_get_long_address(bind_req->src_address); - bind_req->src_endp = HA_THERMOSTAT_ENDPOINT; + bind_req->src_endp = _endpoint; bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; /* populate the dst information of the binding */ @@ -98,11 +108,11 @@ static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpo } } -void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { +void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *param) { uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; param->num_in_clusters = 1; param->num_out_clusters = 0; param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, user_cb, (void *)&temp_sensor); + esp_zb_zdo_match_cluster(param, find_cb, (void *)&temp_sensor); } \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_thermostat.h b/libraries/Zigbee/src/ep/ep_thermostat.h index 3ca06cad604..03295c7ee8b 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.h +++ b/libraries/Zigbee/src/ep/ep_thermostat.h @@ -5,10 +5,30 @@ #include "Zigbee_ep.h" #include "ha/esp_zigbee_ha_standard.h" +//define the thermostat configuration to avoid narrowing conversion issue in zigbee-sdk +#define ZB_DEFAULT_THERMOSTAT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .thermostat_cfg = \ + { \ + .local_temperature = (int16_t)ESP_ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_DEFAULT_VALUE, \ + .occupied_cooling_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE, \ + .occupied_heating_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE, \ + .control_sequence_of_operation = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_DEFAULT_VALUE, \ + .system_mode = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE, \ + }, \ + } class ZigbeeThermostat : public Zigbee_EP { public: - ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)); - //ZigbeeThermostat(uint8_t endpoint, void (*cb)(const esp_zb_zcl_set_attr_value_message_t *message)) : ZigbeeTempSensor(endpoint, cb, NULL) {} + ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat(); void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); From 3078306475f10c9f6fae769ad43e0bbabda12e32 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:48:22 +0200 Subject: [PATCH 04/34] Dev update: implement on/off light and switch methods Implemented basic function calls of switch commands to on/off light: lightToggle, lightOn, lightOff, ... Implemented virtual methods for on/off light that have to be override in user code: setOnOff, sceneControl, setOnOffTime, setOffWaitTime APIs can be changed, still early development. --- .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 6 +- .../Zigbee_Light_Switch.ino | 22 +++-- libraries/Zigbee/src/Zigbee_ep.h | 3 +- libraries/Zigbee/src/ep/ep_on_off_light.cpp | 52 +++++++----- libraries/Zigbee/src/ep/ep_on_off_light.h | 7 +- libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 81 +++++++++++++++++++ libraries/Zigbee/src/ep/ep_on_off_switch.h | 24 +++++- 7 files changed, 157 insertions(+), 38 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino index 5c0d8470321..1082a6693f1 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino @@ -1,4 +1,4 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -22,6 +22,8 @@ * 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 @@ -45,7 +47,7 @@ public: MyZigbeeLight(uint8_t endpoint) : ZigbeeLight(endpoint) {} // Override the set_on_off function - void set_on_off(bool value) override { + void setOnOff(bool value) override { log_v("Overwritten method, set on/off: %d", value); neopixelWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light } diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino index aeb95a0799f..48829cb9fa8 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino @@ -1,9 +1,9 @@ -// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// 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 @@ -16,13 +16,15 @@ * @brief This example demonstrates simple Zigbee light switch. * * The example demonstrates how to use ESP Zigbee stack to control a light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). * Button switch and Zigbee runs in separate tasks. * * 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 @@ -68,16 +70,14 @@ typedef enum { static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; +/* Zigbee switch */ +ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); + /********************* Zigbee functions **************************/ static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* implemented light switch toggle functionality */ - esp_zb_zcl_on_off_cmd_t cmd_req; - cmd_req.zcl_basic_cmd.src_endpoint = SWITCH_ENDPOINT_NUMBER; - 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; - log_i("Send 'on_off toggle' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); + // Send toggle command to the light + zbSwitch.lightToggle(); } } @@ -98,8 +98,6 @@ static void switch_gpios_intr_enabled(bool enabled) { } } -ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); - /********************* Arduino functions **************************/ void setup() { diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index 93d361ef09f..854d635a782 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -14,7 +14,8 @@ class Zigbee_EP { Zigbee_EP(uint8_t endpoint = 10); ~Zigbee_EP(); - virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) = 0; + // Find endpoint may be implemented by EPs + virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; static uint8_t _endpoint; esp_zb_ha_standard_devices_t _device_id; //type of device diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index e9f3fb6a7be..a4cead0cca2 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -14,35 +14,51 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { }; } -void ZigbeeLight::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - //NOTE: Light is looking for switch? - return; -} - //set attribude method -> methon overriden in child class void ZigbeeLight::attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) { //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - bool light_state = 0; if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; - set_on_off(light_state); + setOnOff(*(bool *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + sceneControl(*(bool *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + setOnOffTime(*(uint16_t *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + setOffWaitTime(*(uint16_t *)message->attribute.data.value); + } + // else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + // //TODO: more info needed, not implemented for now + // } + else { + log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } } - // if (message->attr_id == ESP_ZB_ON_OFF_LIGHT_ATTR_ON_OFF) { - // //call method to set on/off - // set_on_off(message->attribute.data[0]); - // } - // else if (message->attr_id == ESP_ZB_ON_OFF_LIGHT_ATTR_LEVEL) { - // //call method to set level - // } else { - //unknown attribute + log_w("Recieved message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); } } //default method to set on/off -void ZigbeeLight::set_on_off(bool value) { +void ZigbeeLight::setOnOff(bool value) { //set on/off log_v("Function not overwritten, set on/off: %d", value); -} \ No newline at end of file +} + +void ZigbeeLight::sceneControl(bool value) { + //set scene control + log_v("Function not overwritten, set scene control: %d", value); +} + +void ZigbeeLight::setOnOffTime(uint16_t value) { + //set on/off time + log_v("Function not overwritten, set on/off time: %d", value); +} + +void ZigbeeLight::setOffWaitTime(uint16_t value) { + //set off wait time + log_v("Function not overwritten, set off wait time: %d", value); +} diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.h b/libraries/Zigbee/src/ep/ep_on_off_light.h index 4d52ba05f72..8df9c5a06e3 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.h +++ b/libraries/Zigbee/src/ep/ep_on_off_light.h @@ -11,11 +11,12 @@ class ZigbeeLight : public Zigbee_EP { ~ZigbeeLight(); // methods to be implemented by the user by overwritting them - virtual void set_on_off(bool value); + virtual void setOnOff(bool value); + virtual void sceneControl(bool value); + virtual void setOnOffTime(uint16_t value); + virtual void setOffWaitTime(uint16_t value); private: - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; }; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index e025d56dd7a..18bf1b509b2 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -69,3 +69,84 @@ void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { esp_zb_zdo_match_cluster(&on_off_req, find_cb, NULL); } + +// Call to control the light +void ZigbeeSwitch::lightToggle() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light toggle' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light on' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light off' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.effect_variant = effect_variant; + log_i("Sending 'light off with effect' command"); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOnWithSceneRecall() { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_i("Sending 'light on with scene recall' command"); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} +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; + 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 + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_i("Sending 'light on with time off' command"); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h index b1fff42d0ce..70bcebc0fd0 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -1,4 +1,4 @@ -/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ +/* Class of Zigbee On/Off Switch endpoint inherited from common EP class */ #pragma once @@ -10,10 +10,30 @@ class ZigbeeSwitch : public Zigbee_EP { ZigbeeSwitch(uint8_t endpoint); ~ZigbeeSwitch(); + // methods to control the on/off light + void lightToggle(); + void lightOn(); + void lightOff(); + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); + + private: void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); static uint8_t get_endpoint() { return _endpoint; } -}; \ No newline at end of file +}; + +//NOTE: +/* ON/OFF switch commands for light control */ +// typedef enum { +// ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID = 0x00, /*!< "Turn off" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_ID = 0x01, /*!< "Turn on" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID = 0x02, /*!< "Toggle state" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID = 0x40, /*!< "Off with effect" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID = 0x41, /*!< "On with recall global scene" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID = 0x42, /*!< "On with timed off" command. */ +// } esp_zb_zcl_on_off_cmd_id_t; From 14b99db7583cb8b82031e4cbe3a3d8c884c221a0 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:49:58 +0200 Subject: [PATCH 05/34] Dev update: Factory reset, names, multiple EPs Implemented Factory reset of Zigbee device, in order to connect to new network without reflashing/erasing flash Implemented optional setting for Manufacturer and Model names Added option to allow endpoint to have multiple endpoint connected -> switch - 2 lights (tested) Minor sketches update --- .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 24 ++- .../Zigbee_Light_Switch.ino | 32 +++- libraries/Zigbee/src/Zigbee_core.cpp | 134 +++++++---------- libraries/Zigbee/src/Zigbee_core.h | 2 + libraries/Zigbee/src/Zigbee_ep.cpp | 82 ++++++++++ libraries/Zigbee/src/Zigbee_ep.h | 19 +++ libraries/Zigbee/src/Zigbee_handlers.cpp | 52 ++++--- libraries/Zigbee/src/ep/ep_on_off_light.cpp | 4 +- libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 142 ++++++++++++++++-- libraries/Zigbee/src/ep/ep_on_off_switch.h | 22 +++ .../Zigbee/src/ep/ep_temperature_sensor.cpp | 1 + 11 files changed, 396 insertions(+), 118 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino index 1082a6693f1..f7eb0a73b7b 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino @@ -39,6 +39,7 @@ #include "ha/esp_zigbee_ha_standard.h" #define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // C6/H2 Boot button #define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ class MyZigbeeLight : public ZigbeeLight { @@ -48,7 +49,6 @@ public: // Override the set_on_off function void setOnOff(bool value) override { - log_v("Overwritten method, set on/off: %d", value); neopixelWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light } }; @@ -60,6 +60,12 @@ void setup() { // Init RMT and leave light OFF neopixelWrite(LED_PIN, 0, 0, 0); + // Init button for factory reset + pinMode(BUTTON_PIN, INPUT); + + //Optional: set Zigbee device name and model + zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + //Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); @@ -70,5 +76,19 @@ void setup() { } void loop() { - //empty, zigbee running in task + // Cheking button for factory reset + if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(BUTTON_PIN) == LOW) { + delay(50); + if((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Zigbee.factoryReset(); + } + } + } + delay(100); } \ No newline at end of file diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino index 48829cb9fa8..c4d052e3813 100644 --- a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino @@ -71,7 +71,23 @@ typedef enum { static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; /* Zigbee switch */ -ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); +class MyZigbeeSwitch : public ZigbeeSwitch { +public: + // Constructor that passes parameters to the base class constructor + MyZigbeeSwitch(uint8_t endpoint) : ZigbeeSwitch(endpoint) {} + + // Override the set_on_off function + void readManufacturer(char* manufacturer) override { + //Do what you want with the manufacturer string + Serial.printf("Manufacturer: %s\n", manufacturer); + } + void readModel(char* model) override { + //Do what you want with the model string + Serial.printf("Model: %s\n", model); + } +}; + +MyZigbeeSwitch zbSwitch = MyZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); /********************* Zigbee functions **************************/ static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { @@ -103,6 +119,12 @@ void setup() { Serial.begin(115200); + //Optional: set Zigbee device name and model + zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); + + //Optional to allow multiple light to bind to the switch + zbSwitch.allowMultipleBinding(true); + //Add endpoint to Zigbee Core log_d("Adding ZigbeeSwitch endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbSwitch); @@ -110,6 +132,7 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); + // Init button switch for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { pinMode(button_func_pair[i].pin, INPUT_PULLUP); @@ -169,4 +192,11 @@ void loop() { } vTaskDelay(10 / portTICK_PERIOD_MS); } + + // print the bound lights every 10 seconds + static uint32_t last_print = 0; + if (millis() - last_print > 10000) { + last_print = millis(); + zbSwitch.printBoundLights(); + } } diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 714a1e1c41b..5a3a08d507f 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -3,6 +3,7 @@ #include "Zigbee_handlers.cpp" #include "Arduino.h" + Zigbee_Core::Zigbee_Core() { _radio_config = ZIGBEE_DEFAULT_RADIO_CONFIG(); _host_config = ZIGBEE_DEFAULT_HOST_CONFIG(); @@ -254,9 +255,9 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { //TODO: Save the device short address and endpoint to the list ???????? - // for each endpoint in the list call the find_endpoint function if not bounded + // for each endpoint in the list call the find_endpoint function if not bounded or allowed to bind multiple devices for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (!(*it)->_is_bound) { + if (!(*it)->_is_bound || (*it)->_allow_multiple_binding) { (*it)->find_endpoint(&cmd_req); } } @@ -277,87 +278,10 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } -// // Zigbee action handlers -// static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { -// esp_err_t ret = ESP_OK; -// /* TODO: -// Implement handlers for different Zigbee actions (callback_id's) -// */ -// // NOTE: Implement all Zigbee actions that can be handled by the Zigbee_Core class, or just call user defined callback function and let the user handle the action and read the message properly -// // NOTE: This may me harder for users, to know what callback_id's are available and what message type is received -// switch (callback_id) { -// case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; -// case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; -// case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; -// case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; -// case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; -// default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; -// } - -// //TODO: get destination endpoint from the message: -// uint8_t dst_endpoint = ((esp_zb_zcl_set_attr_value_message_t *)message)->info.dst_endpoint; - - - -// return ret; -// } - -// static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { -// if (!message) { -// log_e("Empty message"); -// } -// if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { -// log_e("Received message: error status(%d)", message->info.status); -// } - -// log_i( -// "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, -// message->attribute.data.size -// ); - -// // List through all Zigbee EPs and call the callback function, with the message -// for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { -// if (message->info.dst_endpoint == (*it)->_endpoint) { -// //TODO: implement argument passing to the callback function -// //if Zigbee_EP argument is set, pass it to the callback function -// // if ((*it)->_arg) { -// // (*it)->_cb(message, (*it)->_arg); -// // } -// // else { -// (*it)->_cb(message); //method zb_attribute_set_handler in the LIGHT EP -// // } -// } -// } -// return ESP_OK; -// } - -// static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { -// if (!message) { -// log_e("Empty message"); -// } -// if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { -// log_e("Received message: error status(%d)", message->status); -// } -// log_i( -// "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, -// message->dst_endpoint, message->cluster -// ); -// // List through all Zigbee EPs and call the callback function, with the message -// for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { -// if (message->info.dst_endpoint == (*it)->_endpoint) { -// //TODO: implement argument passing to the callback function -// //if Zigbee_EP argument is set, pass it to the callback function -// // if ((*it)->_arg) { -// // (*it)->_cb(message, (*it)->_arg); -// // } -// // else { -// (*it)->_cb(message); -// // } -// } -// } -// return ESP_OK; -// } - +void Zigbee_Core::factoryReset() { + log_v("Factory reseting Zigbee stack, device will reboot"); + esp_zb_factory_reset(); +} // TODO: Implement scanning network @@ -394,4 +318,48 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { // esp_host_zb_output(ESP_ZNSP_ZDO_BIND_SET, &zdo_data, sizeof(esp_zb_zdo_bind_req_t), &output, &outlen); // } +// Function to convert enum value to string +const char* Zigbee_Core::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { + switch (deviceId) { + case ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID: return "General On/Off switch"; + case ESP_ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID: return "Level Control Switch"; + case ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID: return "General On/Off output"; + case ESP_ZB_HA_LEVEL_CONTROLLABLE_OUTPUT_DEVICE_ID: return "Level Controllable Output"; + case ESP_ZB_HA_SCENE_SELECTOR_DEVICE_ID: return "Scene Selector"; + case ESP_ZB_HA_CONFIGURATION_TOOL_DEVICE_ID: return "Configuration Tool"; + case ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID: return "Remote Control"; + case ESP_ZB_HA_COMBINED_INTERFACE_DEVICE_ID: return "Combined Interface"; + case ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID: return "Range Extender"; + case ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID: return "Mains Power Outlet"; + case ESP_ZB_HA_DOOR_LOCK_DEVICE_ID: return "Door lock client"; + case ESP_ZB_HA_DOOR_LOCK_CONTROLLER_DEVICE_ID: return "Door lock controller"; + case ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID: return "Simple Sensor device"; + case ESP_ZB_HA_CONSUMPTION_AWARENESS_DEVICE_ID: return "Consumption Awareness Device"; + case ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID: return "Home Gateway"; + case ESP_ZB_HA_SMART_PLUG_DEVICE_ID: return "Smart plug"; + case ESP_ZB_HA_WHITE_GOODS_DEVICE_ID: return "White Goods"; + case ESP_ZB_HA_METER_INTERFACE_DEVICE_ID: return "Meter Interface"; + case ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID: return "On/Off Light Device"; + case ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID: return "Dimmable Light Device"; + case ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID: return "Color Dimmable Light Device"; + case ESP_ZB_HA_DIMMER_SWITCH_DEVICE_ID: return "Dimmer Switch Device"; + case ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID: return "Color Dimmer Switch Device"; + case ESP_ZB_HA_SHADE_DEVICE_ID: return "Shade"; + case ESP_ZB_HA_SHADE_CONTROLLER_DEVICE_ID: return "Shade controller"; + case ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID: return "Window Covering client"; + case ESP_ZB_HA_WINDOW_COVERING_CONTROLLER_DEVICE_ID: return "Window Covering controller"; + case ESP_ZB_HA_HEATING_COOLING_UNIT_DEVICE_ID: return "Heating/Cooling Unit device"; + case ESP_ZB_HA_THERMOSTAT_DEVICE_ID: return "Thermostat Device"; + case ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID: return "Temperature Sensor"; + case ESP_ZB_HA_IAS_CONTROL_INDICATING_EQUIPMENT_ID: return "IAS Control and Indicating Equipment"; + case ESP_ZB_HA_IAS_ANCILLARY_CONTROL_EQUIPMENT_ID: return "IAS Ancillary Control Equipment"; + case ESP_ZB_HA_IAS_ZONE_ID: return "IAS Zone"; + case ESP_ZB_HA_IAS_WARNING_DEVICE_ID: return "IAS Warning Device"; + case ESP_ZB_HA_TEST_DEVICE_ID: return "Custom HA device for test"; + case ESP_ZB_HA_CUSTOM_TUNNEL_DEVICE_ID: return "Custom Tunnel device"; + case ESP_ZB_HA_CUSTOM_ATTR_DEVICE_ID: return "Custom Attributes Device"; + default: return "Unknown device type"; + } +} + Zigbee_Core Zigbee = Zigbee_Core(); diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h index 365d46c9020..a25b512d3d2 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -108,6 +108,8 @@ class Zigbee_Core { void setPrimaryChannelMask(uint32_t mask); void setRebootOpenNetwork(uint8_t time); + + void factoryReset(); }; extern Zigbee_Core Zigbee; diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index df6f4bfa9f2..294b0201530 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -1,17 +1,99 @@ /* Common Class for Zigbee End Point */ #include "Zigbee_ep.h" +#include "esp_zigbee_cluster.h" uint8_t Zigbee_EP::_endpoint = 0; bool Zigbee_EP::_is_bound = false; +bool Zigbee_EP::_allow_multiple_binding = false; /* Zigbee End Device Class */ Zigbee_EP::Zigbee_EP(uint8_t endpoint) { _endpoint = endpoint; _ep_config.endpoint = 0; _cluster_list = nullptr; + _attribute_cluster = nullptr; } Zigbee_EP::~Zigbee_EP() { } + +void Zigbee_EP::setManufacturerAndModel(const char *name, const char *model) { + // Convert manufacturer to ZCL string + size_t length = strlen(name); + if (length > 32) { + log_e("Manufacturer name is too long"); + return; + } + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char* zb_name = new char[length + 2]; + // Store the length as the first element + zb_name[0] = static_cast(length); // Cast size_t to char + // Use memcpy to copy the characters to the result array + memcpy(zb_name + 1, name, length); + // Null-terminate the array + zb_name[length + 1] = '\0'; + + // Convert model to ZCL string + length = strlen(model); + if (length > 32) { + log_e("Model name is too long"); + delete[] zb_name; + return; + } + char* zb_model = new char[length + 2]; + zb_model[0] = static_cast(length); + memcpy(zb_model + 1, model, length); + zb_model[length + 1] = '\0'; + + esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); + esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); + +} + +void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { + /* Read peer Manufacture Name & Model Identifier */ + 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_BASIC; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, + ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + esp_zb_zcl_read_attr_cmd_req(&read_req); +} + +void Zigbee_EP::attribute_read_cmd(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { + /* Basic cluster attributes */ + if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Manufacturer is \"%s\"", string); + readManufacturer(string); + free(string); + } + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Model is \"%s\"", string); + readModel(string); + free(string); + } + } +} +//NOTE: +// esp_zb_cluster_add_attr function \ No newline at end of file diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index 854d635a782..ae901cff16e 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -7,6 +7,12 @@ /* Usefull defines */ #define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) +#define print_ieee_addr(addr) log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) + +typedef struct zbstring_s { + uint8_t len; + char data[]; +} ESP_ZB_PACKED_STRUCT zbstring_t; /* Zigbee End Device Class */ class Zigbee_EP { @@ -23,6 +29,9 @@ class Zigbee_EP { esp_zb_endpoint_config_t _ep_config; esp_zb_cluster_list_t *_cluster_list; + esp_zb_attribute_list_t *_attribute_cluster; + + esp_zb_identify_cluster_cfg_t *_identify_cluster; // Set ep config and cluster list void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { @@ -33,9 +42,19 @@ class Zigbee_EP { static bool _is_bound; static bool is_bound() { return _is_bound; } + static bool _allow_multiple_binding; + static void allowMultipleBinding(bool bind) { _allow_multiple_binding = bind; } + + // Manufacturer name and model implemented + void setManufacturerAndModel(const char *name, const char *model); + void readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr); + + virtual void readManufacturer(char* manufacturer) {}; + virtual void readModel(char* model) {}; //list of all handlers function calls, to be overide by EPs implementation virtual void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) {}; + virtual void attribute_read_cmd(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented friend class ZigbeeCore; diff --git a/libraries/Zigbee/src/Zigbee_handlers.cpp b/libraries/Zigbee/src/Zigbee_handlers.cpp index 59594038e8a..7c3a1b88abc 100644 --- a/libraries/Zigbee/src/Zigbee_handlers.cpp +++ b/libraries/Zigbee/src/Zigbee_handlers.cpp @@ -5,6 +5,7 @@ // forward declaration of all implemented handlers static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); +static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message); // Zigbee action handlers static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { @@ -17,7 +18,7 @@ static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, switch (callback_id) { case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; - // case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; // case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; @@ -41,14 +42,7 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag // List through all Zigbee EPs and call the callback function, with the message for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->info.dst_endpoint == (*it)->_endpoint) { - //TODO: implement argument passing to the callback function - //if Zigbee_EP argument is set, pass it to the callback function - // if ((*it)->_arg) { - // (*it)->_cb(message, (*it)->_arg); - // } - // else { - (*it)->attribute_set(message); //method zb_attribute_set_handler in the LIGHT EP - // } + (*it)->attribute_set(message); //method zb_attribute_set_handler in the EP } } return ESP_OK; @@ -68,14 +62,38 @@ 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::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->dst_endpoint == (*it)->_endpoint) { - //TODO: implement argument passing to the callback function - //if Zigbee_EP argument is set, pass it to the callback function - // if ((*it)->_arg) { - // (*it)->_cb(message, (*it)->_arg); - // } - // else { - //(*it)->_cb(message); //method zb_attribute_reporting_handler in the EP - // } + //TODO: implement attribute reporting handler + } + } + return ESP_OK; +} + +static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + log_i( + "Read attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, + message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster + ); + + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->_endpoint) { + esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; + while (variable) { + log_i( + "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)", variable->status, message->info.cluster, + variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 + ); + if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { + //esp_app_zb_attribute_handler(message->info.cluster, &variable->attribute); + (*it)->attribute_read_cmd(message->info.cluster, &variable->attribute); + } + variable = variable->next; + } } } return ESP_OK; diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index a4cead0cca2..69b75c51969 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -5,13 +5,15 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { _version = 0; esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); + _identify_cluster = &light_cfg.identify_cfg; + _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() _ep_config = { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, .app_device_version = _version }; + _attribute_cluster = esp_zb_basic_cluster_create(&light_cfg.basic_cfg); } //set attribude method -> methon overriden in child class diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index 18bf1b509b2..d1878c84635 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -1,16 +1,16 @@ #include "ep_on_off_switch.h" -typedef struct light_bulb_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} light_bulb_device_params_t; +// Initialize the static instance pointer +ZigbeeSwitch* ZigbeeSwitch::_instance = nullptr; ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; _version = 0; + _instance = this; // Set the static pointer to this instance + esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); + _identify_cluster = &switch_cfg.identify_cfg; _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); _ep_config = { @@ -19,18 +19,23 @@ ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, .app_device_version = _version }; + _attribute_cluster = esp_zb_basic_cluster_create(&switch_cfg.basic_cfg); } void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Bound successfully!"); - if (user_ctx) { - light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; - log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - free(light); + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + //Read manufacturer and model automatically after successful bind + _instance->readManufacturerAndModel(light->endpoint, light->short_addr); + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + //TODO: call user method to notify about the light and pass all the info ???? + _instance->_bound_lights.push_back(light); + //free(light); + } + _is_bound = true; } - _is_bound = true; - } } void ZigbeeSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { @@ -70,6 +75,29 @@ void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { esp_zb_zdo_match_cluster(&on_off_req, find_cb, NULL); } +void ZigbeeSwitch::printBoundLights() { + log_i("Bound lights:"); + // for (std::list::iterator it = _bound_lights.begin(); it != _bound_lights.end(); ++it) { + // log_i("Light on endpoint %d, short address: 0x%x", (*it)->endpoint, (*it)->short_addr); + // print_ieee_addr((*it)->ieee_addr); + // } + for(const auto& light : _bound_lights) { + log_i("Light on endpoint %d, short address: 0x%x", light->endpoint, light->short_addr); + print_ieee_addr(light->ieee_addr); + } +} +// TODO: add endpont + adress optional parameters +// typedef enum { +// ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT = 0x0, /*!< DstAddress and DstEndpoint not present, +// only for APSDE-DATA request and confirm */ +// ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT = 0x1, /*!< 16-bit group address for DstAddress; DstEndpoint not present */ +// ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT = 0x2, /*!< 16-bit address for DstAddress and DstEndpoint present */ +// ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT = 0x3, /*!< 64-bit extended address for DstAddress and DstEndpoint present */ +// ESP_ZB_APS_ADDR_MODE_64_PRESENT_ENDP_NOT_PRESENT = 0x4, /*!< 64-bit extended address for DstAddress, but DstEndpoint NOT present, +// only for APSDE indication */ +// } esp_zb_aps_address_mode_t; + + // Call to control the light void ZigbeeSwitch::lightToggle() { if (_is_bound) { @@ -84,6 +112,35 @@ void ZigbeeSwitch::lightToggle() { } } +void ZigbeeSwitch::lightToggle(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + void ZigbeeSwitch::lightOn() { if (_is_bound) { esp_zb_zcl_on_off_cmd_t cmd_req; @@ -97,6 +154,35 @@ void ZigbeeSwitch::lightOn() { } } +void ZigbeeSwitch::lightOn(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + void ZigbeeSwitch::lightOff() { if (_is_bound) { esp_zb_zcl_on_off_cmd_t cmd_req; @@ -110,6 +196,35 @@ void ZigbeeSwitch::lightOff() { } } +void ZigbeeSwitch::lightOff(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + 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; @@ -149,4 +264,3 @@ void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, log_e("Light not bound"); } } - diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h index 70bcebc0fd0..e382969efe4 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -5,15 +5,37 @@ #include "Zigbee_ep.h" #include "ha/esp_zigbee_ha_standard.h" +typedef struct light_bulb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} light_bulb_device_params_t; + class ZigbeeSwitch : public Zigbee_EP { public: ZigbeeSwitch(uint8_t endpoint); ~ZigbeeSwitch(); + // save instance of the class in order to use it in static functions + static ZigbeeSwitch* _instance; + + // list of bounded on/off lights + std::list _bound_lights; + void printBoundLights(); + // methods to control the on/off light void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); void lightOnWithSceneRecall(); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp index 552556dee26..d71ece9f1bc 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -12,6 +12,7 @@ ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = _version }; + _attribute_cluster = esp_zb_basic_cluster_create(&temp_sensor_cfg.basic_cfg); } void ZigbeeTempSensor::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { From 54488a4537bea1c4b7aaf248a5823d2cf1d454a0 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:52:29 +0200 Subject: [PATCH 06/34] Dev update: Device ID to string Implemented easy transfer from device it to Device type (0x0000 = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID -> "General On/Off switch". --- libraries/Zigbee/src/Zigbee_core.cpp | 2 +- libraries/Zigbee/src/Zigbee_core.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 5a3a08d507f..b3940a043c9 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -101,7 +101,7 @@ bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { //print the list of Zigbee EPs from ep_objects log_i("List of registered Zigbee EPs:"); for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { - log_i("Endpoint: %d, Device ID: 0x%04x", (*it)->_endpoint, (*it)->_device_id); //TODO: Idea device id -> device name + log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); } // Register Zigbee action handler diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h index a25b512d3d2..e0d320edc54 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -110,6 +110,8 @@ class Zigbee_Core { void setRebootOpenNetwork(uint8_t time); void factoryReset(); + + const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); }; extern Zigbee_Core Zigbee; From a83f695b4b147c66f3614235f8b99aed0fb37fd7 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:05:44 +0200 Subject: [PATCH 07/34] Implement cmd default response handler --- libraries/Zigbee/src/Zigbee_ep.cpp | 5 ++-- libraries/Zigbee/src/Zigbee_handlers.cpp | 29 +++++++++++++++++------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index 294b0201530..706c9e88cf1 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -47,10 +47,13 @@ void Zigbee_EP::setManufacturerAndModel(const char *name, const char *model) { memcpy(zb_model + 1, model, length); zb_model[length + 1] = '\0'; + // Get the basic cluster and update the manufacturer and model attributes esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); + //NOTE: + // esp_zb_cluster_add_attr function } void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { @@ -95,5 +98,3 @@ void Zigbee_EP::attribute_read_cmd(uint16_t cluster_id, const esp_zb_zcl_attribu } } } -//NOTE: -// esp_zb_cluster_add_attr function \ No newline at end of file diff --git a/libraries/Zigbee/src/Zigbee_handlers.cpp b/libraries/Zigbee/src/Zigbee_handlers.cpp index 7c3a1b88abc..61861842123 100644 --- a/libraries/Zigbee/src/Zigbee_handlers.cpp +++ b/libraries/Zigbee/src/Zigbee_handlers.cpp @@ -6,21 +6,20 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message); +static esp_err_t zb_cmd_default_resp_handler(esp_zb_zcl_cmd_default_resp_message_t *message); // Zigbee action handlers static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; /* TODO: - Implement handlers for different Zigbee actions (callback_id's) + Implement handlers for different Zigbee actions (callback_id's) here and call the respective EP's method */ - // NOTE: Implement all Zigbee actions that can be handled by the Zigbee_Core class, or just call user defined callback function and let the user handle the action and read the message properly - // NOTE: This may me harder for users, to know what callback_id's are available and what message type is received switch (callback_id) { case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; // case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; - case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: log_i("Received default response"); break; + case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break; default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; } return ret; @@ -34,7 +33,7 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag log_e("Received message: error status(%d)", message->info.status); } - log_i( + log_v( "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, message->attribute.data.size ); @@ -55,7 +54,7 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { log_e("Received message: error status(%d)", message->status); } - log_i( + log_v( "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, message->dst_endpoint, message->cluster ); @@ -75,7 +74,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { log_e("Received message: error status(%d)", message->info.status); } - log_i( + log_v( "Read attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster ); @@ -84,7 +83,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re if (message->info.dst_endpoint == (*it)->_endpoint) { esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; while (variable) { - log_i( + log_v( "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)", variable->status, message->info.cluster, variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 ); @@ -98,3 +97,17 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re } return ESP_OK; } + +static esp_err_t zb_cmd_default_resp_handler(esp_zb_zcl_cmd_default_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + log_v( + "Received default response: from address(0x%x), src_endpoint(%d) to dst_endpoint(%d), cluster(0x%x) with status 0x%x", message->info.src_address.u.short_addr, + message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster, message->status_code + ); + return ESP_OK; +} From 06b0700f1782c508182e81d9da8e48829f938302 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:30:10 +0200 Subject: [PATCH 08/34] Remove unused _identify_cluster --- libraries/Zigbee/src/Zigbee_ep.h | 2 -- libraries/Zigbee/src/ep/ep_on_off_light.cpp | 1 - libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 1 - 3 files changed, 4 deletions(-) diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index ae901cff16e..6f935bbbf07 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -31,8 +31,6 @@ class Zigbee_EP { esp_zb_cluster_list_t *_cluster_list; esp_zb_attribute_list_t *_attribute_cluster; - esp_zb_identify_cluster_cfg_t *_identify_cluster; - // Set ep config and cluster list void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { _ep_config = ep_config; diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index 69b75c51969..4cc6ccfbdfb 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -5,7 +5,6 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { _version = 0; esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - _identify_cluster = &light_cfg.identify_cfg; _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() _ep_config = { .endpoint = _endpoint, diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index d1878c84635..724ad256eea 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -10,7 +10,6 @@ ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { _instance = this; // Set the static pointer to this instance esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); - _identify_cluster = &switch_cfg.identify_cfg; _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); _ep_config = { From ec60ed4e50ef1e016e81a8bfdbecce3449a3ba75 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:52:19 +0200 Subject: [PATCH 09/34] Dev Update: Color DImmable light + switch implemented Implemeted color dimmable light and color dimmer switch HA devices + examples. Removed unnecessary stored attribute cluster Renamed on/off light and switch examples --- .../README.md | 0 .../Zigbee_Color_Dimmable_Light.ino | 127 ++++++ .../README.md | 0 .../Zigbee_Color_Dimmer_Switch.ino | 149 +++++++ .../examples/Zigbee_Light_Bulb/.skip.esp32 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32c3 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32c6 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32h2 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32s2 | 0 .../examples/Zigbee_Light_Bulb/.skip.esp32s3 | 0 .../examples/Zigbee_Light_Switch/.skip.esp32 | 0 .../Zigbee_Light_Switch/.skip.esp32c3 | 0 .../Zigbee_Light_Switch/.skip.esp32c6 | 0 .../Zigbee_Light_Switch/.skip.esp32h2 | 0 .../Zigbee_Light_Switch/.skip.esp32s2 | 0 .../Zigbee_Light_Switch/.skip.esp32s3 | 0 .../examples/Zigbee_On_Off_Light/README.md | 73 +++ .../Zigbee_On_Off_Light.ino} | 0 .../examples/Zigbee_On_Off_Switch/README.md | 73 +++ .../Zigbee_On_Off_Switch.ino} | 0 libraries/Zigbee/src/Zigbee_ep.cpp | 1 - libraries/Zigbee/src/Zigbee_ep.h | 17 +- .../Zigbee/src/ep/ep_color_dimmable_light.cpp | 151 +++++++ .../Zigbee/src/ep/ep_color_dimmable_light.h | 31 ++ .../Zigbee/src/ep/ep_color_dimmer_switch.cpp | 416 ++++++++++++++++++ .../Zigbee/src/ep/ep_color_dimmer_switch.h | 77 ++++ libraries/Zigbee/src/ep/ep_on_off_light.cpp | 1 - libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 1 - libraries/Zigbee/src/ep/ep_on_off_switch.h | 2 - .../Zigbee/src/ep/ep_temperature_sensor.cpp | 1 - 30 files changed, 1113 insertions(+), 7 deletions(-) rename libraries/Zigbee/examples/{Zigbee_Light_Bulb => Zigbee_Color_Dimmable_Light}/README.md (100%) create mode 100644 libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino rename libraries/Zigbee/examples/{Zigbee_Light_Switch => Zigbee_Color_Dimmer_Switch}/README.md (100%) create mode 100644 libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 delete mode 100644 libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 create mode 100644 libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md rename libraries/Zigbee/examples/{Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino => Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino} (100%) create mode 100644 libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md rename libraries/Zigbee/examples/{Zigbee_Light_Switch/Zigbee_Light_Switch.ino => Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino} (100%) create mode 100644 libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp create mode 100644 libraries/Zigbee/src/ep/ep_color_dimmable_light.h create mode 100644 libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp create mode 100644 libraries/Zigbee/src/ep/ep_color_dimmer_switch.h diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md similarity index 100% rename from libraries/Zigbee/examples/Zigbee_Light_Bulb/README.md rename to libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino new file mode 100644 index 00000000000..7cddbcd07e0 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -0,0 +1,127 @@ +// 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 light bulb. + * + * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * 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_core.h" +#include "ep/ep_color_dimmable_light.h" + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // C6/H2 Boot button +#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ + +class MyZigbeeColorLight : public ZigbeeColorDimmableLight { +public: + // Constructor that passes parameters to the base class constructor + MyZigbeeColorLight(uint8_t endpoint) : ZigbeeColorDimmableLight(endpoint) {} + + // Override the set_on_off function + void setOnOff(bool value) override { + if (value == false) { + neopixelWrite(LED_PIN, 0, 0, 0); // Turn off light + } else { + updateLight(); // Turn on light on last color and level + } + } + + // Override the set_level function + void setLevel(uint8_t level) override { + if (level == 0) { + neopixelWrite(LED_PIN, 0, 0, 0); // Turn off light and dont update ratio + return; + } + _ratio = (float)level / 255; + updateLight(); + } + + // Override the set_color function + void setColor(uint8_t red, uint8_t green, uint8_t blue) override { + _red = red; + _green = green; + _blue = blue; + updateLight(); + } + + void updateLight() { + neopixelWrite(LED_PIN, _red * _ratio, _green * _ratio, _blue * _ratio); // Update light + } +private: + // Add your custom attributes and methods here + float _ratio = 1.0; + uint8_t _red = 255; + uint8_t _green = 255; + uint8_t _blue = 255; + +}; + +MyZigbeeColorLight zbColorLight = MyZigbeeColorLight(ZIGBEE_LIGHT_ENDPOINT); + +/********************* Arduino functions **************************/ +void setup() { + // Init RMT and leave light OFF + neopixelWrite(LED_PIN, 0, 0, 0); + + // Init button for factory reset + pinMode(BUTTON_PIN, INPUT); + + //Optional: set Zigbee device name and model + zbColorLight.setManufacturerAndModel("Espressif", "ZBColorLightBulb"); + + //Add endpoint to Zigbee Core + log_d("Adding ZigbeeLight endpoint to Zigbee Core"); + Zigbee.addEndpoint(&zbColorLight); + + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE + log_d("Calling Zigbee.begin()"); + Zigbee.begin(); +} + +void loop() { + // Cheking button for factory reset + if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(BUTTON_PIN) == LOW) { + delay(50); + if((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Zigbee.factoryReset(); + } + } + } + delay(100); +} \ No newline at end of file diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md similarity index 100% rename from libraries/Zigbee/examples/Zigbee_Light_Switch/README.md rename to libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino new file mode 100644 index 00000000000..9244bae40e4 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -0,0 +1,149 @@ +// 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 light switch. + * + * The example demonstrates how to use ESP Zigbee stack to control a light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). + * Button switch and Zigbee runs in separate tasks. + * + * 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_core.h" +#include "ep/ep_color_dimmer_switch.h" + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define SWITCH_ENDPOINT_NUMBER 5 + +/* Switch configuration */ +#define GPIO_SWITCH GPIO_NUM_9 //Boot button for C6/H2 + +/* Zigbee switch */ +ZigbeeColorDimmerSwitch zbSwitch = ZigbeeColorDimmerSwitch(SWITCH_ENDPOINT_NUMBER); + +/********************* Arduino functions **************************/ +void setup() { + + Serial.begin(115200); + + // Init button switch + pinMode(GPIO_SWITCH, INPUT); + + //Optional: set Zigbee device name and model + zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); + + //Optional to allow multiple light to bind to the switch + zbSwitch.allowMultipleBinding(true); + + //Add endpoint to Zigbee Core + Zigbee.addEndpoint(&zbSwitch); + + //Open network for 180 seconds after boot + Zigbee.setRebootOpenNetwork(180); + + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode + Zigbee.begin(ZIGBEE_COORDINATOR); + + Serial.println("Waiting for Light to bound to the switch"); + //Wait for switch to bound to a light: + while(!zbSwitch.is_bound()) + { + Serial.printf("."); + delay(500); + } + Serial.println(); +} + +void loop() { + // Handle button switch in loop() + if (digitalRead(GPIO_SWITCH) == LOW) { // Push button pressed + + // Key debounce handling + while (digitalRead(GPIO_SWITCH) == LOW) { + delay(50); + } + // Toggle light + zbSwitch.lightToggle(); + } + // Handle serial input to controll color and level of the light + if (Serial.available()) { + String command = Serial.readString(); + + if (command == "on") { + zbSwitch.lightOn(); + } else if (command == "off") { + zbSwitch.lightOff(); + } else if (command == "toggle") { + zbSwitch.lightToggle(); + } else if (command == "red") { + zbSwitch.setLightColor(255, 0, 0); + } else if (command == "green") { + zbSwitch.setLightColor(0, 255, 0); + } else if (command == "blue") { + zbSwitch.setLightColor(0, 0, 255); + } else if (command == "white") { + zbSwitch.setLightColor(255, 255, 255); + } else if (command == "color") { + //wait for color value + Serial.println("Enter red value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int red = Serial.parseInt(); + Serial.println("Enter green value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int green = Serial.parseInt(); + Serial.println("Enter blue value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int blue = Serial.parseInt(); + zbSwitch.setLightColor(red, green, blue); + } else if (command == "level") { + //wait for level value + Serial.println("Enter level value (0-255):"); + while (!Serial.available()) { + delay(100); + } + int level = Serial.parseInt(); + zbSwitch.setLightLevel(level); + } else { + Serial.println("Unknown command"); + } + } + + // print the bound lights every 30 seconds + static uint32_t last_print = 0; + if (millis() - last_print > 30000) { + last_print = millis(); + zbSwitch.printBoundLights(); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c3 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32c6 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32h2 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s2 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 b/libraries/Zigbee/examples/Zigbee_Light_Bulb/.skip.esp32s3 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c3 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32c6 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32h2 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s2 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 b/libraries/Zigbee/examples/Zigbee_Light_Switch/.skip.esp32s3 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md new file mode 100644 index 00000000000..cccc97aec98 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md @@ -0,0 +1,73 @@ +# Arduino-ESP32 Zigbee Light Bulb Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. + +**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) + +### Configure the Project + +Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. +By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. + +#### 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. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` +* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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 + +The ESP Zigbee SDK provides more examples: +* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) +* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino similarity index 100% rename from libraries/Zigbee/examples/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino rename to libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md new file mode 100644 index 00000000000..81f9354a6a0 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md @@ -0,0 +1,73 @@ +# Arduino-ESP32 Zigbee Light Switch Example + +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. + +**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). +* A USB cable for power supply and programming. +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Light_switch example). + +### Configure the Project + +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, the LED_PIN is `GPIO_NUM_9`. + +#### 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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. + +## Troubleshooting + +If the End device flashed with the example `Zigbee_Light_Bulb` 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`. +* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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 + +The ESP Zigbee SDK provides more examples: +* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) +* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) + +* Official ESP32 Forum: [Link](https://esp32.com) +* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) +* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) +* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) +* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino similarity index 100% rename from libraries/Zigbee/examples/Zigbee_Light_Switch/Zigbee_Light_Switch.ino rename to libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index 706c9e88cf1..0acce54c4d0 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -12,7 +12,6 @@ Zigbee_EP::Zigbee_EP(uint8_t endpoint) { _endpoint = endpoint; _ep_config.endpoint = 0; _cluster_list = nullptr; - _attribute_cluster = nullptr; } Zigbee_EP::~Zigbee_EP() { diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index 6f935bbbf07..1a28f69b1e6 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -8,6 +8,22 @@ /* Usefull defines */ #define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) #define print_ieee_addr(addr) log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) +#define XYZ_to_RGB(X, Y, Z, r, g, b) \ +{ \ + r = (float)( 3.240479*(X) -1.537150*(Y) -0.498535*(Z)); \ + g = (float)(-0.969256*(X) +1.875992*(Y) +0.041556*(Z)); \ + b = (float)( 0.055648*(X) -0.204043*(Y) +1.057311*(Z)); \ + if(r>1){r=1;} \ + if(g>1){g=1;} \ + if(b>1){b=1;} \ +} + +#define RGB_to_XYZ(r, g, b, X, Y, Z) \ +{ \ + X = (float)(0.412453*(r) + 0.357580*(g) + 0.180423*(b)); \ + Y = (float)(0.212671*(r) + 0.715160*(g) + 0.072169*(b)); \ + Z = (float)(0.019334*(r) + 0.119193*(g) + 0.950227*(b)); \ +} typedef struct zbstring_s { uint8_t len; @@ -29,7 +45,6 @@ class Zigbee_EP { esp_zb_endpoint_config_t _ep_config; esp_zb_cluster_list_t *_cluster_list; - esp_zb_attribute_list_t *_attribute_cluster; // Set ep config and cluster list void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { diff --git a/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp b/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp new file mode 100644 index 00000000000..a411e082113 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp @@ -0,0 +1,151 @@ +#include "ep_color_dimmable_light.h" + +ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : Zigbee_EP(endpoint) { + _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; + _version = 0; + + esp_zb_color_dimmable_light_cfg_t light_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg); + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, + .app_device_version = _version + }; +} + +uint8_t ZigbeeColorDimmableLight::getCurrentLevel(){ + return (*(uint8_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID)->data_p); +} + +uint16_t ZigbeeColorDimmableLight::getCurrentColorX(){ + return (*(uint16_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID)->data_p); +} + +uint16_t ZigbeeColorDimmableLight::getCurrentColorY(){ + return (*(uint16_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID)->data_p); +} + +void ZigbeeColorDimmableLight::calculateRGB( uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue){ + float r, g, b, color_x, color_y; + color_x = (float)x / 65535; + color_y = (float)y / 65535; + + float color_X = color_x / color_y; + float color_Z = (1 - color_x - color_y) / color_y; + + XYZ_to_RGB(color_X, 1, color_Z, r, g, b); + + red = (uint8_t)(r * (float)255); + green = (uint8_t)(g * (float)255); + blue = (uint8_t)(b * (float)255); +} + +//set attribude method -> methon overriden in child class +void ZigbeeColorDimmableLight::attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) { + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + setOnOff(*(bool *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + sceneControl(*(bool *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + setOnOffTime(*(uint16_t *)message->attribute.data.value); + } + else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + setOffWaitTime(*(uint16_t *)message->attribute.data.value); + } + // else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + // //TODO: more info needed, not implemented for now + // } + else { + log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + } + } + else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + setLevel(*(uint8_t *)message->attribute.data.value); + } + else { + log_w("Recieved message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h + } + } + else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + log_v("Light color x changes to 0x%x", *(uint16_t *)message->attribute.data.value); + uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value); + uint16_t light_color_y = getCurrentColorY(); + //calculate RGB from XY and call setColor() + uint8_t red, green, blue; + calculateRGB(light_color_x, light_color_y, red, green, blue); + setColor(red, green, blue); + + } + else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + log_v("Light color x changes to 0x%x", *(uint16_t *)message->attribute.data.value); + uint16_t light_color_x = getCurrentColorX(); + uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value); + //calculate RGB from XY and call setColor() + uint8_t red, green, blue; + calculateRGB(light_color_x, light_color_y, red, green, blue); + setColor(red, green, blue); + } + else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + setColorSaturation(*(uint8_t *)message->attribute.data.value); + } + else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + setColorHue(*(uint8_t *)message->attribute.data.value); + } + else { + log_w("Recieved message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); + //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_color_control.h + } + } + else { + log_w("Recieved message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); + } +} + +//default method to set on/off +void ZigbeeColorDimmableLight::setOnOff(bool value) { + //set on/off + log_v("Function not overwritten, set on/off: %d", value); +} + +void ZigbeeColorDimmableLight::sceneControl(bool value) { + //set scene control + log_v("Function not overwritten, set scene control: %d", value); +} + +void ZigbeeColorDimmableLight::setOnOffTime(uint16_t value) { + //set on/off time + log_v("Function not overwritten, set on/off time: %d", value); +} + +void ZigbeeColorDimmableLight::setOffWaitTime(uint16_t value) { + //set off wait time + log_v("Function not overwritten, set off wait time: %d", value); +} + +void ZigbeeColorDimmableLight::setLevel(uint8_t value) { + //set level + log_v("Function not overwritten, set level: %d", value); +} + +void ZigbeeColorDimmableLight::setColor(uint8_t r, uint8_t g, uint8_t b) { + //set color + log_v("Function not overwritten, set color: r: %d, g: %d, b: %d", r, g, b); +} + +void ZigbeeColorDimmableLight::setColorSaturation(uint8_t value) { + //set color saturation + log_v("Function not overwritten, set color saturation: %d", value); +} + +void ZigbeeColorDimmableLight::setColorHue(uint8_t value) { + //set color hue + log_v("Function not overwritten, set color hue: %d", value); +} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_color_dimmable_light.h b/libraries/Zigbee/src/ep/ep_color_dimmable_light.h new file mode 100644 index 00000000000..b1f960fa429 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_color_dimmable_light.h @@ -0,0 +1,31 @@ +/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +class ZigbeeColorDimmableLight : public Zigbee_EP { + public: + ZigbeeColorDimmableLight(uint8_t endpoint); + ~ZigbeeColorDimmableLight(); + + uint8_t getCurrentLevel(); + uint16_t getCurrentColorX(); + uint16_t getCurrentColorY(); + void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); + + // methods to be implemented by the user by overwritting them + virtual void setOnOff(bool value); + virtual void sceneControl(bool value); + virtual void setOnOffTime(uint16_t value); + virtual void setOffWaitTime(uint16_t value); + virtual void setLevel(uint8_t value); + virtual void setColor(uint8_t red, uint8_t green, uint8_t blue); + virtual void setColorSaturation(uint8_t value); + virtual void setColorHue(uint8_t value); + + private: + void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; + +}; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp new file mode 100644 index 00000000000..cc6b05b3ccd --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp @@ -0,0 +1,416 @@ +#include "ep_color_dimmer_switch.h" + +// Initialize the static instance pointer +ZigbeeColorDimmerSwitch* ZigbeeColorDimmerSwitch::_instance = nullptr; + +ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { + _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; + _version = 0; + + _instance = this; // Set the static pointer to this instance + + esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); + _cluster_list = esp_zb_color_dimmable_switch_clusters_create(&switch_cfg); + + _ep_config = { + .endpoint = _endpoint, + .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .app_device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID, + .app_device_version = _version + }; +} + +void ZigbeeColorDimmerSwitch::calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y) { + // Convert RGB to XYZ + float r = (float)red / 255.0f; + float g = (float)green / 255.0f; + float b = (float)blue / 255.0f; + + float X, Y, Z; + RGB_to_XYZ(r, g, b, X, Y, Z); + + // Convert XYZ to xy chromaticity coordinates + float color_x = X / (X + Y + Z); + float color_y = Y / (X + Y + Z); + + // Convert normalized xy to 16-bit values + x = (uint16_t)(color_x * 65535.0f); + y = (uint16_t)(color_y * 65535.0f); +} + +void ZigbeeColorDimmerSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + //Read manufacturer and model automatically after successful bind + _instance->readManufacturerAndModel(light->endpoint, light->short_addr); + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + //TODO: call user method to notify about the light and pass all the info ???? + _instance->_bound_lights.push_back(light); + } + _is_bound = true; + } +} + +void ZigbeeColorDimmerSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = _endpoint; //_dev_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_v("Try to bind on/off control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + log_v("Try to bind level control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + log_v("Try to bind color control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); + } else { + log_v("No color dimmable light endpoint found"); + } +} + +// find on_off light endpoint +void ZigbeeColorDimmerSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, + ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL}; + esp_zb_zdo_match_desc_req_param_t color_dimmable_light_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 3, + .num_out_clusters = 3, + .cluster_list = cluster_list, + }; + //esp_zb_zdo_find_color_dimmable_light(&cmd_req, user_find_cb, NULL); + esp_zb_zdo_match_cluster(&color_dimmable_light_req, find_cb, NULL); +} + +void ZigbeeColorDimmerSwitch::printBoundLights() { + log_i("Bound lights:"); + for(const auto& light : _bound_lights) { + log_i("Light on endpoint %d, short address: 0x%x", light->endpoint, light->short_addr); + print_ieee_addr(light->ieee_addr); + } +} + +// Methods to control the light +void ZigbeeColorDimmerSwitch::lightToggle() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light toggle' command"); + //esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + //esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light on' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff() { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.effect_variant = effect_variant; + log_i("Sending 'light off with effect' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_i("Sending 'light on with scene recall' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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 + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_i("Sending 'light on with time off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + 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; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) { + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + 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; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue) { + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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 = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr) { + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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; + cmd_req.color_x = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr) { + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.color_x = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h new file mode 100644 index 00000000000..bab457aa2c8 --- /dev/null +++ b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h @@ -0,0 +1,77 @@ +/* Class of Zigbee On/Off Switch endpoint inherited from common EP class */ + +#pragma once + +#include "Zigbee_ep.h" +#include "ha/esp_zigbee_ha_standard.h" + +typedef struct light_bulb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} light_bulb_device_params_t; + +class ZigbeeColorDimmerSwitch : public Zigbee_EP { + public: + ZigbeeColorDimmerSwitch(uint8_t endpoint); + ~ZigbeeColorDimmerSwitch(); + + // save instance of the class in order to use it in static functions + static ZigbeeColorDimmerSwitch* _instance; + + // list of bounded lights + std::list _bound_lights; + void printBoundLights(); + + void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); + + // methods to control the color dimmable light + void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); + + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); + + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); + + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); + + void setLightLevel(uint8_t level); + void setLightLevel(uint8_t level, uint16_t group_addr); + void setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr); + + void setLightColor(uint8_t red, uint8_t green, uint8_t blue); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); + + void setLightColorSaturation(uint8_t value); + void setLightColorSaturation(uint8_t value, uint16_t group_addr); + void setLightColorSaturation(uint8_t value, uint8_t endpoint, uint16_t short_addr); + + void setLightColorHue(uint8_t value); + void setLightColorHue(uint8_t value, uint16_t group_addr); + void setLightColorHue(uint8_t value, uint8_t endpoint, uint16_t short_addr); + + private: + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + +}; + +//NOTE: +/* ON/OFF switch commands for light control */ +// typedef enum { +// ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID = 0x00, /*!< "Turn off" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_ID = 0x01, /*!< "Turn on" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID = 0x02, /*!< "Toggle state" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID = 0x40, /*!< "Off with effect" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID = 0x41, /*!< "On with recall global scene" command. */ +// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID = 0x42, /*!< "On with timed off" command. */ +// } esp_zb_zcl_on_off_cmd_id_t; diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index 4cc6ccfbdfb..a6c5787c1d0 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -12,7 +12,6 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, .app_device_version = _version }; - _attribute_cluster = esp_zb_basic_cluster_create(&light_cfg.basic_cfg); } //set attribude method -> methon overriden in child class diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index 724ad256eea..b943f4de596 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -18,7 +18,6 @@ ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, .app_device_version = _version }; - _attribute_cluster = esp_zb_basic_cluster_create(&switch_cfg.basic_cfg); } void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h index e382969efe4..ac3e8ba59b6 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -45,8 +45,6 @@ class ZigbeeSwitch : public Zigbee_EP { static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - static uint8_t get_endpoint() { return _endpoint; } - }; //NOTE: diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp index d71ece9f1bc..552556dee26 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -12,7 +12,6 @@ ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = _version }; - _attribute_cluster = esp_zb_basic_cluster_create(&temp_sensor_cfg.basic_cfg); } void ZigbeeTempSensor::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { From ef1cc8950e1e10906b886de1d8feded6f42063a3 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:32:23 +0200 Subject: [PATCH 10/34] Implement Network Scanning Implemented Zigbee network scanning (async) to mostly match WiFi scan APIs. Added Zigbee_Scan_Networks example --- .../Zigbee_Scan_Networks.ino | 109 ++++++++++++++++++ .../examples/Zigbee_simple/Zigbee_simple.ino | 93 --------------- libraries/Zigbee/src/Zigbee_core.cpp | 94 ++++++++++----- libraries/Zigbee/src/Zigbee_core.h | 18 +++ 4 files changed, 195 insertions(+), 119 deletions(-) create mode 100644 libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino delete mode 100644 libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino new file mode 100644 index 00000000000..d64f9eef812 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -0,0 +1,109 @@ +// 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 Network Scanning. + * + * The example demonstrates how to use ESP Zigbee stack to scan for Zigbee networks. + * + * Any Zigbee mode can be selected in Tools->Zigbee mode + * with proper Zigbee partition scheme 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/) + */ + +#if !defined(ZIGBEE_MODE_ED) && !defined(ZIGBEE_MODE_ZCZR) +#error "Zigbee device mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee_core.h" + +#ifdef ZIGBEE_MODE_ZCZR +zigbee_role_t role = ZIGBEE_ROUTER; // or can be ZIGBEE_COORDINATOR, but it wont scan itself +#else +zigbee_role_t role = ZIGBEE_END_DEVICE; +#endif + +void printScannedNetworks(uint16_t networksFound) { + if (networksFound == 0) { + Serial.println("No networks found"); + } else { + zigbee_scan_result_t *scan_result = Zigbee.getScanResult(); + Serial.println("\nScan done"); + Serial.print(networksFound); + Serial.println(" networks found:"); + Serial.println("Nr | PAN ID | CH | Permit Joining | Router Capacity | End Device Capacity | Extended PAN ID"); + for (int i = 0; i < networksFound; ++i) { + // Print all available info for each network found + Serial.printf("%2d", i + 1); + Serial.print(" | "); + Serial.printf("0x%04hx", scan_result[i].short_pan_id); + Serial.print(" | "); + Serial.printf("%2ld", scan_result[i].logic_channel); + Serial.print(" | "); + Serial.printf("%-14.14s", scan_result[i].permit_joining ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf("%-15.15s", scan_result[i].router_capacity ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf("%-19.19s", scan_result[i].end_device_capacity ? "Yes" : "No"); + Serial.print(" | "); + Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", scan_result[i].extended_pan_id[7], scan_result[i].extended_pan_id[6], + scan_result[i].extended_pan_id[5], scan_result[i].extended_pan_id[4], + scan_result[i].extended_pan_id[3], scan_result[i].extended_pan_id[2], + scan_result[i].extended_pan_id[1], scan_result[i].extended_pan_id[0]); + Serial.println(); + delay(10); + } + Serial.println(""); + // Delete the scan result to free memory for code below. + Zigbee.scanDelete(); + } +} + +void setup() { + Serial.begin(115200); + + // Initialize Zigbee stack without any EPs just for scanning + Zigbee.begin(role); + + // Waint until Zigbee stack is ready + while (!Zigbee.isStarted()) { + delay(100); + } + + Serial.println("Setup done"); + // Start Zigbee Network Scan with default parameters (all channels, scan time 5) + Zigbee.scanNetworks(); +} + +void loop() { + // check Zigbee Network Scan process + int16_t ZigbeeScanStatus = Zigbee.scanComplete(); + if (ZigbeeScanStatus < 0) { // it is busy scanning or got an error + if (ZigbeeScanStatus == ZB_SCAN_FAILED) { + Serial.println("WiFi Scan has failed. Starting again."); + Zigbee.scanNetworks(); + } + // other option is status ZB_SCAN_RUNNING - just wait. + } else { // Found Zero or more Wireless Networks + printScannedNetworks(ZigbeeScanStatus); + Zigbee.scanNetworks(); // start over... + } + + // Loop can do something else... + delay(500); + Serial.println("Loop running..."); +} diff --git a/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino b/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino deleted file mode 100644 index adc2a942878..00000000000 --- a/libraries/Zigbee/examples/Zigbee_simple/Zigbee_simple.ino +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2023 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 light bulb. - * - * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. - * - * 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. - */ - -#ifndef ZIGBEE_MODE_ED -#error "Zigbee end device mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define LED_PIN RGB_BUILTIN - -/* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/* Handle the light attribute */ -// User callback for Zigbee actions to handle turning on/off the light called by Zigbee stack in zb_attribute_handler() - -static esp_err_t zigbee_callback(const esp_zb_zcl_set_attr_value_message_t *message) { - esp_err_t ret = ESP_OK; - bool light_state = 0; - - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - - log_i( - "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, - message->attribute.data.size - ); - if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; - log_i("Light sets to %s", light_state ? "On" : "Off"); - neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light - } - } - } - return ret; -} - -ZigbeeEP ZigbeeLight(10,zigbee_callback); - -/********************* Arduino functions **************************/ -void setup() { - // Init RMT and leave light OFF - neopixelWrite(LED_PIN, 0, 0, 0); - - //Setup endpoint - ZigbeeLight.addCluster(ESP_ZB_ZCL_CLUSTER_ID_ON_OFF); - ZigbeeLight.addCluster(ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL); - ZigbeeLight.begin(); //??? - - // When all EPs are registered, start Zigbee stack - Zigbee.begin(); -} - -void loop() { - //empty, zigbee running in task -} diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index b3940a043c9..39ff41e816c 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -10,6 +10,8 @@ Zigbee_Core::Zigbee_Core() { _zb_ep_list = esp_zb_ep_list_create(); _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; _open_network = 0; + _scan_status = ZB_SCAN_FAILED; + _started = false; } Zigbee_Core::~Zigbee_Core() {} @@ -91,19 +93,22 @@ bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { esp_zb_init(zb_cfg); // Register all Zigbee EPs in list - log_d("Register all Zigbee EPs in list"); - err = esp_zb_device_register(_zb_ep_list); - if (err != ESP_OK) { - log_e("Failed to register Zigbee EPs"); - return false; - } - - //print the list of Zigbee EPs from ep_objects - log_i("List of registered Zigbee EPs:"); - for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { - log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); + if(ep_objects.empty()) { + log_w("No Zigbee EPs to register"); + } else { + log_d("Register all Zigbee EPs in list"); + err = esp_zb_device_register(_zb_ep_list); + if (err != ESP_OK) { + log_e("Failed to register Zigbee EPs"); + return false; + } + + //print the list of Zigbee EPs from ep_objects + log_i("List of registered Zigbee EPs:"); + for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { + log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); + } } - // Register Zigbee action handler esp_zb_core_action_handler_register(zb_action_handler); err = esp_zb_set_primary_network_channel_set(_primary_channel_mask); @@ -159,7 +164,6 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { //coordinator variables esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - log_d("Zigbee role: %d", Zigbee._role); //main switch switch (sig_type) { case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common @@ -183,8 +187,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } else { log_i("Device rebooted"); - - // Implement opening network for joining after reboot if set + Zigbee._started = true; if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { log_i("Openning network for joining for %d seconds", Zigbee._open_network); esp_zb_bdb_open_network(Zigbee._open_network); @@ -213,6 +216,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device + Zigbee._started = true; if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { log_i("Network steering started"); @@ -283,18 +287,56 @@ void Zigbee_Core::factoryReset() { esp_zb_factory_reset(); } +bool Zigbee_Core::isStarted() { + return _started; +} + +void Zigbee_Core::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor){ + log_v("Zigbee network scan complete"); + if(zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_v("Found %d networks", count); + //print Zigbee networks + for (int i = 0; i < count; i++) { + log_v("Network %d: PAN ID: 0x%04hx, Permit Joining: %s, Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, Channel: %d, Router Capacity: %s, End Device Capacity: %s", + i, nwk_descriptor[i].short_pan_id, nwk_descriptor[i].permit_joining ? "Yes" : "No", nwk_descriptor[i].extended_pan_id[7], nwk_descriptor[i].extended_pan_id[6], nwk_descriptor[i].extended_pan_id[5], nwk_descriptor[i].extended_pan_id[4], nwk_descriptor[i].extended_pan_id[3], nwk_descriptor[i].extended_pan_id[2], nwk_descriptor[i].extended_pan_id[1], nwk_descriptor[i].extended_pan_id[0], nwk_descriptor[i].logic_channel, nwk_descriptor[i].router_capacity ? "Yes" : "No", nwk_descriptor[i].end_device_capacity ? "Yes" : "No"); + } + //save scan result and update scan status + //copy network descriptor to _scan_result to keep the data after the callback + Zigbee._scan_result = (esp_zb_network_descriptor_t *)malloc(count * sizeof(esp_zb_network_descriptor_t)); + memcpy(Zigbee._scan_result, nwk_descriptor, count * sizeof(esp_zb_network_descriptor_t)); + Zigbee._scan_status = count; + } else { + log_e("Failed to scan Zigbee network (status: 0x%x)", zdo_status); + Zigbee._scan_status = ZB_SCAN_FAILED; + Zigbee._scan_result = nullptr; + } +} + +void Zigbee_Core::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { + if(!_started) { + log_e("Zigbee stack is not started, cannot scan networks"); + return; + } + log_v("Scanning Zigbee networks"); + esp_zb_zdo_active_scan_request(channel_mask, scan_duration, scanCompleteCallback); + _scan_status = ZB_SCAN_RUNNING; +} + +int16_t Zigbee_Core::scanComplete(){ + return _scan_status; +} + +zigbee_scan_result_t* Zigbee_Core::getScanResult() { + return _scan_result; +} -// TODO: Implement scanning network -// /** -// * @brief Active scan available network. -// * -// * Network discovery service for scanning available network -// * -// * @param[in] channel_mask Valid channel mask is from 0x00000800 (only channel 11) to 0x07FFF800 (all channels from 11 to 26) -// * @param[in] scan_duration Time to spend scanning each channel -// * @param[in] user_cb A user callback to get the active scan result please refer to esp_zb_zdo_scan_complete_callback_t -// */ -// void esp_zb_zdo_active_scan_request(uint32_t channel_mask, uint8_t scan_duration, esp_zb_zdo_scan_complete_callback_t user_cb); +void Zigbee_Core::scanDelete() { + if (_scan_result != nullptr) { + free(_scan_result); + _scan_result = nullptr; + } + _scan_status = ZB_SCAN_FAILED; +} // NOTE: Binding functions to not forget // void esp_zb_zdo_device_bind_req(esp_zb_zdo_bind_req_param_t *cmd_req, esp_zb_zdo_bind_callback_t user_cb, void *user_ctx) diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/Zigbee_core.h index e0d320edc54..4384e2877a7 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/Zigbee_core.h @@ -18,6 +18,8 @@ typedef struct { void *arg; } zigbee_cb_t; +typedef esp_zb_network_descriptor_t zigbee_scan_result_t; + // enum of Zigbee Roles typedef enum { ZIGBEE_COORDINATOR = 0, @@ -31,6 +33,9 @@ typedef enum { #define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ #define MAX_CHILDREN 10 +#define ZB_SCAN_RUNNING (-1) +#define ZB_SCAN_FAILED (-2) + #define ZIGBEE_DEFAULT_ED_CONFIG() \ { \ .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ @@ -81,20 +86,26 @@ class Zigbee_Core { esp_zb_radio_config_t _radio_config; esp_zb_host_config_t _host_config; uint32_t _primary_channel_mask; + int16_t _scan_status; + bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); public: esp_zb_ep_list_t *_zb_ep_list; zigbee_role_t _role; + bool _started; uint8_t _open_network; std::list ep_objects; + zigbee_scan_result_t *_scan_result; Zigbee_Core(); ~Zigbee_Core(); bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); + bool isStarted(); // bool end(); void addEndpoint(Zigbee_EP *ep); @@ -109,6 +120,13 @@ class Zigbee_Core { void setPrimaryChannelMask(uint32_t mask); void setRebootOpenNetwork(uint8_t time); + //scan_duration Time spent scanning each channel, in units of ((1 << scan_duration) + 1) * a beacon time. (15.36 microseconds) + void scanNetworks(uint32_t channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK, uint8_t scan_duration = 5); + // Zigbee scan complete status check, -2: failed or not started, -1: running, 0: no networks found, >0: number of networks found + int16_t scanComplete(); + zigbee_scan_result_t* getScanResult(); + void scanDelete(); + void factoryReset(); const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); From 97920df65586183834c3ba638cc0d416cb8d8ed3 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:54:13 +0200 Subject: [PATCH 11/34] Dev Update: Thermostat and Temperature sensor EP Implemeted thermostat and temperature sensor HA devices + examples. Implemented configure report handler. Updated READMEs and description of examples. Minor code updates --- .../Zigbee_Color_Dimmable_Light/README.md | 21 +-- .../Zigbee_Color_Dimmable_Light.ino | 10 +- .../Zigbee_Color_Dimmable_Light/ci.json | 16 +++ .../Zigbee_Color_Dimmer_Switch/README.md | 22 +-- .../Zigbee_Color_Dimmer_Switch.ino | 33 ++--- .../Zigbee_Color_Dimmer_Switch/ci.json | 16 +++ .../examples/Zigbee_On_Off_Light/README.md | 20 +-- .../Zigbee_On_Off_Light.ino | 9 +- .../examples/Zigbee_On_Off_Light/ci.json | 16 +++ .../examples/Zigbee_On_Off_Switch/README.md | 18 +-- .../Zigbee_On_Off_Switch.ino | 7 +- .../examples/Zigbee_On_Off_Switch/ci.json | 16 +++ .../examples/Zigbee_Scan_Networks/README.md | 69 ++++++++++ .../examples/Zigbee_Scan_Networks/ci.json | 16 +++ .../Zigbee_Temperature_Sensor/README.md | 75 ++++++++++ .../Zigbee_Temperature_Sensor.ino | 104 ++++++++++++++ .../Zigbee_Temperature_Sensor/ci.json | 16 +++ .../examples/Zigbee_Thermostat/README.md | 76 ++++++++++ .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 130 ++++++++++++++++++ .../Zigbee/examples/Zigbee_Thermostat/ci.json | 16 +++ libraries/Zigbee/src/Zigbee_ep.cpp | 38 +++-- libraries/Zigbee/src/Zigbee_ep.h | 58 +------- libraries/Zigbee/src/Zigbee_handlers.cpp | 38 +++-- .../Zigbee/src/ep/ep_temperature_sensor.cpp | 72 +++++++++- .../Zigbee/src/ep/ep_temperature_sensor.h | 13 +- libraries/Zigbee/src/ep/ep_thermostat.cpp | 105 +++++++++++++- libraries/Zigbee/src/ep/ep_thermostat.h | 23 +++- 27 files changed, 864 insertions(+), 189 deletions(-) create mode 100644 libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json create mode 100644 libraries/Zigbee/examples/Zigbee_Thermostat/README.md create mode 100644 libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino create mode 100644 libraries/Zigbee/examples/Zigbee_Thermostat/ci.json diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md index cccc97aec98..e14ad0b7000 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md @@ -1,8 +1,6 @@ -# Arduino-ESP32 Zigbee Light Bulb Example +# Arduino-ESP32 Zigbee Color Dimmable Light Example -This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) color dimmable light. # Supported Targets @@ -13,14 +11,13 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Color_Dimmer_Switch example) * A USB cable for power supply and programming -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_Color_Dimmable_Light example ### Configure the Project Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. -By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. #### Using Arduino IDE @@ -60,14 +57,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index 7cddbcd07e0..989491c73d6 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -13,9 +13,10 @@ // limitations under the License. /** - * @brief This example demonstrates simple Zigbee light bulb. + * @brief This example demonstrates Zigbee Color Dimmable light bulb. * - * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The example demonstrates how to use Zigbee library to create an end device with + * color dimmable light end point. * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. * * Proper Zigbee mode must be selected in Tools->Zigbee mode @@ -33,11 +34,6 @@ #include "Zigbee_core.h" #include "ep/ep_color_dimmable_light.h" -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - #define LED_PIN RGB_BUILTIN #define BUTTON_PIN 9 // C6/H2 Boot button #define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json new file mode 100644 index 00000000000..83af1395ee6 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md index 81f9354a6a0..75d8ea6fe1f 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md @@ -1,8 +1,6 @@ -# Arduino-ESP32 Zigbee Light Switch Example +# Arduino-ESP32 Zigbee Color Dimmer Switch Example -This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) color dimmer light switch. # Supported Targets @@ -13,13 +11,13 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Color_Dimmable_Light example). * A USB cable for power supply and programming. -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Light_switch example). +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator and upload the Zigbee_Color_Dimmable_Light example. ### Configure the Project -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, the LED_PIN is `GPIO_NUM_9`. +Set the Button Switch GPIO by changing the `GPIO_SWITCH` definition. By default, it's the pin `9` (BOOT button on ESP32-C6 and ESP32-H2). #### Using Arduino IDE @@ -60,14 +58,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index 9244bae40e4..7695de03726 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -13,11 +13,15 @@ // limitations under the License. /** - * @brief This example demonstrates simple Zigbee light switch. + * @brief This example demonstrates Zigbee color dimmer switch. * - * The example demonstrates how to use ESP Zigbee stack to control a light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). - * Button switch and Zigbee runs in separate tasks. + * The example demonstrates how to use Zigbee library to control a RGB light bulb. + * The RGB light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). + * To turn on/off the light, push the button on the switch. + * To change the color or level of the light, send serial commands to the switch. + * + * By setting the switch to allow multiple binding, so it can bind to multiple lights. + * Also every 30 seconds, all bound lights are printed to the serial console. * * Proper Zigbee mode must be selected in Tools->Zigbee mode * and also the correct partition scheme must be selected in Tools->Partition Scheme. @@ -34,15 +38,9 @@ #include "Zigbee_core.h" #include "ep/ep_color_dimmer_switch.h" -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define SWITCH_ENDPOINT_NUMBER 5 - /* Switch configuration */ -#define GPIO_SWITCH GPIO_NUM_9 //Boot button for C6/H2 +#define SWITCH_PIN 9 //Boot button for C6/H2 +#define SWITCH_ENDPOINT_NUMBER 5 /* Zigbee switch */ ZigbeeColorDimmerSwitch zbSwitch = ZigbeeColorDimmerSwitch(SWITCH_ENDPOINT_NUMBER); @@ -52,8 +50,8 @@ void setup() { Serial.begin(115200); - // Init button switch - pinMode(GPIO_SWITCH, INPUT); + //Init button switch + pinMode(SWITCH_PIN, INPUT); //Optional: set Zigbee device name and model zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); @@ -67,7 +65,7 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode + //When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode Zigbee.begin(ZIGBEE_COORDINATOR); Serial.println("Waiting for Light to bound to the switch"); @@ -82,10 +80,9 @@ void setup() { void loop() { // Handle button switch in loop() - if (digitalRead(GPIO_SWITCH) == LOW) { // Push button pressed - + if (digitalRead(SWITCH_PIN) == LOW) { // Push button pressed // Key debounce handling - while (digitalRead(GPIO_SWITCH) == LOW) { + while (digitalRead(SWITCH_PIN) == LOW) { delay(50); } // Toggle light diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json new file mode 100644 index 00000000000..203fce34b38 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md index cccc97aec98..1b9d9725aa0 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md @@ -1,8 +1,6 @@ -# Arduino-ESP32 Zigbee Light Bulb Example +# Arduino-ESP32 Zigbee On/Off Light Example -This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light. # Supported Targets @@ -13,9 +11,9 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_On_Off_switch example) * A USB cable for power supply and programming -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the Zigbee_On_Off_Light example ### Configure the Project @@ -60,14 +58,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index f7eb0a73b7b..43ca3346220 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -15,7 +15,7 @@ /** * @brief This example demonstrates simple Zigbee light bulb. * - * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The example demonstrates how to use Zigbee library to create a end device light bulb. * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. * * Proper Zigbee mode must be selected in Tools->Zigbee mode @@ -33,14 +33,9 @@ #include "Zigbee_core.h" #include "ep/ep_on_off_light.h" -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - #define LED_PIN RGB_BUILTIN #define BUTTON_PIN 9 // C6/H2 Boot button -#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ class MyZigbeeLight : public ZigbeeLight { public: diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json new file mode 100644 index 00000000000..83af1395ee6 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md index 81f9354a6a0..d665a396f2f 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md @@ -1,9 +1,7 @@ -# Arduino-ESP32 Zigbee Light Switch Example +# Arduino-ESP32 Zigbee On/Off Light Switch Example This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** - # Supported Targets Currently, this example supports the following targets. @@ -13,9 +11,9 @@ Currently, this example supports the following targets. ## Hardware Required -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_On_Off_Light example). * A USB cable for power supply and programming. -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Light_switch example). +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator and upload the Zigbee_On_Off_Switch example. ### Configure the Project @@ -60,14 +58,8 @@ Before creating a new issue, be sure to try Troubleshooting and check if the sam ## Resources -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - * Official ESP32 Forum: [Link](https://esp32.com) * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) +* 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_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index c4d052e3813..59121eeaedf 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -15,7 +15,7 @@ /** * @brief This example demonstrates simple Zigbee light switch. * - * The example demonstrates how to use ESP Zigbee stack to control a light bulb. + * The example demonstrates how to use Zigbee library to control a light bulb. * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). * Button switch and Zigbee runs in separate tasks. * @@ -34,11 +34,6 @@ #include "Zigbee_core.h" #include "ep/ep_on_off_switch.h" -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - #define SWITCH_ENDPOINT_NUMBER 5 /* Switch configuration */ diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json new file mode 100644 index 00000000000..203fce34b38 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md new file mode 100644 index 00000000000..dbdbb7ce554 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md @@ -0,0 +1,69 @@ +# Arduino-ESP32 Zigbee Networks Scan Example + +This example shows how to scan Zigbee Networks. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Example Output + +//TODO: + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with `Zigbee_Thermostat` example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with `Zigbee_Temperature_Sensor` example) + +### Configure the Project + +In this example, the internal temperature sensor task is reading the chip temperature. +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_9` (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. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` +* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json new file mode 100644 index 00000000000..83af1395ee6 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md new file mode 100644 index 00000000000..c52d7b710cc --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md @@ -0,0 +1,75 @@ +# Arduino-ESP32 Zigbee Temperature Sensor Example + +This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) temperature sensor. + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Temperature Sensor Functions + +Note: + * This board means the board (e.g. ESP32-H2 / C6) loaded with `Zigbee_Temperature_Sensor` example. + * The remote board means the board (e.g. ESP32-H2 / C6) loaded with `Zigbee_Thermostat` example. + +Functions: + * After this board first starts up, it would be configured locally to report the temperature on 1 degree change and no periodic reporting to the remote board. + * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured temperature to the remote board. + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with `Zigbee_Thermostat` example) +* A USB cable for power supply and programming +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device and upload the `Zigbee_Temperature_Sensor` example + +### Configure the Project + +In this example, the internal temperature sensor task is reading the chip temperature. +Set the Button GPIO by changing the `BUTTON_PIN` definition. By default, it's the pin `9` (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. + +## Troubleshooting + +If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` +* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino new file mode 100644 index 00000000000..8602af424e2 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -0,0 +1,104 @@ +// 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 sensor. + * + * The example demonstrates how to use Zigbee library to create a end device temperature sensor. + * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * 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 coordinator mode is not selected in Tools->Zigbee mode" +#endif + +#include "Zigbee_core.h" +#include "ep/ep_temperature_sensor.h" + +#define BUTTON_PIN 9 //Boot button for C6/H2 + +#define TEMP_SENSOR_ENDPOINT_NUMBER 10 +ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); + +/************************ Temp sensor *****************************/ +static void temp_sensor_value_update(void *arg) { + for (;;) { + // Read temperature sensor value + float tsens_value = temperatureRead(); + log_v("Temperature sensor value: %.2f°C", tsens_value); + // Update temperature value in Temperature sensor EP + zbTempSensor.setTemperature(tsens_value); + delay(1000); + } +} + +/********************* Arduino functions **************************/ +void setup() { + + Serial.begin(115200); + + // Init button switch + pinMode(BUTTON_PIN, INPUT); + + // 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 endpoint to Zigbee Core + Zigbee.addEndpoint(&zbTempSensor); + + // When all EPs are registered, start Zigbee in End Device mode + Zigbee.begin(); + + // Start Temperature sensor reading task + xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL); + + // Set reporting interval for temperature measurement in seconds, must be called after Zigbee.begin() + // min_interval and max_interval in seconds, delta (temp change in °C) + // if min = 1 and max = 0, reporting is sent only when temperature changes by delta + // if min = 0 and max = 10, reporting is sent every 10 secods or temperature changes by delta + // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of temperature change + zbTempSensor.setReporting(1, 0, 1); +} + +void loop() { + // Cheking button for factory reset + if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + // Key debounce handling + delay(100); + int startTime = millis(); + while (digitalRead(BUTTON_PIN) == LOW) { + delay(50); + if((millis() - startTime) > 3000) { + // If key pressed for more than 3secs, factory reset Zigbee and reboot + Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Zigbee.factoryReset(); + } + } + zbTempSensor.reportTemperature(); + } + delay(100); +} diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json new file mode 100644 index 00000000000..83af1395ee6 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" + ] + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/README.md b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md new file mode 100644 index 00000000000..d239aaefcca --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md @@ -0,0 +1,76 @@ +# Arduino-ESP32 Zigbee Thermostat Example + +This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) thermostat. + +**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_thermostat.** + +# Supported Targets + +Currently, this example supports the following targets. + +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +## Thermostat Functions + +Note: + * This board means the board (e.g. ESP32-H2) loaded with `Zigbee_Thermostat` example. + * The remote board means the board (e.g. ESP32-H2) loaded with `Zigbee_Temperature_Sensor` example. + +Functions: + * By clicking the button (BOOT) on this board, this board will read temperature value, temperature measurement range and temperature tolerance from the remote board. Also, this board will configure the remote board to report the measured temperature value every 10 seconds or every 2 degree changes. + +## Hardware Required + +* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Temperature_Sensor example). +* A USB cable for power supply and programming. +* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Thermostat example). + +### Configure the Project + +Set the Button GPIO by changing the `BUTTON_PIN` definition. By default, it's the pin `9` (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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. + +## Troubleshooting + +If the End device flashed with the example `Zigbee_Temperature_Sensor` 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`. +* In the `Zigbee_Temperature_Sensor` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. + +By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. +You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. + +***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_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino new file mode 100644 index 00000000000..da99829b2d1 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -0,0 +1,130 @@ +// 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_core.h" +#include "ep/ep_thermostat.h" + +#define BUTTON_PIN 9 // Boot button for C6/H2 +#define THERMOSTAT_ENDPOINT_NUMBER 5 + +class MyZigbeeThermostat : public ZigbeeThermostat { + public: + // Constructor that passes parameters to the base class constructor + MyZigbeeThermostat(uint8_t endpoint) : ZigbeeThermostat(endpoint) {} + + // Override virtual functions from ZigbeeThermostat to handle temperature sensor data + void temperatureRead(float temp) override { + if (temperature != temp) { + Serial.printf("Temperature sensor value changed to: %.2f°C\n", temp); + temperature = temp; + } + } + + void temperatureMin(float temp) override { + Serial.printf("Temperature sensor min value: %.2f°C\n", temp); + min_temperature = temp; + } + + void temperatureMax(float temp) override { + Serial.printf("Temperature sensor max value: %.2f°C\n", temp); + max_temperature = temp; + } + + void temperatureTolerance(float tolerance) override { + Serial.printf("Temperature sensor tolerance: %.2f°C\n", tolerance); + temp_tolerance = tolerance; + } + + float temperature; + float max_temperature; + float min_temperature; + float temp_tolerance; +}; + +MyZigbeeThermostat zbThermostat = MyZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); + +/********************* Arduino functions **************************/ +void setup() { + + Serial.begin(115200); + + // Init button switch + pinMode(BUTTON_PIN, INPUT); + + //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 + Zigbee.begin(ZIGBEE_COORDINATOR); + + Serial.println("Waiting for Light to bound to the switch"); + //Wait for switch to bound to a light: + while(!zbThermostat.is_bound()) + { + Serial.printf("."); + delay(500); + } + + // Get temperature sensor value to update min and max values + zbThermostat.getTemperature(); + + Serial.println(); +} + +void loop() { + // Handle button switch in loop() + if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed + + // Key debounce handling + while (digitalRead(BUTTON_PIN) == LOW) { + delay(50); + } + + // Set reporting interval for temperature sensor + zbThermostat.setTemperatureReporting(0, 10, 2); + } + + // 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)((zbThermostat.temperature - zbThermostat.min_temperature) / (zbThermostat.max_temperature - zbThermostat.min_temperature) * 100); + Serial.printf("Temperature: %.2f°C (%d '%')\n", zbThermostat.temperature, temp_percent); + } +} diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json new file mode 100644 index 00000000000..203fce34b38 --- /dev/null +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -0,0 +1,16 @@ +{ + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false + }, + "fqbn": { + "esp32c6": [ + "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ], + "esp32h2": [ + "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" + ] + } +} diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index 0acce54c4d0..3c55f9cc8b5 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -74,26 +74,24 @@ void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) esp_zb_zcl_read_attr_cmd_req(&read_req); } -void Zigbee_EP::attribute_read_cmd(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { +void Zigbee_EP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ - if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Manufacturer is \"%s\"", string); - readManufacturer(string); - free(string); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Model is \"%s\"", string); - readModel(string); - free(string); - } + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Manufacturer is \"%s\"", string); + readManufacturer(string); + free(string); + } + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Model is \"%s\"", string); + readModel(string); + free(string); } } diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index 1a28f69b1e6..3d8ec6df2ec 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -26,9 +26,10 @@ } typedef struct zbstring_s { - uint8_t len; - char data[]; -} ESP_ZB_PACKED_STRUCT zbstring_t; + uint8_t len; + char data[]; +} ESP_ZB_PACKED_STRUCT +zbstring_t; /* Zigbee End Device Class */ class Zigbee_EP { @@ -67,58 +68,11 @@ class Zigbee_EP { //list of all handlers function calls, to be overide by EPs implementation virtual void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) {}; - virtual void attribute_read_cmd(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented + virtual void attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {}; + virtual void readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented friend class ZigbeeCore; // List of Zigbee EP classes friend class ZigbeeLight; - - /* TODO: create all possible methods for each EP type, that can be overwritten by user to use them - - // NOTE: This is a list of all possible callbacks that can be used in Zigbee_EP class - // typedef enum esp_zb_core_action_callback_id_s { - // ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID = 0x0000, /*!< Set attribute value, refer to esp_zb_zcl_set_attr_value_message_t */ - // ESP_ZB_CORE_SCENES_STORE_SCENE_CB_ID = 0x0001, /*!< Store scene, refer to esp_zb_zcl_store_scene_message_t */ - // ESP_ZB_CORE_SCENES_RECALL_SCENE_CB_ID = 0x0002, /*!< Recall scene, refer to esp_zb_zcl_recall_scene_message_t */ - // ESP_ZB_CORE_IAS_ZONE_ENROLL_RESPONSE_VALUE_CB_ID = 0x0003, /*!< IAS Zone enroll response, refer to esp_zb_zcl_ias_zone_enroll_response_message_t */ - // ESP_ZB_CORE_OTA_UPGRADE_VALUE_CB_ID = 0x0004, /*!< Upgrade OTA, refer to esp_zb_zcl_ota_upgrade_value_message_t */ - // ESP_ZB_CORE_OTA_UPGRADE_SRV_STATUS_CB_ID = 0x0005, /*!< OTA Server status, refer to esp_zb_zcl_ota_upgrade_server_status_message_t */ - // ESP_ZB_CORE_OTA_UPGRADE_SRV_QUERY_IMAGE_CB_ID = 0x0006, /*!< OTA Server query image, refer to esp_zb_zcl_ota_upgrade_server_query_image_message_t */ - // ESP_ZB_CORE_THERMOSTAT_VALUE_CB_ID = 0x0007, /*!< Thermostat value, refer to esp_zb_zcl_thermostat_value_message_t */ - // ESP_ZB_CORE_METERING_GET_PROFILE_CB_ID = 0x0008, /*!< Metering get profile, refer to esp_zb_zcl_metering_get_profile_message_t */ - // ESP_ZB_CORE_METERING_GET_PROFILE_RESP_CB_ID = 0x0009, /*!< Metering get profile response, refer to esp_zb_zcl_metering_get_profile_resp_message_t */ - // ESP_ZB_CORE_METERING_REQ_FAST_POLL_MODE_CB_ID = 0x000a, /*!< Metering request fast poll mode, refer to esp_zb_zcl_metering_request_fast_poll_mode_message_t */ - // ESP_ZB_CORE_METERING_REQ_FAST_POLL_MODE_RESP_CB_ID = 0x000b, /*!< Metering request fast poll mode response, refer to esp_zb_zcl_metering_request_fast_poll_mode_resp_message_t */ - // ESP_ZB_CORE_METERING_GET_SNAPSHOT_CB_ID = 0x000c, /*!< Metering get snapshot, refer to esp_zb_zcl_metering_get_snapshot_message_t */ - // ESP_ZB_CORE_METERING_PUBLISH_SNAPSHOT_CB_ID = 0x000d, /*!< Metering publish snapshot, refer to esp_zb_zcl_metering_publish_snapshot_message_t */ - // ESP_ZB_CORE_METERING_GET_SAMPLED_DATA_CB_ID = 0x000e, /*!< Metering get sampled data, refer to esp_zb_zcl_metering_get_sampled_data_message_t */ - // ESP_ZB_CORE_METERING_GET_SAMPLED_DATA_RESP_CB_ID = 0x000f, /*!< Metering get sampled data response, refer to esp_zb_zcl_metering_get_sampled_data_resp_message_t */ - // ESP_ZB_CORE_DOOR_LOCK_LOCK_DOOR_CB_ID = 0x0010, /*!< Lock/unlock door request, refer to esp_zb_zcl_door_lock_lock_door_message_t */ - // ESP_ZB_CORE_DOOR_LOCK_LOCK_DOOR_RESP_CB_ID = 0x0011, /*!< Lock/unlock door response, refer to esp_zb_zcl_door_lock_lock_door_resp_message_t */ - // ESP_ZB_CORE_IDENTIFY_EFFECT_CB_ID = 0x0012, /*!< Identify triggers effect request, refer to esp_zb_zcl_identify_effect_message_t */ - // ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID = 0x1000, /*!< Read attribute response, refer to esp_zb_zcl_cmd_read_attr_resp_message_t */ - // ESP_ZB_CORE_CMD_WRITE_ATTR_RESP_CB_ID = 0x1001, /*!< Write attribute response, refer to esp_zb_zcl_cmd_write_attr_resp_message_t */ - // ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID = 0x1002, /*!< Configure reprot response, refer to esp_zb_zcl_cmd_config_report_resp_message_t */ - // ESP_ZB_CORE_CMD_READ_REPORT_CFG_RESP_CB_ID = 0x1003, /*!< Read report configuration response, refer to esp_zb_zcl_cmd_read_report_config_resp_message_t */ - // ESP_ZB_CORE_CMD_DISC_ATTR_RESP_CB_ID = 0x1004, /*!< Discover attributes response, refer to esp_zb_zcl_cmd_discover_attributes_resp_message_t */ - // ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID = 0x1005, /*!< Default response, refer to esp_zb_zcl_cmd_default_resp_message_t */ - // ESP_ZB_CORE_CMD_OPERATE_GROUP_RESP_CB_ID = 0x1010, /*!< Group add group response, refer to esp_zb_zcl_groups_operate_group_resp_message_t */ - // ESP_ZB_CORE_CMD_VIEW_GROUP_RESP_CB_ID = 0x1011, /*!< Group view response, refer to esp_zb_zcl_groups_view_group_resp_message_t */ - // ESP_ZB_CORE_CMD_GET_GROUP_MEMBERSHIP_RESP_CB_ID = 0x1012, /*!< Group get membership response, refer to esp_zb_zcl_groups_get_group_membership_resp_message_t */ - // ESP_ZB_CORE_CMD_OPERATE_SCENE_RESP_CB_ID = 0x1020, /*!< Scenes operate response, refer to esp_zb_zcl_scenes_operate_scene_resp_message_t */ - // ESP_ZB_CORE_CMD_VIEW_SCENE_RESP_CB_ID = 0x1021, /*!< Scenes view response, refer to esp_zb_zcl_scenes_view_scene_resp_message_t */ - // ESP_ZB_CORE_CMD_GET_SCENE_MEMBERSHIP_RESP_CB_ID = 0x1022, /*!< Scenes get membership response, refer to esp_zb_zcl_scenes_get_scene_membership_resp_message_t */ - // ESP_ZB_CORE_CMD_IAS_ZONE_ZONE_ENROLL_REQUEST_ID = 0x1030, /*!< IAS Zone enroll request, refer to esp_zb_zcl_ias_zone_enroll_request_message_t */ - // ESP_ZB_CORE_CMD_IAS_ZONE_ZONE_STATUS_CHANGE_NOT_ID = 0x1031, /*!< IAS Zone status change notification, refer to esp_zb_zcl_ias_zone_status_change_notification_message_t */ - // ESP_ZB_CORE_CMD_CUSTOM_CLUSTER_REQ_CB_ID = 0x1040, /*!< Custom Cluster request, refer to esp_zb_zcl_custom_cluster_command_message_t */ - // ESP_ZB_CORE_CMD_CUSTOM_CLUSTER_RESP_CB_ID = 0x1041, /*!< Custom Cluster response, refer to esp_zb_zcl_custom_cluster_command_message_t */ - // ESP_ZB_CORE_CMD_PRIVILEGE_COMMAND_REQ_CB_ID = 0x1050, /*!< Custom Cluster request, refer to esp_zb_zcl_privilege_command_message_t */ - // ESP_ZB_CORE_CMD_PRIVILEGE_COMMAND_RESP_CB_ID = 0x1051, /*!< Custom Cluster response, refer to esp_zb_zcl_privilege_command_message_t */ - // ESP_ZB_CORE_CMD_GREEN_POWER_RECV_CB_ID = 0x1F00, /*!< Green power cluster command receiving, refer to esp_zb_zcl_cmd_green_power_recv_message_t */ - // ESP_ZB_CORE_REPORT_ATTR_CB_ID = 0x2000, /*!< Attribute Report, refer to esp_zb_zcl_report_attr_message_t */ - // } esp_zb_core_action_callback_id_t; - - }; - diff --git a/libraries/Zigbee/src/Zigbee_handlers.cpp b/libraries/Zigbee/src/Zigbee_handlers.cpp index 61861842123..f46aed3afe9 100644 --- a/libraries/Zigbee/src/Zigbee_handlers.cpp +++ b/libraries/Zigbee/src/Zigbee_handlers.cpp @@ -6,19 +6,17 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message); -static esp_err_t zb_cmd_default_resp_handler(esp_zb_zcl_cmd_default_resp_message_t *message); +static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message); +static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message); // Zigbee action handlers static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; - /* TODO: - Implement handlers for different Zigbee actions (callback_id's) here and call the respective EP's method - */ switch (callback_id) { case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; - // case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break; default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; } @@ -61,7 +59,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::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->dst_endpoint == (*it)->_endpoint) { - //TODO: implement attribute reporting handler + (*it)->attribute_read(message->cluster, &message->attribute); //method attribute_read must be implemented in specific EP class } } return ESP_OK; @@ -88,8 +86,12 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 ); if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { - //esp_app_zb_attribute_handler(message->info.cluster, &variable->attribute); - (*it)->attribute_read_cmd(message->info.cluster, &variable->attribute); + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { + (*it)->readBasicCluster(message->info.cluster, &variable->attribute); //method readBasicCluster implemented in the common EP class + } + else { + (*it)->attribute_read(message->info.cluster, &variable->attribute); //method attribute_read must be implemented in specific EP class + } } variable = variable->next; } @@ -98,7 +100,25 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re return ESP_OK; } -static esp_err_t zb_cmd_default_resp_handler(esp_zb_zcl_cmd_default_resp_message_t *message) { +static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message) { + if (!message) { + log_e("Empty message"); + } + if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { + log_e("Received message: error status(%d)", message->info.status); + } + esp_zb_zcl_config_report_resp_variable_t *variable = message->variables; + while (variable) { + log_v( + "Configure report response: status(%d), cluster(0x%x), direction(0x%x), attribute(0x%x)", variable->status, message->info.cluster, variable->direction, + variable->attribute_id + ); + variable = variable->next; + } + return ESP_OK; +} + +static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message) { if (!message) { log_e("Empty message"); } diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp index 552556dee26..41ba9947f1a 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -14,7 +14,73 @@ ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { }; } -void ZigbeeTempSensor::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - //empty function, not used for this type of device - return; +static int16_t zb_temperature_to_s16(float temp) { + return (int16_t)(temp * 100); +} + +void ZigbeeTempSensor::setMinMaxValue(int16_t min, int16_t max) { + esp_zb_attribute_list_t *temp_measure_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&min); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&max); +} + +void ZigbeeTempSensor::setTolerance(float tolerance) { + // Convert tolerance to ZCL uint16_t + uint16_t zb_tolerance = (uint16_t)(tolerance * 100); + esp_zb_attribute_list_t *temp_measure_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); +} + +void ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { + esp_zb_zcl_reporting_info_t reporting_info = { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .ep = _endpoint, + .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, + .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, + .attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .u = + { + .send_info = + { + .min_interval = min_interval, + .max_interval = max_interval, + .delta = + { + .u16 = (uint16_t)(delta * 100), // Convert delta to ZCL uint16_t + }, + .def_min_interval = min_interval, + .def_max_interval = max_interval, + }, + }, + .dst = + { + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + }, + .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, + }; + esp_zb_zcl_update_reporting_info(&reporting_info); +} + +void ZigbeeTempSensor::setTemperature(float temperature) { + int16_t zb_temperature = zb_temperature_to_s16(temperature); + log_v("Updating temperature sensor value..."); + /* Update temperature sensor measured value */ + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false); + esp_zb_lock_release(); +} + +void ZigbeeTempSensor::reportTemperature() { + /* 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_TEMP_MEASUREMENT_VALUE_ID; + report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Temperature report sent"); } \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.h b/libraries/Zigbee/src/ep/ep_temperature_sensor.h index f05dde0875b..bf2172e59ab 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.h +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.h @@ -10,5 +10,16 @@ class ZigbeeTempSensor : public Zigbee_EP { ZigbeeTempSensor(uint8_t endpoint); ~ZigbeeTempSensor(); - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + // Set the temperature value in 0,01°C + void setTemperature(float value); + + // Set the min and max value for the temperature sensor in °C + void setMinMaxValue(int16_t min, int16_t max); + + // Set the tolerance value for the temperature sensor in 0,01°C + void setTolerance(float tolerance); + + // Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C) + void setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + void reportTemperature(); }; \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_thermostat.cpp b/libraries/Zigbee/src/ep/ep_thermostat.cpp index bd1960ff619..25b17042646 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.cpp +++ b/libraries/Zigbee/src/ep/ep_thermostat.cpp @@ -8,6 +8,10 @@ typedef struct temp_sensor_device_params_s { static temp_sensor_device_params_t temp_sensor; +static float zb_s16_to_temperature(int16_t value) { + return 1.0 * value / 100; +} + ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; _version = 0; @@ -15,7 +19,16 @@ ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); - _cluster_list = esp_zb_thermostat_clusters_create(&thermostat_cfg); + //use custom cluster creating to accept reportings from temperature sensor + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat_cfg.basic_cfg)); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(&(thermostat_cfg.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + esp_zb_cluster_list_add_thermostat_cluster(_cluster_list, esp_zb_thermostat_cluster_create(&(thermostat_cfg.thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + /* Add temperature measurement cluster for attribute reporting */ + esp_zb_cluster_list_add_temperature_meas_cluster(_cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + _ep_config = { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, @@ -52,10 +65,11 @@ void ZigbeeThermostat::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (bind_req->req_dst_addr == temp_sensor.short_addr) { log_i("The temperature sensor from address(0x%x) on endpoint(%d) successfully binds us", temp_sensor.short_addr, temp_sensor.endpoint); } + _is_bound = true; free(bind_req); } else { /* Bind failed, maybe retry the binding ? */ - + log_e("Binding failed!"); // esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); } } @@ -115,4 +129,89 @@ void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *param) { param->num_out_clusters = 0; param->cluster_list = cluster_list; esp_zb_zdo_match_cluster(param, find_cb, (void *)&temp_sensor); -} \ No newline at end of file +} + +void ZigbeeThermostat::attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { + 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; + temperatureRead(zb_s16_to_temperature(value)); + } + 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; + temperatureMin(min_value); + } + 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; + temperatureMax(max_value); + } + 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; + temperatureTolerance(1.0 * tolerance / 100); + } + } +} + +void ZigbeeThermostat::getTemperature(){ + /* 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_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, 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 temperature' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); +} + +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; + 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; + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .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"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); +} + +// default methods for thermostat +void ZigbeeThermostat::temperatureRead(float temp){ + log_v("Function not overwritten, measured temperature: %.2f °C", temp); +} + +void ZigbeeThermostat::temperatureMin(float temp){ + log_v("Function not overwritten, min temperature: %.2f °C", temp); +} + +void ZigbeeThermostat::temperatureMax(float temp){ + log_v("Function not overwritten, max temperature: %.2f °C", temp); +} + +void ZigbeeThermostat::temperatureTolerance(float tolerance){ + log_v("Function not overwritten, temperature tolerance: %.2f °C", tolerance); +} diff --git a/libraries/Zigbee/src/ep/ep_thermostat.h b/libraries/Zigbee/src/ep/ep_thermostat.h index 03295c7ee8b..7e1265f9b87 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.h +++ b/libraries/Zigbee/src/ep/ep_thermostat.h @@ -27,12 +27,23 @@ }, \ } class ZigbeeThermostat : public Zigbee_EP { - public: - ZigbeeThermostat(uint8_t endpoint); - ~ZigbeeThermostat(); + public: + ZigbeeThermostat(uint8_t endpoint); + ~ZigbeeThermostat(); - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + + virtual void temperatureRead(float temp); + virtual void temperatureMin(float temp); + virtual void temperatureMax(float temp); + virtual void temperatureTolerance(float tolerance); + + void getTemperature(); + void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); + + private: + void attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override; }; \ No newline at end of file From fa716f0e34a3a36ab5b47b563484c993ebc72459 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:09:51 +0200 Subject: [PATCH 12/34] fix(): Replace deprecated function --- libraries/Zigbee/src/Zigbee_core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 39ff41e816c..97e635d560c 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -71,7 +71,7 @@ void Zigbee_Core::addEndpoint(Zigbee_EP *ep) { static void esp_zb_task(void *pvParameters) { /* initialize Zigbee stack */ ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); + esp_zb_stack_main_loop(); } // Zigbee core init function From db01086a4cab79b17369ac23b2138dea9aeaae36 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:00:55 +0200 Subject: [PATCH 13/34] Remove ported IDF examples --- .../Zigbee/Zigbee_Light_Bulb/README.md | 73 --- .../Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino | 188 ------ .../examples/Zigbee/Zigbee_Light_Bulb/ci.json | 10 - .../Zigbee/Zigbee_Light_Switch/README.md | 73 --- .../Zigbee_Light_Switch.ino | 296 --------- .../Zigbee/Zigbee_Light_Switch/ci.json | 10 - .../Zigbee_Temperature_Sensor/README.md | 83 --- .../Zigbee_Temperature_Sensor.ino | 349 ----------- .../Zigbee/Zigbee_Temperature_Sensor/ci.json | 10 - .../Zigbee/Zigbee_Thermostat/README.md | 82 --- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 565 ------------------ .../examples/Zigbee/Zigbee_Thermostat/ci.json | 10 - 12 files changed, 1749 deletions(-) delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino delete mode 100644 libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md deleted file mode 100644 index 807b8a42ade..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Arduino-ESP32 Zigbee Light Bulb Example - -This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** - -# Supported Targets - -Currently, this example supports the following targets. - -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | - -## Hardware Required - -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) -* A USB cable for power supply and programming -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) - -### Configure the Project - -Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. -By default, the `rgbLedWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. - -#### 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. - -## Troubleshooting - -If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. - -By default, the coordinator network is open for 180 s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. - -***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 - -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - -* Official ESP32 Forum: [Link](https://esp32.com) -* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) -* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino deleted file mode 100644 index 25585abbbf2..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/Zigbee_Light_Bulb.ino +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2023 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 light bulb. - * - * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. - * - * 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. - */ - -#ifndef ZIGBEE_MODE_ED -#error "Zigbee end device mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define LED_PIN RGB_BUILTIN - -/* Default End Device config */ -#define ESP_ZB_ZED_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ - .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ - .nwk_cfg = { \ - .zed_cfg = \ - { \ - .ed_timeout = ED_AGING_TIMEOUT, \ - .keep_alive = ED_KEEP_ALIVE, \ - }, \ - }, \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/********************* Zigbee functions **************************/ -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Device rebooted"); - } - } else { - /* commissioning failed */ - log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - } else { - log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { - esp_err_t ret = ESP_OK; - switch (callback_id) { - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: - ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); - break; - default: - log_w("Receive Zigbee action(0x%x) callback", callback_id); - break; - } - return ret; -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); - esp_zb_device_register(esp_zb_on_off_light_ep); - esp_zb_core_action_handler_register(zb_action_handler); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - - //Erase NVRAM before creating connection to new Coordinator - esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are connecting to new Coordinator - - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/* Handle the light attribute */ - -static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { - esp_err_t ret = ESP_OK; - bool light_state = 0; - - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - - log_i( - "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, - message->attribute.data.size - ); - if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; - log_i("Light sets to %s", light_state ? "On" : "Off"); - rgbLedWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light - } - } - } - return ret; -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init RMT and leave light OFF - rgbLedWrite(LED_PIN, 0, 0, 0); - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - //empty, zigbee running in task -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Bulb/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md deleted file mode 100644 index efa7d45cb9c..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Arduino-ESP32 Zigbee Light Switch Example - -This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) on/off light switch. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_switch.** - -# Supported Targets - -Currently, this example supports the following targets. - -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | - -## Hardware Required - -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Light_bulb example). -* A USB cable for power supply and programming. -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Light_switch example). - -### Configure the Project - -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, the LED_PIN is `GPIO_NUM_9`. - -#### 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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. -* 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. - -## Troubleshooting - -If the End device flashed with the example `Zigbee_Light_Bulb` 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`. -* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. - -By default, the coordinator network is open for 180 s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. - -***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 - -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - -* Official ESP32 Forum: [Link](https://esp32.com) -* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) -* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino deleted file mode 100644 index 83ec1d7aa53..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/Zigbee_Light_Switch.ino +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2023 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 light switch. - * - * The example demonstrates how to use ESP Zigbee stack to control a light bulb. - * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. - * Button switch and Zigbee runs in separate tasks. - * - * 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. - */ - -#ifndef ZIGBEE_MODE_ZCZR -#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 -#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) - -typedef enum { - SWITCH_ON_CONTROL, - SWITCH_OFF_CONTROL, - SWITCH_ONOFF_TOGGLE_CONTROL, - SWITCH_LEVEL_UP_CONTROL, - SWITCH_LEVEL_DOWN_CONTROL, - SWITCH_LEVEL_CYCLE_CONTROL, - SWITCH_COLOR_CONTROL, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default Coordinator config */ -#define ESP_ZB_ZC_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = INSTALLCODE_POLICY_ENABLE, .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = MAX_CHILDREN, \ - }, \ - } \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -typedef struct light_bulb_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} light_bulb_device_params_t; - -/* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_ONOFF_SWITCH_ENDPOINT 1 /* esp light switch device endpoint */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/********************* Zigbee functions **************************/ -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* implemented light switch toggle functionality */ - esp_zb_zcl_on_off_cmd_t cmd_req; - cmd_req.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_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; - log_i("Send 'on_off toggle' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Bound successfully!"); - if (user_ctx) { - light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; - log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - free(light); - } - } -} - -static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Found light"); - esp_zb_zdo_bind_req_param_t bind_req; - light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); - light->endpoint = endpoint; - light->short_addr = addr; - esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); - esp_zb_get_long_address(bind_req.src_address); - bind_req.src_endp = HA_ONOFF_SWITCH_ENDPOINT; - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; - bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req.dst_endp = endpoint; - bind_req.req_dst_addr = esp_zb_get_short_address(); - log_i("Try to bind On/Off"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); - } -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); - } else { - log_i("Device rebooted"); - log_i("Opening network for joining for %d seconds", 180); - esp_zb_bdb_open_network(180); - } - } else { - log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_FORMATION: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - log_i("Network steering started"); - } - break; - case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: - dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); - log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); - esp_zb_zdo_match_desc_req_param_t cmd_req; - cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; - cmd_req.addr_of_interest = dev_annce_params->device_short_addr; - esp_zb_zdo_find_on_off_light(&cmd_req, user_find_cb, NULL); - break; - case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: - if (err_status == ESP_OK) { - if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { - log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); - } else { - log_w("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); - } - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); - esp_zb_ep_list_t *esp_zb_on_off_switch_ep = esp_zb_on_off_switch_ep_create(HA_ONOFF_SWITCH_ENDPOINT, &switch_cfg); - esp_zb_device_register(esp_zb_on_off_switch_ep); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Light_Switch/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md deleted file mode 100644 index f8177082a8a..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# Arduino-ESP32 Zigbee Temperature Sensor Example - -This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) temperature sensor. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_temperature_sensor.** - -# Supported Targets - -Currently, this example supports the following targets. - -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | - -## Temperature Sensor Functions - -Note: - * This board means the board (e.g. ESP32-H2) loaded with `Zigbee_Temperature_Sensor` example. - * The remote board means the board (e.g. ESP32-H2) loaded with `Zigbee_Thermostat` example. - -Functions: - * After this board first starts up, it would be configured locally to report the temperature on 1 degree change and no periodic reporting to the remote board. - * By clicking the switch button (BOOT) on this board, this board will immediately send a report of the current measured temperature to the remote board. - -## Hardware Required - -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with `Zigbee_Thermostat` example) -* A USB cable for power supply and programming -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with `Zigbee_Temperature_Sensor` example) - -### Configure the Project - -In this example, the internal temperature sensor task is reading the chip temperature. -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_9` (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. - -## Troubleshooting - -If the End device flashed with this example is not connecting to the coordinator, erase the flash before flashing it to the board. It is recommended to do this if you did changes to 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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. - -By default, the coordinator network is open for 180 s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. - -***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 - -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - -* Official ESP32 Forum: [Link](https://esp32.com) -* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) -* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino deleted file mode 100644 index a510c968051..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ /dev/null @@ -1,349 +0,0 @@ -// 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 temperature sensor. - * - * The example demonstrates how to use ESP Zigbee stack to create a end device temperature sensor. - * The temperature sensor is a Zigbee end device, which is controlled by a Zigbee coordinator. - * - * 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. - */ - -#ifndef ZIGBEE_MODE_ED -#error "Zigbee end device mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 -#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) - -typedef enum { - SWITCH_ON_CONTROL, - SWITCH_OFF_CONTROL, - SWITCH_ONOFF_TOGGLE_CONTROL, - SWITCH_LEVEL_UP_CONTROL, - SWITCH_LEVEL_DOWN_CONTROL, - SWITCH_LEVEL_CYCLE_CONTROL, - SWITCH_COLOR_CONTROL, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default End Device config */ -#define ESP_ZB_ZED_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ - .nwk_cfg = { \ - .zed_cfg = \ - { \ - .ed_timeout = ED_AGING_TIMEOUT, \ - .keep_alive = ED_KEEP_ALIVE, \ - }, \ - }, \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Zigbee configuration */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define HA_ESP_SENSOR_ENDPOINT 10 /* esp temperature sensor device endpoint, used for temperature measurement */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/* Temperature sensor configuration */ -#define ESP_TEMP_SENSOR_UPDATE_INTERVAL (1) /* Local sensor update interval (second) */ -#define ESP_TEMP_SENSOR_MIN_VALUE (10) /* Local sensor min measured value (degree Celsius) */ -#define ESP_TEMP_SENSOR_MAX_VALUE (50) /* Local sensor max measured value (degree Celsius) */ - -/* Attribute values in ZCL string format - * The string should be started with the length of its own. - */ -#define MANUFACTURER_NAME \ - "\x0B" \ - "ESPRESSIF" -#define MODEL_IDENTIFIER "\x09" CONFIG_IDF_TARGET - -/********************* Zigbee functions **************************/ -static int16_t zb_temperature_to_s16(float temp) { - return (int16_t)(temp * 100); -} - -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* 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_TEMP_MEASUREMENT_VALUE_ID; - report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; - report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - report_attr_cmd.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT; - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); - esp_zb_lock_release(); - log_i("Send 'report attributes' command"); - } -} - -static void esp_app_temp_sensor_handler(float temperature) { - int16_t measured_value = zb_temperature_to_s16(temperature); - Serial.println("Updating temperature sensor value..."); - Serial.println(measured_value); - /* Update temperature sensor measured value */ - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_set_attribute_val( - HA_ESP_SENSOR_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &measured_value, - false - ); - esp_zb_lock_release(); -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Start network steering"); - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - // Start Temperature sensor reading task - xTaskCreate(temp_sensor_value_update, "temp_sensor_update", 2048, NULL, 10, NULL); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network steering"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Device rebooted"); - } - } else { - /* commissioning failed */ - log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - } else { - log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static esp_zb_cluster_list_t *custom_temperature_sensor_clusters_create(esp_zb_temperature_sensor_cfg_t *temperature_sensor) { - esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(temperature_sensor->basic_cfg)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(&(temperature_sensor->identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE) - ); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_temperature_meas_cluster( - cluster_list, esp_zb_temperature_meas_cluster_create(&(temperature_sensor->temp_meas_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE - )); - return cluster_list; -} - -static esp_zb_ep_list_t *custom_temperature_sensor_ep_create(uint8_t endpoint_id, esp_zb_temperature_sensor_cfg_t *temperature_sensor) { - esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); - esp_zb_endpoint_config_t endpoint_config = { - .endpoint = endpoint_id, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = 0 - }; - esp_zb_ep_list_add_ep(ep_list, custom_temperature_sensor_clusters_create(temperature_sensor), endpoint_config); - return ep_list; -} - -static void esp_zb_task(void *pvParameters) { - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - /* Create customized temperature sensor endpoint */ - esp_zb_temperature_sensor_cfg_t sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); - /* Set (Min|Max)MeasuredValure */ - sensor_cfg.temp_meas_cfg.min_value = zb_temperature_to_s16(ESP_TEMP_SENSOR_MIN_VALUE); - sensor_cfg.temp_meas_cfg.max_value = zb_temperature_to_s16(ESP_TEMP_SENSOR_MAX_VALUE); - esp_zb_ep_list_t *esp_zb_sensor_ep = custom_temperature_sensor_ep_create(HA_ESP_SENSOR_ENDPOINT, &sensor_cfg); - /* Register the device */ - esp_zb_device_register(esp_zb_sensor_ep); - - /* Config the reporting info */ - esp_zb_zcl_reporting_info_t reporting_info = { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .ep = HA_ESP_SENSOR_ENDPOINT, - .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, - .attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, - .u = - { - .send_info = - { - .min_interval = 1, - .max_interval = 0, - .delta = - { - .u16 = 100, - }, - .def_min_interval = 1, - .def_max_interval = 0, - }, - }, - .dst = - { - .profile_id = ESP_ZB_AF_HA_PROFILE_ID, - }, - .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, - }; - esp_zb_zcl_update_reporting_info(&reporting_info); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - - //Erase NVRAM before creating connection to new Coordinator - //esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are connecting to new Coordinator - - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/************************ Temp sensor *****************************/ -static void temp_sensor_value_update(void *arg) { - for (;;) { - float tsens_value = temperatureRead(); - esp_app_temp_sensor_handler(tsens_value); - delay(1000); - } -} - -/********************* Arduino functions **************************/ -void setup() { - Serial.begin(115200); - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - float temperature; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - delay(10); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Temperature_Sensor/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md deleted file mode 100644 index 5c88feda311..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# Arduino-ESP32 Zigbee Thermostat Example - -This example shows how to configure Zigbee Coordinator and use it as a Home Automation (HA) thermostat. - -**This example is based on ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_thermostat.** - -# Supported Targets - -Currently, this example supports the following targets. - -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | - -## Thermostat Functions - -Note: - * This board means the board (e.g. ESP32-H2) loaded with `Zigbee_Thermostat` example. - * The remote board means the board (e.g. ESP32-H2) loaded with `Zigbee_Temperature_Sensor` example. - -Functions: - * By clicking the switch button (BOOT) on this board, this board will read temperature value, temperature measurement range and temperature tolerance from the remote board. Also, this board will configure the remote board to report the measured temperature value every 10 seconds or every 2 degree changes. - -## Hardware Required - -* One development board (ESP32-H2 or ESP32-C6) acting as Zigbee end device (loaded with Zigbee_Temperature_Sensor example). -* A USB cable for power supply and programming. -* Choose another board (ESP32-H2 or ESP32-C6) as Zigbee coordinator (loaded with Zigbee_Thermostat example). - -### Configure the Project - -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the `GPIO_NUM_9` (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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. -* 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. - -## Troubleshooting - -If the End device flashed with the example `Zigbee_Temperature_Sensor` 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`. -* In the `Zigbee_Temperature_Sensor` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. - -By default, the coordinator network is open for 180 s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. - -***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 - -The ESP Zigbee SDK provides more examples: -* ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) -* ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) - -* Official ESP32 Forum: [Link](https://esp32.com) -* Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) -* ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) -* ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) -* ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) -* ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) -* Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino deleted file mode 100644 index f229b9f10e8..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ /dev/null @@ -1,565 +0,0 @@ -// 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 ESP Zigbee stack 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). - * Button switch and Zigbee runs in separate tasks. - * - * 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. - */ - -#ifndef ZIGBEE_MODE_ZCZR -#error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" -#endif - -#include "esp_zigbee_core.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" - -#define ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) - -/* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 -#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) - -typedef enum { - SWITCH_ON_CONTROL, - SWITCH_OFF_CONTROL, - SWITCH_ONOFF_TOGGLE_CONTROL, - SWITCH_LEVEL_UP_CONTROL, - SWITCH_LEVEL_DOWN_CONTROL, - SWITCH_LEVEL_CYCLE_CONTROL, - SWITCH_COLOR_CONTROL, -} switch_func_t; - -typedef struct { - uint8_t pin; - switch_func_t func; -} switch_func_pair_t; - -typedef enum { - SWITCH_IDLE, - SWITCH_PRESS_ARMED, - SWITCH_PRESS_DETECTED, - SWITCH_PRESSED, - SWITCH_RELEASE_DETECTED, -} switch_state_t; - -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; - -/* Default Coordinator config */ -#define ESP_ZB_ZC_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = INSTALLCODE_POLICY_ENABLE, .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = MAX_CHILDREN, \ - }, \ - } \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - -/* Temperature sensor device parameters */ -typedef struct temp_sensor_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} temp_sensor_device_params_t; - -typedef struct zbstring_s { - uint8_t len; - char data[]; -} ESP_ZB_PACKED_STRUCT zbstring_t; - -static temp_sensor_device_params_t temp_sensor; - -/* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_THERMOSTAT_ENDPOINT 1 /* esp light switch device endpoint */ -#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ - -/* Attribute values in ZCL string format - * The string should be started with the length of its own. - */ -#define MANUFACTURER_NAME \ - "\x0B" \ - "ESPRESSIF" -#define MODEL_IDENTIFIER "\x09" CONFIG_IDF_TARGET - -/********************* Zigbee functions **************************/ -static float zb_s16_to_temperature(int16_t value) { - return 1.0 * value / 100; -} - -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { - if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { - /* 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_DST_ADDR_ENDP_NOT_PRESENT; - read_req.zcl_basic_cmd.src_endpoint = HA_THERMOSTAT_ENDPOINT; - read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, 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 = ARRAY_LENTH(attributes); - read_req.attr_field = attributes; - - /* 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_DST_ADDR_ENDP_NOT_PRESENT; - report_cmd.zcl_basic_cmd.src_endpoint = HA_THERMOSTAT_ENDPOINT; - report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - int16_t report_change = 200; /* report on each 2 degree changes */ - esp_zb_zcl_config_report_record_t records[] = { - { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, - .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, - .min_interval = 0, - .max_interval = 10, - .reportable_change = &report_change, - }, - }; - report_cmd.record_number = ARRAY_LENTH(records); - report_cmd.record_field = records; - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_config_report_cmd_req(&report_cmd); - esp_zb_lock_release(); - log_i("Send 'configure reporting' command"); - - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_read_attr_cmd_req(&read_req); - esp_zb_lock_release(); - log_i("Send 'read attributes' command"); - } -} - -static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { - ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); -} - -static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)user_ctx; - - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - /* Local binding succeeds */ - if (bind_req->req_dst_addr == esp_zb_get_short_address()) { - log_i("Successfully bind the temperature sensor from address(0x%x) on endpoint(%d)", temp_sensor.short_addr, temp_sensor.endpoint); - - /* Read peer Manufacture Name & Model Identifier */ - 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 = HA_THERMOSTAT_ENDPOINT; - read_req.zcl_basic_cmd.dst_endpoint = temp_sensor.endpoint; - read_req.zcl_basic_cmd.dst_addr_u.addr_short = temp_sensor.short_addr; - read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; - - uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, - ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, - }; - read_req.attr_number = ARRAY_LENTH(attributes); - read_req.attr_field = attributes; - - esp_zb_zcl_read_attr_cmd_req(&read_req); - } - if (bind_req->req_dst_addr == temp_sensor.short_addr) { - log_i("The temperature sensor from address(0x%x) on endpoint(%d) successfully binds us", temp_sensor.short_addr, temp_sensor.endpoint); - } - free(bind_req); - } else { - /* Bind failed, maybe retry the binding ? */ - - // esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - } -} - -static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Found temperature sensor"); - /* Store the information of the remote device */ - temp_sensor_device_params_t *sensor = (temp_sensor_device_params_t *)user_ctx; - sensor->endpoint = endpoint; - sensor->short_addr = addr; - esp_zb_ieee_address_by_short(sensor->short_addr, sensor->ieee_addr); - log_d("Temperature sensor found: short address(0x%x), endpoint(%d)", sensor->short_addr, sensor->endpoint); - - /* 1. Send binding request to the sensor */ - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = addr; - log_d("Request temperature sensor to bind us"); - - /* populate the src information of the binding */ - memcpy(bind_req->src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->src_endp = endpoint; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - log_d("Bind temperature sensor"); - - /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - esp_zb_get_long_address(bind_req->dst_address_u.addr_long); - bind_req->dst_endp = HA_THERMOSTAT_ENDPOINT; - - log_i("Request temperature sensor to bind us"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - - /* 2. Send binding request to self */ - bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = esp_zb_get_short_address(); - - /* populate the src information of the binding */ - esp_zb_get_long_address(bind_req->src_address); - bind_req->src_endp = HA_THERMOSTAT_ENDPOINT; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - - /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req->dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->dst_endp = endpoint; - - log_i("Bind temperature sensor"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); - } -} - -static void find_temperature_sensor(esp_zb_zdo_match_desc_req_param_t *param, esp_zb_zdo_match_desc_callback_t user_cb, void *user_ctx) { - uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; - param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; - param->num_in_clusters = 1; - param->num_out_clusters = 0; - param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, user_cb, (void *)&temp_sensor); -} - -void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { - uint32_t *p_sg_p = signal_struct->p_app_signal; - esp_err_t err_status = signal_struct->esp_err_status; - esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; - esp_zb_zdo_signal_device_annce_params_t *dev_annce_params = NULL; - switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: - log_i("Zigbee stack initialized"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); - break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: - if (err_status == ESP_OK) { - log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); - if (esp_zb_bdb_is_factory_new()) { - log_i("Start network formation"); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); - } else { - log_i("Device rebooted"); - log_i("Opening network for joining for %d seconds", 180); - esp_zb_bdb_open_network(180); - } - } else { - log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); - } - break; - case ESP_ZB_BDB_SIGNAL_FORMATION: - if (err_status == ESP_OK) { - esp_zb_ieee_addr_t extended_pan_id; - esp_zb_get_extended_pan_id(extended_pan_id); - log_i( - "Formed network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", - extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], - extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address() - ); - esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); - } else { - log_i("Restart network formation (status: %s)", esp_err_to_name(err_status)); - esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_FORMATION, 1000); - } - break; - case ESP_ZB_BDB_SIGNAL_STEERING: - if (err_status == ESP_OK) { - log_i("Network steering started"); - } - break; - case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: - dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); - log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); - esp_zb_zdo_match_desc_req_param_t cmd_req; - cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; - cmd_req.addr_of_interest = dev_annce_params->device_short_addr; - find_temperature_sensor(&cmd_req, user_find_cb, NULL); - break; - case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: - if (err_status == ESP_OK) { - if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { - log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); - } else { - log_w("Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); - } - } - break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; - } -} - -static void esp_app_zb_attribute_handler(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { - /* Basic cluster attributes */ - if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Manufacturer is \"%s\"", string); - free(string); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Model is \"%s\"", string); - free(string); - } - } - - /* Temperature Measurement cluster attributes */ - 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; - log_i("Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(value)); - } - 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; - log_i("Min Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(min_value)); - } - 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; - log_i("Max Measured Value is %.2f degrees Celsius", zb_s16_to_temperature(max_value)); - } - 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; - log_i("Tolerance is %.2f degrees Celsius", 1.0 * tolerance / 100); - } - } -} - -static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->status); - } - log_i( - "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, - message->dst_endpoint, message->cluster - ); - esp_app_zb_attribute_handler(message->cluster, &message->attribute); - return ESP_OK; -} - -static esp_err_t zb_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - log_i( - "Read attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr, - message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster - ); - - esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; - while (variable) { - log_i( - "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)", variable->status, message->info.cluster, - variable->attribute.id, variable->attribute.data.type, variable->attribute.data.value ? *(uint8_t *)variable->attribute.data.value : 0 - ); - if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { - esp_app_zb_attribute_handler(message->info.cluster, &variable->attribute); - } - - variable = variable->next; - } - - return ESP_OK; -} - -static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message) { - if (!message) { - log_e("Empty message"); - } - if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { - log_e("Received message: error status(%d)", message->info.status); - } - esp_zb_zcl_config_report_resp_variable_t *variable = message->variables; - while (variable) { - log_i( - "Configure report response: status(%d), cluster(0x%x), direction(0x%x), attribute(0x%x)", variable->status, message->info.cluster, variable->direction, - variable->attribute_id - ); - variable = variable->next; - } - - return ESP_OK; -} - -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { - esp_err_t ret = ESP_OK; - switch (callback_id) { - case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; - case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; - case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; - default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; - } - return ret; -} - -static esp_zb_cluster_list_t *custom_thermostat_clusters_create(esp_zb_thermostat_cfg_t *thermostat) { - esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat->basic_cfg)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); - ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(&(thermostat->identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE) - ); - ESP_ERROR_CHECK( - esp_zb_cluster_list_add_thermostat_cluster(cluster_list, esp_zb_thermostat_cluster_create(&(thermostat->thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE) - ); - /* Add temperature measurement cluster for attribute reporting */ - ESP_ERROR_CHECK(esp_zb_cluster_list_add_temperature_meas_cluster(cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); - return cluster_list; -} - -static esp_zb_ep_list_t *custom_thermostat_ep_create(uint8_t endpoint_id, esp_zb_thermostat_cfg_t *thermostat) { - esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); - esp_zb_endpoint_config_t endpoint_config = { - .endpoint = endpoint_id, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, .app_device_version = 0 - }; - esp_zb_ep_list_add_ep(ep_list, custom_thermostat_clusters_create(thermostat), endpoint_config); - return ep_list; -} - -static void esp_zb_task(void *pvParameters) { - /* Initialize Zigbee stack */ - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG(); - esp_zb_init(&zb_nwk_cfg); - /* Create customized thermostat endpoint */ - esp_zb_thermostat_cfg_t thermostat_cfg = ESP_ZB_DEFAULT_THERMOSTAT_CONFIG(); - esp_zb_ep_list_t *esp_zb_thermostat_ep = custom_thermostat_ep_create(HA_THERMOSTAT_ENDPOINT, &thermostat_cfg); - /* Register the device */ - esp_zb_device_register(esp_zb_thermostat_ep); - - esp_zb_core_action_handler_register(zb_action_handler); - esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_main_loop_iteration(); -} - -/********************* GPIO functions **************************/ -static QueueHandle_t gpio_evt_queue = NULL; - -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); -} - -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { - if (enabled) { - enableInterrupt((button_func_pair[i]).pin); - } else { - disableInterrupt((button_func_pair[i]).pin); - } - } -} - -/********************* Arduino functions **************************/ -void setup() { - // Init Zigbee - esp_zb_platform_config_t config = { - .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), - .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), - }; - - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - - // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); - /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); - if (gpio_evt_queue == 0) { - log_e("Queue was not created and must not be used"); - while (1); - } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); - } - - // Start Zigbee task - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} - -void loop() { - // Handle button switch in loop() - uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; - - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; - } - while (evt_flag) { - bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; - case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; - /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); - break; - default: break; - } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; - break; - } - delay(10); - } -} diff --git a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json b/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json deleted file mode 100644 index 7cfaa76784d..00000000000 --- a/libraries/ESP32/examples/Zigbee/Zigbee_Thermostat/ci.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "targets": { - "esp32": false, - "esp32c3": false, - "esp32c6": false, - "esp32h2": false, - "esp32s2": false, - "esp32s3": false - } -} From 4d18a8c17a1020deb3e343b85acdc38557deb2b8 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:01:26 +0200 Subject: [PATCH 14/34] Update Zigbee examples with new APIs --- .../Zigbee_Color_Dimmable_Light.ino | 8 ++++---- .../Zigbee_Color_Dimmer_Switch.ino | 4 ++-- .../examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino | 4 ++-- .../Zigbee_Temperature_Sensor.ino | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index 989491c73d6..9de7705192d 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -46,7 +46,7 @@ public: // Override the set_on_off function void setOnOff(bool value) override { if (value == false) { - neopixelWrite(LED_PIN, 0, 0, 0); // Turn off light + rgbLedWrite(LED_PIN, 0, 0, 0); // Turn off light } else { updateLight(); // Turn on light on last color and level } @@ -55,7 +55,7 @@ public: // Override the set_level function void setLevel(uint8_t level) override { if (level == 0) { - neopixelWrite(LED_PIN, 0, 0, 0); // Turn off light and dont update ratio + rgbLedWrite(LED_PIN, 0, 0, 0); // Turn off light and dont update ratio return; } _ratio = (float)level / 255; @@ -71,7 +71,7 @@ public: } void updateLight() { - neopixelWrite(LED_PIN, _red * _ratio, _green * _ratio, _blue * _ratio); // Update light + rgbLedWrite(LED_PIN, _red * _ratio, _green * _ratio, _blue * _ratio); // Update light } private: // Add your custom attributes and methods here @@ -87,7 +87,7 @@ MyZigbeeColorLight zbColorLight = MyZigbeeColorLight(ZIGBEE_LIGHT_ENDPOINT); /********************* Arduino functions **************************/ void setup() { // Init RMT and leave light OFF - neopixelWrite(LED_PIN, 0, 0, 0); + rgbLedWrite(LED_PIN, 0, 0, 0); // Init button for factory reset pinMode(BUTTON_PIN, INPUT); diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index 7695de03726..e56d2b6582e 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -137,10 +137,10 @@ void loop() { } } - // print the bound lights every 30 seconds + // print the bound devices (lights) every 30 seconds static uint32_t last_print = 0; if (millis() - last_print > 30000) { last_print = millis(); - zbSwitch.printBoundLights(); + zbSwitch.printBoundDevices(); } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index 43ca3346220..cff9838decc 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -44,7 +44,7 @@ public: // Override the set_on_off function void setOnOff(bool value) override { - neopixelWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light + rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light } }; @@ -53,7 +53,7 @@ MyZigbeeLight zbLight = MyZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); /********************* Arduino functions **************************/ void setup() { // Init RMT and leave light OFF - neopixelWrite(LED_PIN, 0, 0, 0); + rgbLedWrite(LED_PIN, 0, 0, 0); // Init button for factory reset pinMode(BUTTON_PIN, INPUT); diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 8602af424e2..3a0ea1db35f 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -34,8 +34,8 @@ #include "ep/ep_temperature_sensor.h" #define BUTTON_PIN 9 //Boot button for C6/H2 - #define TEMP_SENSOR_ENDPOINT_NUMBER 10 + ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); /************************ Temp sensor *****************************/ From fa6267aff14f5951f117e185f4bc517da9e70299 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:44:51 +0200 Subject: [PATCH 15/34] Dev Update: Version setting, Thermostat fix, ... Simplified bounded device print as the structure is common for any EP type Allowed setting custom app version for EP, default is 0 Small fixes and code updates --- boards.txt | 84 +++++++------- .../Zigbee_Color_Dimmer_Switch/README.md | 2 +- .../examples/Zigbee_On_Off_Switch/README.md | 4 +- .../examples/Zigbee_Thermostat/README.md | 2 +- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 2 +- libraries/Zigbee/library.properties | 1 + libraries/Zigbee/src/Zigbee_core.cpp | 29 +---- libraries/Zigbee/src/Zigbee_ep.cpp | 12 ++ libraries/Zigbee/src/Zigbee_ep.h | 17 ++- .../Zigbee/src/ep/ep_color_dimmable_light.cpp | 3 +- .../Zigbee/src/ep/ep_color_dimmer_switch.cpp | 23 ++-- .../Zigbee/src/ep/ep_color_dimmer_switch.h | 21 ---- libraries/Zigbee/src/ep/ep_on_off_light.cpp | 3 +- libraries/Zigbee/src/ep/ep_on_off_switch.cpp | 35 +----- libraries/Zigbee/src/ep/ep_on_off_switch.h | 10 -- .../Zigbee/src/ep/ep_temperature_sensor.cpp | 13 ++- .../Zigbee/src/ep/ep_temperature_sensor.h | 4 +- libraries/Zigbee/src/ep/ep_template.cpp | 11 +- libraries/Zigbee/src/ep/ep_thermostat.cpp | 106 +++++++----------- libraries/Zigbee/src/ep/ep_thermostat.h | 3 + 20 files changed, 149 insertions(+), 236 deletions(-) diff --git a/boards.txt b/boards.txt index 6ac1a2cae20..72d338cff09 100644 --- a/boards.txt +++ b/boards.txt @@ -339,7 +339,7 @@ esp32h2.menu.ZigbeeMode.default.build.zigbee_libs= esp32h2.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32h2.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED esp32h2.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32h2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32h2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32h2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32h2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port esp32h2.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -533,7 +533,7 @@ esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -789,7 +789,7 @@ esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e esp32s3.menu.ZigbeeMode.default=Disabled esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -971,7 +971,7 @@ esp32c3.menu.EraseFlash.all.upload.erase_cmd=-e esp32c3.menu.ZigbeeMode.default=Disabled esp32c3.menu.ZigbeeMode.default.build.zigbee_mode= esp32c3.menu.ZigbeeMode.default.build.zigbee_libs= -esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -1180,7 +1180,7 @@ esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e esp32s2.menu.ZigbeeMode.default=Disabled esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -1376,7 +1376,7 @@ esp32.menu.EraseFlash.all.upload.erase_cmd=-e esp32.menu.ZigbeeMode.default=Disabled esp32.menu.ZigbeeMode.default.build.zigbee_mode= esp32.menu.ZigbeeMode.default.build.zigbee_libs= -esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -4133,7 +4133,7 @@ um_tinyc6.menu.ZigbeeMode.default.build.zigbee_libs= um_tinyc6.menu.ZigbeeMode.ed=Zigbee ED (end device) um_tinyc6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED um_tinyc6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -um_tinyc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +um_tinyc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) um_tinyc6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR um_tinyc6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port um_tinyc6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -6933,7 +6933,7 @@ sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.default.build.zigbee_libs= sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed=Zigbee ED (end device) sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port sparkfun_esp32c6_thing_plus.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -7532,7 +7532,7 @@ sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.default.build.zigbee_libs= sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed=Zigbee ED (end device) sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port sparkfun_esp32c6_qwiic_pocket.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -10770,7 +10770,7 @@ dfrobot_beetle_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED dfrobot_beetle_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR dfrobot_beetle_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port dfrobot_beetle_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -11322,7 +11322,7 @@ dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port dfrobot_firebeetle2_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -11921,7 +11921,7 @@ adafruit_metro_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_metro_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_metro_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_metro_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_metro_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_metro_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_metro_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_metro_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12124,7 +12124,7 @@ adafruit_metro_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_metro_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_metro_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_metro_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_metro_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_metro_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_metro_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_metro_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12307,7 +12307,7 @@ adafruit_magtag29_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_magtag29_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_magtag29_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_magtag29_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_magtag29_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12490,7 +12490,7 @@ adafruit_funhouse_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_funhouse_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_funhouse_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_funhouse_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_funhouse_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12624,7 +12624,7 @@ featheresp32.menu.EraseFlash.all.upload.erase_cmd=-e featheresp32.menu.ZigbeeMode.default=Disabled featheresp32.menu.ZigbeeMode.default.build.zigbee_mode= featheresp32.menu.ZigbeeMode.default.build.zigbee_libs= -featheresp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +featheresp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) featheresp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR featheresp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12742,7 +12742,7 @@ adafruit_feather_esp32_v2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32_v2.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32_v2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32_v2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32_v2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -12925,7 +12925,7 @@ adafruit_feather_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -13108,7 +13108,7 @@ adafruit_feather_esp32s2_tft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2_tft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s2_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -13291,7 +13291,7 @@ adafruit_feather_esp32s2_reversetft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s2_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -13509,7 +13509,7 @@ adafruit_feather_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -13696,7 +13696,7 @@ adafruit_feather_esp32s3_nopsram.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -13914,7 +13914,7 @@ adafruit_feather_esp32s3_tft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_tft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s3_tft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -14132,7 +14132,7 @@ adafruit_feather_esp32s3_reversetft.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default=Disabled adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32s3_reversetft.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -14307,7 +14307,7 @@ adafruit_feather_esp32c6.menu.ZigbeeMode.default.build.zigbee_libs= adafruit_feather_esp32c6.menu.ZigbeeMode.ed=Zigbee ED (end device) adafruit_feather_esp32c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED adafruit_feather_esp32c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -adafruit_feather_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_feather_esp32c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_feather_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_feather_esp32c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port adafruit_feather_esp32c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -14430,7 +14430,7 @@ adafruit_qtpy_esp32_pico.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32_pico.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qtpy_esp32_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -14565,7 +14565,7 @@ adafruit_qtpy_esp32c3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32c3.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32c3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32c3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qtpy_esp32c3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -14748,7 +14748,7 @@ adafruit_qtpy_esp32s2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s2.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qtpy_esp32s2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -14935,7 +14935,7 @@ adafruit_qtpy_esp32s3_nopsram.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qtpy_esp32s3_nopsram.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -15153,7 +15153,7 @@ adafruit_qtpy_esp32s3_n4r2.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default=Disabled adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qtpy_esp32s3_n4r2.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -15271,7 +15271,7 @@ adafruit_itsybitsy_esp32.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_itsybitsy_esp32.menu.ZigbeeMode.default=Disabled adafruit_itsybitsy_esp32.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_itsybitsy_esp32.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_itsybitsy_esp32.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -15468,7 +15468,7 @@ adafruit_matrixportal_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_matrixportal_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_matrixportal_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -15686,7 +15686,7 @@ adafruit_camera_esp32s3.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_camera_esp32s3.menu.ZigbeeMode.default=Disabled adafruit_camera_esp32s3.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_camera_esp32s3.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_camera_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_camera_esp32s3.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_camera_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_camera_esp32s3.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -15889,7 +15889,7 @@ adafruit_qualia_s3_rgb666.menu.EraseFlash.all.upload.erase_cmd=-e adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default=Disabled adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default.build.zigbee_mode= adafruit_qualia_s3_rgb666.menu.ZigbeeMode.default.build.zigbee_libs= -adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR adafruit_qualia_s3_rgb666.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -16344,7 +16344,7 @@ nologo_esp32s3_pico.menu.EraseFlash.all.upload.erase_cmd=-e nologo_esp32s3_pico.menu.ZigbeeMode.default=Disabled nologo_esp32s3_pico.menu.ZigbeeMode.default.build.zigbee_mode= nologo_esp32s3_pico.menu.ZigbeeMode.default.build.zigbee_libs= -nologo_esp32s3_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +nologo_esp32s3_pico.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) nologo_esp32s3_pico.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR nologo_esp32s3_pico.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -18290,7 +18290,7 @@ esp32c6-evb.menu.ZigbeeMode.default.build.zigbee_libs= esp32c6-evb.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32c6-evb.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED esp32c6-evb.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32c6-evb.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32c6-evb.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32c6-evb.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32c6-evb.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port esp32c6-evb.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -18472,7 +18472,7 @@ esp32h2-devkitlipo.menu.ZigbeeMode.default.build.zigbee_libs= esp32h2-devkitlipo.menu.ZigbeeMode.ed=Zigbee ED (end device) esp32h2-devkitlipo.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED esp32h2-devkitlipo.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -esp32h2-devkitlipo.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32h2-devkitlipo.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32h2-devkitlipo.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32h2-devkitlipo.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port esp32h2-devkitlipo.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -18668,7 +18668,7 @@ esp32-sbc-fabgl.menu.EraseFlash.all.upload.erase_cmd=-e esp32-sbc-fabgl.menu.ZigbeeMode.default=Disabled esp32-sbc-fabgl.menu.ZigbeeMode.default.build.zigbee_mode= esp32-sbc-fabgl.menu.ZigbeeMode.default.build.zigbee_libs= -esp32-sbc-fabgl.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +esp32-sbc-fabgl.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) esp32-sbc-fabgl.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR esp32-sbc-fabgl.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port @@ -23358,7 +23358,7 @@ m5stack_nanoc6.menu.ZigbeeMode.default.build.zigbee_libs= m5stack_nanoc6.menu.ZigbeeMode.ed=Zigbee ED (end device) m5stack_nanoc6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED m5stack_nanoc6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -m5stack_nanoc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +m5stack_nanoc6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) m5stack_nanoc6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR m5stack_nanoc6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port m5stack_nanoc6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -33790,7 +33790,7 @@ XIAO_ESP32C6.menu.ZigbeeMode.default.build.zigbee_libs= XIAO_ESP32C6.menu.ZigbeeMode.ed=Zigbee ED (end device) XIAO_ESP32C6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED XIAO_ESP32C6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -XIAO_ESP32C6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +XIAO_ESP32C6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) XIAO_ESP32C6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR XIAO_ESP32C6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port XIAO_ESP32C6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -38988,7 +38988,7 @@ epulse_feather_c6.menu.ZigbeeMode.default.build.zigbee_libs= epulse_feather_c6.menu.ZigbeeMode.ed=Zigbee ED (end device) epulse_feather_c6.menu.ZigbeeMode.ed.build.zigbee_mode=-DZIGBEE_MODE_ED epulse_feather_c6.menu.ZigbeeMode.ed.build.zigbee_libs=-lesp_zb_api_ed -lesp_zb_cli_command -lzboss_stack.ed -lzboss_port -epulse_feather_c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +epulse_feather_c6.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) epulse_feather_c6.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR epulse_feather_c6.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port epulse_feather_c6.menu.ZigbeeMode.rcp=Zigbee RCP (radio co-processor) @@ -41275,7 +41275,7 @@ jczn_2432s028r.menu.EraseFlash.all.upload.erase_cmd=-e jczn_2432s028r.menu.ZigbeeMode.default=Disabled jczn_2432s028r.menu.ZigbeeMode.default.build.zigbee_mode= jczn_2432s028r.menu.ZigbeeMode.default.build.zigbee_libs= -jczn_2432s028r.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator) +jczn_2432s028r.menu.ZigbeeMode.zczr=Zigbee ZCZR (coordinator/router) jczn_2432s028r.menu.ZigbeeMode.zczr.build.zigbee_mode=-DZIGBEE_MODE_ZCZR jczn_2432s028r.menu.ZigbeeMode.zczr.build.zigbee_libs=-lesp_zb_api_zczr -lesp_zb_cli_command -lzboss_stack.zczr -lzboss_port diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md index 75d8ea6fe1f..89a578191bd 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md @@ -24,7 +24,7 @@ Set the Button Switch GPIO by changing the `GPIO_SWITCH` definition. By default, 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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md index d665a396f2f..90a95c3fc34 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md @@ -17,14 +17,14 @@ Currently, this example supports the following targets. ### Configure the Project -Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, the LED_PIN is `GPIO_NUM_9`. +Set the Button Switch GPIO by changing the `GPIO_INPUT_IO_TOGGLE_SWITCH` definition. By default, it's the pin `9` (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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/README.md b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md index d239aaefcca..2e6d9ca471c 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/README.md +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md @@ -35,7 +35,7 @@ Set the Button GPIO by changing the `BUTTON_PIN` definition. By default, it's th 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 Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator)`. +* Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index da99829b2d1..d88f5781d99 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -93,7 +93,7 @@ void setup() { // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode Zigbee.begin(ZIGBEE_COORDINATOR); - Serial.println("Waiting for Light to bound to the switch"); + Serial.println("Waiting for Temperature sensor to bound to the switch"); //Wait for switch to bound to a light: while(!zbThermostat.is_bound()) { diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties index 0c5028b21db..ce00e64a730 100644 --- a/libraries/Zigbee/library.properties +++ b/libraries/Zigbee/library.properties @@ -4,5 +4,6 @@ author=P-R-O-C-H-Y maintainer=Jan Procházka sentence=Enables zigbee connection with the ESP32 paragraph=With this library you can create zigbee end devices, routers, coordinators and connect them to the zigbee network. +category=Communication url= architectures=esp32 diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/Zigbee_core.cpp index 97e635d560c..569ac06ae83 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/Zigbee_core.cpp @@ -244,7 +244,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { esp_zb_zdo_match_desc_req_param_t cmd_req; cmd_req.dst_nwk_addr = dev_annce_params->device_short_addr; cmd_req.addr_of_interest = dev_annce_params->device_short_addr; - log_i("Device capabilities: 0x%02x", dev_annce_params->capability); + log_v("Device capabilities: 0x%02x", dev_annce_params->capability); /* capability: Bit 0 – Alternate PAN Coordinator @@ -257,8 +257,6 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { Bit 7 – Reserved */ - //TODO: Save the device short address and endpoint to the list ???????? - // for each endpoint in the list call the find_endpoint function if not bounded or allowed to bind multiple devices for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (!(*it)->_is_bound || (*it)->_allow_multiple_binding) { @@ -278,7 +276,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } break; - default: log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; + default: log_v("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; } } @@ -338,28 +336,6 @@ void Zigbee_Core::scanDelete() { _scan_status = ZB_SCAN_FAILED; } -// NOTE: Binding functions to not forget -// void esp_zb_zdo_device_bind_req(esp_zb_zdo_bind_req_param_t *cmd_req, esp_zb_zdo_bind_callback_t user_cb, void *user_ctx) -// { -// uint8_t output = 0; -// uint16_t outlen = sizeof(uint8_t); - -// typedef struct { -// esp_zb_zdo_bind_req_param_t bind_req; -// esp_zb_user_cb_t bind_usr; -// } esp_zb_zdo_bind_req_t; - -// esp_zb_zdo_bind_req_t zdo_data = { -// .bind_usr = { -// .user_ctx = (uint32_t)user_ctx, -// .user_cb = (uint32_t)user_cb, -// }, -// }; - -// memcpy(&zdo_data.bind_req, cmd_req, sizeof(esp_zb_zdo_bind_req_param_t)); -// esp_host_zb_output(ESP_ZNSP_ZDO_BIND_SET, &zdo_data, sizeof(esp_zb_zdo_bind_req_t), &output, &outlen); -// } - // Function to convert enum value to string const char* Zigbee_Core::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { switch (deviceId) { @@ -386,6 +362,7 @@ const char* Zigbee_Core::getDeviceTypeString(esp_zb_ha_standard_devices_t device case ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID: return "Color Dimmable Light Device"; case ESP_ZB_HA_DIMMER_SWITCH_DEVICE_ID: return "Dimmer Switch Device"; case ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID: return "Color Dimmer Switch Device"; + case ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID: return "Light Sensor"; case ESP_ZB_HA_SHADE_DEVICE_ID: return "Shade"; case ESP_ZB_HA_SHADE_CONTROLLER_DEVICE_ID: return "Shade controller"; case ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID: return "Window Covering client"; diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/Zigbee_ep.cpp index 3c55f9cc8b5..f5cfcdbc4f1 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/Zigbee_ep.cpp @@ -18,6 +18,10 @@ Zigbee_EP::~Zigbee_EP() { } +void Zigbee_EP::setVersion(uint8_t version) { + _ep_config.app_device_version = version; +} + void Zigbee_EP::setManufacturerAndModel(const char *name, const char *model) { // Convert manufacturer to ZCL string size_t length = strlen(name); @@ -74,6 +78,14 @@ void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) esp_zb_zcl_read_attr_cmd_req(&read_req); } +void Zigbee_EP::printBoundDevices() { + log_i("Bound devices:"); + for(const auto& device : _bound_devices) { + log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); + print_ieee_addr(device->ieee_addr); + } +} + void Zigbee_EP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/Zigbee_ep.h index 3d8ec6df2ec..ff34783d9f5 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/Zigbee_ep.h @@ -31,6 +31,12 @@ typedef struct zbstring_s { } ESP_ZB_PACKED_STRUCT zbstring_t; +typedef struct zb_device_params_s { + esp_zb_ieee_addr_t ieee_addr; + uint8_t endpoint; + uint16_t short_addr; +} zb_device_params_t; + /* Zigbee End Device Class */ class Zigbee_EP { public: @@ -42,10 +48,12 @@ class Zigbee_EP { static uint8_t _endpoint; esp_zb_ha_standard_devices_t _device_id; //type of device - uint8_t _version; esp_zb_endpoint_config_t _ep_config; esp_zb_cluster_list_t *_cluster_list; + std::list _bound_devices; + + static bool _is_bound; // Set ep config and cluster list void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { @@ -53,8 +61,10 @@ class Zigbee_EP { _cluster_list = cluster_list; } - static bool _is_bound; + void setVersion(uint8_t version); + static bool is_bound() { return _is_bound; } + void printBoundDevices(); static bool _allow_multiple_binding; static void allowMultipleBinding(bool bind) { _allow_multiple_binding = bind; } @@ -72,7 +82,4 @@ class Zigbee_EP { virtual void readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented friend class ZigbeeCore; - - // List of Zigbee EP classes - friend class ZigbeeLight; }; diff --git a/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp b/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp index a411e082113..bddbb7eac4d 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp +++ b/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp @@ -2,7 +2,6 @@ ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; - _version = 0; esp_zb_color_dimmable_light_cfg_t light_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); _cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg); @@ -10,7 +9,7 @@ ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : Zigbee_EP .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp index cc6b05b3ccd..47b0811ce50 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp @@ -5,8 +5,6 @@ ZigbeeColorDimmerSwitch* ZigbeeColorDimmerSwitch::_instance = nullptr; ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; - _version = 0; - _instance = this; // Set the static pointer to this instance esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); @@ -16,7 +14,7 @@ ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : Zigbee_EP(e .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } @@ -42,14 +40,16 @@ void ZigbeeColorDimmerSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Bound successfully!"); if (user_ctx) { - light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + zb_device_params_t *light = (zb_device_params_t *)user_ctx; //Read manufacturer and model automatically after successful bind _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); //TODO: call user method to notify about the light and pass all the info ???? - _instance->_bound_lights.push_back(light); + _instance->_bound_devices.push_back(light); } _is_bound = true; + } else { + log_e("Binding failed!"); } } @@ -57,12 +57,12 @@ void ZigbeeColorDimmerSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t a if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); esp_zb_zdo_bind_req_param_t bind_req; - light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); esp_zb_get_long_address(bind_req.src_address); - bind_req.src_endp = _endpoint; //_dev_endpoint; + bind_req.src_endp = _endpoint; bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); @@ -93,18 +93,9 @@ void ZigbeeColorDimmerSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *c .num_out_clusters = 3, .cluster_list = cluster_list, }; - //esp_zb_zdo_find_color_dimmable_light(&cmd_req, user_find_cb, NULL); esp_zb_zdo_match_cluster(&color_dimmable_light_req, find_cb, NULL); } -void ZigbeeColorDimmerSwitch::printBoundLights() { - log_i("Bound lights:"); - for(const auto& light : _bound_lights) { - log_i("Light on endpoint %d, short address: 0x%x", light->endpoint, light->short_addr); - print_ieee_addr(light->ieee_addr); - } -} - // Methods to control the light void ZigbeeColorDimmerSwitch::lightToggle() { if (_is_bound) { diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h index bab457aa2c8..48a02282b06 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h +++ b/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h @@ -5,12 +5,6 @@ #include "Zigbee_ep.h" #include "ha/esp_zigbee_ha_standard.h" -typedef struct light_bulb_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} light_bulb_device_params_t; - class ZigbeeColorDimmerSwitch : public Zigbee_EP { public: ZigbeeColorDimmerSwitch(uint8_t endpoint); @@ -19,10 +13,6 @@ class ZigbeeColorDimmerSwitch : public Zigbee_EP { // save instance of the class in order to use it in static functions static ZigbeeColorDimmerSwitch* _instance; - // list of bounded lights - std::list _bound_lights; - void printBoundLights(); - void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); // methods to control the color dimmable light @@ -64,14 +54,3 @@ class ZigbeeColorDimmerSwitch : public Zigbee_EP { static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); }; - -//NOTE: -/* ON/OFF switch commands for light control */ -// typedef enum { -// ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID = 0x00, /*!< "Turn off" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_ID = 0x01, /*!< "Turn on" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID = 0x02, /*!< "Toggle state" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID = 0x40, /*!< "Off with effect" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID = 0x41, /*!< "On with recall global scene" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID = 0x42, /*!< "On with timed off" command. */ -// } esp_zb_zcl_on_off_cmd_id_t; diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ep_on_off_light.cpp index a6c5787c1d0..0eea501ef47 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_light.cpp @@ -2,7 +2,6 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; - _version = 0; esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() @@ -10,7 +9,7 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp index b943f4de596..d3b0ced99ef 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.cpp @@ -5,8 +5,6 @@ ZigbeeSwitch* ZigbeeSwitch::_instance = nullptr; ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; - _version = 0; - _instance = this; // Set the static pointer to this instance esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); @@ -16,7 +14,7 @@ ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } @@ -24,12 +22,12 @@ void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Bound successfully!"); if (user_ctx) { - light_bulb_device_params_t *light = (light_bulb_device_params_t *)user_ctx; + zb_device_params_t *light = (zb_device_params_t *)user_ctx; //Read manufacturer and model automatically after successful bind _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); //TODO: call user method to notify about the light and pass all the info ???? - _instance->_bound_lights.push_back(light); + _instance->_bound_devices.push_back(light); //free(light); } _is_bound = true; @@ -40,7 +38,7 @@ void ZigbeeSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_ if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); esp_zb_zdo_bind_req_param_t bind_req; - light_bulb_device_params_t *light = (light_bulb_device_params_t *)malloc(sizeof(light_bulb_device_params_t)); + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); @@ -73,30 +71,7 @@ void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { esp_zb_zdo_match_cluster(&on_off_req, find_cb, NULL); } -void ZigbeeSwitch::printBoundLights() { - log_i("Bound lights:"); - // for (std::list::iterator it = _bound_lights.begin(); it != _bound_lights.end(); ++it) { - // log_i("Light on endpoint %d, short address: 0x%x", (*it)->endpoint, (*it)->short_addr); - // print_ieee_addr((*it)->ieee_addr); - // } - for(const auto& light : _bound_lights) { - log_i("Light on endpoint %d, short address: 0x%x", light->endpoint, light->short_addr); - print_ieee_addr(light->ieee_addr); - } -} -// TODO: add endpont + adress optional parameters -// typedef enum { -// ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT = 0x0, /*!< DstAddress and DstEndpoint not present, -// only for APSDE-DATA request and confirm */ -// ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT = 0x1, /*!< 16-bit group address for DstAddress; DstEndpoint not present */ -// ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT = 0x2, /*!< 16-bit address for DstAddress and DstEndpoint present */ -// ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT = 0x3, /*!< 64-bit extended address for DstAddress and DstEndpoint present */ -// ESP_ZB_APS_ADDR_MODE_64_PRESENT_ENDP_NOT_PRESENT = 0x4, /*!< 64-bit extended address for DstAddress, but DstEndpoint NOT present, -// only for APSDE indication */ -// } esp_zb_aps_address_mode_t; - - -// Call to control the light +// Methods to control the light void ZigbeeSwitch::lightToggle() { if (_is_bound) { esp_zb_zcl_on_off_cmd_t cmd_req; diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ep_on_off_switch.h index ac3e8ba59b6..b058402b3b2 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ep_on_off_switch.h @@ -5,12 +5,6 @@ #include "Zigbee_ep.h" #include "ha/esp_zigbee_ha_standard.h" -typedef struct light_bulb_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} light_bulb_device_params_t; - class ZigbeeSwitch : public Zigbee_EP { public: ZigbeeSwitch(uint8_t endpoint); @@ -19,10 +13,6 @@ class ZigbeeSwitch : public Zigbee_EP { // save instance of the class in order to use it in static functions static ZigbeeSwitch* _instance; - // list of bounded on/off lights - std::list _bound_lights; - void printBoundLights(); - // methods to control the on/off light void lightToggle(); void lightToggle(uint16_t group_addr); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp index 41ba9947f1a..a3e988ae894 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp @@ -2,15 +2,15 @@ ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; - _version = 0; esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); + _ep_config = { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } @@ -18,10 +18,12 @@ static int16_t zb_temperature_to_s16(float temp) { return (int16_t)(temp * 100); } -void ZigbeeTempSensor::setMinMaxValue(int16_t min, int16_t max) { +void ZigbeeTempSensor::setMinMaxValue(float min, float max) { + int16_t zb_min = zb_temperature_to_s16(min); + int16_t zb_max = zb_temperature_to_s16(max); esp_zb_attribute_list_t *temp_measure_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&min); - esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&max); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); } void ZigbeeTempSensor::setTolerance(float tolerance) { @@ -65,6 +67,7 @@ void ZigbeeTempSensor::setTemperature(float temperature) { int16_t zb_temperature = zb_temperature_to_s16(temperature); log_v("Updating temperature sensor value..."); /* Update temperature sensor measured value */ + log_d("Setting temperature to %d", zb_temperature); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false); esp_zb_lock_release(); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.h b/libraries/Zigbee/src/ep/ep_temperature_sensor.h index bf2172e59ab..0e92b87b095 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.h +++ b/libraries/Zigbee/src/ep/ep_temperature_sensor.h @@ -13,8 +13,8 @@ class ZigbeeTempSensor : public Zigbee_EP { // Set the temperature value in 0,01°C void setTemperature(float value); - // Set the min and max value for the temperature sensor in °C - void setMinMaxValue(int16_t min, int16_t max); + // Set the min and max value for the temperature sensor in 0,01°C + void setMinMaxValue(float min, float max); // Set the tolerance value for the temperature sensor in 0,01°C void setTolerance(float tolerance); diff --git a/libraries/Zigbee/src/ep/ep_template.cpp b/libraries/Zigbee/src/ep/ep_template.cpp index 404b17d4369..89c508ab39b 100644 --- a/libraries/Zigbee/src/ep/ep_template.cpp +++ b/libraries/Zigbee/src/ep/ep_template.cpp @@ -1,18 +1,17 @@ #include "ep_template.h" ZigbeeDevice::ZigbeeDevice(uint8_t endpoint) : Zigbee_EP(endpoint) { - _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; //TODO: Change to correct device ID - _version = 0; - - //TODO: Change to correct config + _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; // Change to correct device ID + + //Change to correct config esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); _ep_config = { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, //TODO: Change to correct device ID - .app_device_version = _version + .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, // Change to correct device ID + .app_device_version = 0 }; } diff --git a/libraries/Zigbee/src/ep/ep_thermostat.cpp b/libraries/Zigbee/src/ep/ep_thermostat.cpp index 25b17042646..69d3b26004a 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.cpp +++ b/libraries/Zigbee/src/ep/ep_thermostat.cpp @@ -1,20 +1,15 @@ #include "ep_thermostat.h" -typedef struct temp_sensor_device_params_s { - esp_zb_ieee_addr_t ieee_addr; - uint8_t endpoint; - uint16_t short_addr; -} temp_sensor_device_params_t; - -static temp_sensor_device_params_t temp_sensor; - static float zb_s16_to_temperature(int16_t value) { return 1.0 * value / 100; } +// Initialize the static instance of the class +ZigbeeThermostat* ZigbeeThermostat::_instance = nullptr; + ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; - _version = 0; + _instance = this; // Set the static pointer to this instance //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); @@ -33,92 +28,72 @@ ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, - .app_device_version = _version + .app_device_version = 0 }; } void ZigbeeThermostat::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)user_ctx; - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - /* Local binding succeeds */ - if (bind_req->req_dst_addr == esp_zb_get_short_address()) { - log_i("Successfully bind the temperature sensor from address(0x%x) on endpoint(%d)", temp_sensor.short_addr, temp_sensor.endpoint); - - /* Read peer Manufacture Name & Model Identifier */ - 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 = temp_sensor.endpoint; - read_req.zcl_basic_cmd.dst_addr_u.addr_short = temp_sensor.short_addr; - read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC; - - uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, - ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, - }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); - read_req.attr_field = attributes; - - esp_zb_zcl_read_attr_cmd_req(&read_req); - } - if (bind_req->req_dst_addr == temp_sensor.short_addr) { - log_i("The temperature sensor from address(0x%x) on endpoint(%d) successfully binds us", temp_sensor.short_addr, temp_sensor.endpoint); - } - _is_bound = true; - free(bind_req); + if (user_ctx) { + zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; + //Read manufacturer and model automatically after successful bind + _instance->readManufacturerAndModel(sensor->endpoint, sensor->short_addr); + log_i("The temperature sensor originating from address(0x%x) on endpoint(%d)", sensor->short_addr, sensor->endpoint); + _instance->_bound_devices.push_back(sensor); + } + else { + log_v("Local binding success"); + } + _is_bound = true; } else { - /* Bind failed, maybe retry the binding ? */ - log_e("Binding failed!"); - // esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + log_e("Binding failed!"); } } void ZigbeeThermostat::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Found temperature sensor"); + esp_zb_zdo_bind_req_param_t bind_req; /* Store the information of the remote device */ - temp_sensor_device_params_t *sensor = (temp_sensor_device_params_t *)user_ctx; + zb_device_params_t *sensor = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); sensor->endpoint = endpoint; sensor->short_addr = addr; esp_zb_ieee_address_by_short(sensor->short_addr, sensor->ieee_addr); log_d("Temperature sensor found: short address(0x%x), endpoint(%d)", sensor->short_addr, sensor->endpoint); /* 1. Send binding request to the sensor */ - esp_zb_zdo_bind_req_param_t *bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = addr; + bind_req.req_dst_addr = addr; log_d("Request temperature sensor to bind us"); /* populate the src information of the binding */ - memcpy(bind_req->src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->src_endp = endpoint; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + memcpy(bind_req.src_address, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.src_endp = endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; log_d("Bind temperature sensor"); /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - esp_zb_get_long_address(bind_req->dst_address_u.addr_long); - bind_req->dst_endp = _endpoint; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + esp_zb_get_long_address(bind_req.dst_address_u.addr_long); + bind_req.dst_endp = _endpoint; log_i("Request temperature sensor to bind us"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); /* 2. Send binding request to self */ - bind_req = (esp_zb_zdo_bind_req_param_t *)calloc(sizeof(esp_zb_zdo_bind_req_param_t), 1); - bind_req->req_dst_addr = esp_zb_get_short_address(); + bind_req.req_dst_addr = esp_zb_get_short_address(); /* populate the src information of the binding */ - esp_zb_get_long_address(bind_req->src_address); - bind_req->src_endp = _endpoint; - bind_req->cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = _endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; /* populate the dst information of the binding */ - bind_req->dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req->dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req->dst_endp = endpoint; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, sensor->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; log_i("Bind temperature sensor"); - esp_zb_zdo_device_bind_req(bind_req, bind_cb, bind_req); + esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)sensor); } } @@ -128,22 +103,23 @@ void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *param) { param->num_in_clusters = 1; param->num_out_clusters = 0; param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, find_cb, (void *)&temp_sensor); + esp_zb_zdo_match_cluster(param, find_cb, NULL); } void ZigbeeThermostat::attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { 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; + log_v("Raw temperature value: %d", value); temperatureRead(zb_s16_to_temperature(value)); } 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; - temperatureMin(min_value); + temperatureMin(zb_s16_to_temperature(min_value)); } 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; - temperatureMax(max_value); + temperatureMax(zb_s16_to_temperature(max_value)); } 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; @@ -160,7 +136,9 @@ void ZigbeeThermostat::getTemperature(){ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + 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); diff --git a/libraries/Zigbee/src/ep/ep_thermostat.h b/libraries/Zigbee/src/ep/ep_thermostat.h index 7e1265f9b87..6f32c518409 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.h +++ b/libraries/Zigbee/src/ep/ep_thermostat.h @@ -31,6 +31,9 @@ class ZigbeeThermostat : public Zigbee_EP { ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat(); + // save instance of the class in order to use it in static functions + static ZigbeeThermostat* _instance; + void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); From 7693a167e1fec16bdd0487f6a40b2ec6ef73adbb Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:28:54 +0200 Subject: [PATCH 16/34] Remove EP template + add lib to CMakeLists --- CMakeLists.txt | 13 +++++++++++++ libraries/Zigbee/src/ep/ep_template.cpp | 22 ---------------------- libraries/Zigbee/src/ep/ep_template.h | 14 -------------- 3 files changed, 13 insertions(+), 36 deletions(-) delete mode 100644 libraries/Zigbee/src/ep/ep_template.cpp delete mode 100644 libraries/Zigbee/src/ep/ep_template.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bfb3ee4ff28..d8d1d93eb63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ set(ARDUINO_ALL_LIBRARIES WiFi WiFiProv Wire + Zigbee ) set(ARDUINO_LIBRARY_ArduinoOTA_SRCS libraries/ArduinoOTA/src/ArduinoOTA.cpp) @@ -240,6 +241,18 @@ set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp) set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp) +set(ARDUINO_LIBRARY_Zigbee_SRCS + libraries/Zigbee/src/Zigbee_core.cpp + libraries/Zigbee/src/Zigbee_ep.cpp + libraries/Zigbee/src/Zigbee_handlers.cpp + libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp + libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp + libraries/Zigbee/src/ep/ep_on_off_light.cpp + libraries/Zigbee/src/ep/ep_on_off_switch.cpp + libraries/Zigbee/src/ep/ep_temperature_sensor.cpp + libraries/Zigbee/src/ep/ep_thermostat.cpp + ) + set(ARDUINO_LIBRARY_BLE_SRCS libraries/BLE/src/BLE2901.cpp libraries/BLE/src/BLE2902.cpp diff --git a/libraries/Zigbee/src/ep/ep_template.cpp b/libraries/Zigbee/src/ep/ep_template.cpp deleted file mode 100644 index 89c508ab39b..00000000000 --- a/libraries/Zigbee/src/ep/ep_template.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ep_template.h" - -ZigbeeDevice::ZigbeeDevice(uint8_t endpoint) : Zigbee_EP(endpoint) { - _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; // Change to correct device ID - - //Change to correct config - esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); - - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, // Change to correct device ID - .app_device_version = 0 - }; -} - -void ZigbeeDevice::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - // If device is looking for a endpoint, implement this function + find_cb and bind_cb callbacks - // for reference check ZigbeeSwitch::find_endpoint, ZigbeeSwitch::find_cb and ZigbeeSwitch::bind_cb - return; -} \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ep_template.h b/libraries/Zigbee/src/ep/ep_template.h deleted file mode 100644 index 47a779de794..00000000000 --- a/libraries/Zigbee/src/ep/ep_template.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Class of Zigbee On/Off Light endpoint inherited from common EP class */ - -#pragma once - -#include "Zigbee_ep.h" -#include "ha/esp_zigbee_ha_standard.h" - -class ZigbeeDevice : public Zigbee_EP { - public: - ZigbeeDevice(uint8_t endpoint); - ~ZigbeeDevice(); - - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); -}; \ No newline at end of file From 95ff61bce0c7488cf797c82499cd1e34447b1cd5 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 2 Sep 2024 09:43:30 +0200 Subject: [PATCH 17/34] Rename classes to have proper naming --- CMakeLists.txt | 18 +++--- .../Zigbee_Color_Dimmable_Light.ino | 4 +- .../Zigbee_Color_Dimmer_Switch.ino | 4 +- .../Zigbee_On_Off_Light.ino | 4 +- .../Zigbee_On_Off_Switch.ino | 4 +- .../Zigbee_Scan_Networks.ino | 2 +- .../Zigbee_Temperature_Sensor.ino | 4 +- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 4 +- .../src/{Zigbee_core.cpp => ZigbeeCore.cpp} | 62 ++++++++++--------- .../src/{Zigbee_core.h => ZigbeeCore.h} | 33 +++++----- .../src/{Zigbee_ep.cpp => ZigbeeEP.cpp} | 27 ++++---- .../Zigbee/src/{Zigbee_ep.h => ZigbeeEP.h} | 22 ++++--- ...Zigbee_handlers.cpp => ZigbeeHandlers.cpp} | 12 ++-- ...light.cpp => ZigbeeColorDimmableLight.cpp} | 4 +- ...ble_light.h => ZigbeeColorDimmableLight.h} | 4 +- ...switch.cpp => ZigbeeColorDimmerSwitch.cpp} | 4 +- ...mer_switch.h => ZigbeeColorDimmerSwitch.h} | 4 +- .../{ep_on_off_light.cpp => ZigbeeLight.cpp} | 4 +- .../ep/{ep_on_off_light.h => ZigbeeLight.h} | 4 +- ...{ep_on_off_switch.cpp => ZigbeeSwitch.cpp} | 4 +- .../ep/{ep_on_off_switch.h => ZigbeeSwitch.h} | 4 +- ...rature_sensor.cpp => ZigbeeTempSensor.cpp} | 4 +- ...emperature_sensor.h => ZigbeeTempSensor.h} | 4 +- ...ep_thermostat.cpp => ZigbeeThermostat.cpp} | 4 +- .../{ep_thermostat.h => ZigbeeThermostat.h} | 4 +- 25 files changed, 135 insertions(+), 113 deletions(-) rename libraries/Zigbee/src/{Zigbee_core.cpp => ZigbeeCore.cpp} (90%) rename libraries/Zigbee/src/{Zigbee_core.h => ZigbeeCore.h} (87%) rename libraries/Zigbee/src/{Zigbee_ep.cpp => ZigbeeEP.cpp} (85%) rename libraries/Zigbee/src/{Zigbee_ep.h => ZigbeeEP.h} (85%) rename libraries/Zigbee/src/{Zigbee_handlers.cpp => ZigbeeHandlers.cpp} (93%) rename libraries/Zigbee/src/ep/{ep_color_dimmable_light.cpp => ZigbeeColorDimmableLight.cpp} (99%) rename libraries/Zigbee/src/ep/{ep_color_dimmable_light.h => ZigbeeColorDimmableLight.h} (92%) rename libraries/Zigbee/src/ep/{ep_color_dimmer_switch.cpp => ZigbeeColorDimmerSwitch.cpp} (99%) rename libraries/Zigbee/src/ep/{ep_color_dimmer_switch.h => ZigbeeColorDimmerSwitch.h} (96%) rename libraries/Zigbee/src/ep/{ep_on_off_light.cpp => ZigbeeLight.cpp} (96%) rename libraries/Zigbee/src/ep/{ep_on_off_light.h => ZigbeeLight.h} (89%) rename libraries/Zigbee/src/ep/{ep_on_off_switch.cpp => ZigbeeSwitch.cpp} (98%) rename libraries/Zigbee/src/ep/{ep_on_off_switch.h => ZigbeeSwitch.h} (96%) rename libraries/Zigbee/src/ep/{ep_temperature_sensor.cpp => ZigbeeTempSensor.cpp} (97%) rename libraries/Zigbee/src/ep/{ep_temperature_sensor.h => ZigbeeTempSensor.h} (91%) rename libraries/Zigbee/src/ep/{ep_thermostat.cpp => ZigbeeThermostat.cpp} (98%) rename libraries/Zigbee/src/ep/{ep_thermostat.h => ZigbeeThermostat.h} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8d1d93eb63..9a858ee79cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,15 +242,15 @@ set(ARDUINO_LIBRARY_WiFiProv_SRCS libraries/WiFiProv/src/WiFiProv.cpp) set(ARDUINO_LIBRARY_Wire_SRCS libraries/Wire/src/Wire.cpp) set(ARDUINO_LIBRARY_Zigbee_SRCS - libraries/Zigbee/src/Zigbee_core.cpp - libraries/Zigbee/src/Zigbee_ep.cpp - libraries/Zigbee/src/Zigbee_handlers.cpp - libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp - libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp - libraries/Zigbee/src/ep/ep_on_off_light.cpp - libraries/Zigbee/src/ep/ep_on_off_switch.cpp - libraries/Zigbee/src/ep/ep_temperature_sensor.cpp - libraries/Zigbee/src/ep/ep_thermostat.cpp + libraries/Zigbee/src/ZigbeeCore.cpp + libraries/Zigbee/src/ZigbeeEP.cpp + libraries/Zigbee/src/ZigbeeHandlers.cpp + libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp + libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeLight.cpp + libraries/Zigbee/src/ep/ZigbeeSwitch.cpp + libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp + libraries/Zigbee/src/ep/ZigbeeThermostat.cpp ) set(ARDUINO_LIBRARY_BLE_SRCS diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index 9de7705192d..fb05c4ec9e9 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -31,8 +31,8 @@ #error "Zigbee end device mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_color_dimmable_light.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeColorDimmableLight.h" #define LED_PIN RGB_BUILTIN #define BUTTON_PIN 9 // C6/H2 Boot button diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index e56d2b6582e..61d11c2dc37 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -35,8 +35,8 @@ #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_color_dimmer_switch.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeColorDimmerSwitch.h" /* Switch configuration */ #define SWITCH_PIN 9 //Boot button for C6/H2 diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index cff9838decc..db22c3dcc8e 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -30,8 +30,8 @@ #error "Zigbee end device mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_on_off_light.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeLight.h" #define LED_PIN RGB_BUILTIN #define BUTTON_PIN 9 // C6/H2 Boot button diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index 59121eeaedf..67a3e643a1c 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -31,8 +31,8 @@ #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_on_off_switch.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeSwitch.h" #define SWITCH_ENDPOINT_NUMBER 5 diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino index d64f9eef812..f74b52de9bd 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -29,7 +29,7 @@ #error "Zigbee device mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" +#include "ZigbeeCore.h" #ifdef ZIGBEE_MODE_ZCZR zigbee_role_t role = ZIGBEE_ROUTER; // or can be ZIGBEE_COORDINATOR, but it wont scan itself diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 3a0ea1db35f..5882d78ddae 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -30,8 +30,8 @@ #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_temperature_sensor.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeTempSensor.h" #define BUTTON_PIN 9 //Boot button for C6/H2 #define TEMP_SENSOR_ENDPOINT_NUMBER 10 diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index d88f5781d99..a40987367fe 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -31,8 +31,8 @@ #error "Zigbee coordinator mode is not selected in Tools->Zigbee mode" #endif -#include "Zigbee_core.h" -#include "ep/ep_thermostat.h" +#include "ZigbeeCore.h" +#include "ep/ZigbeeThermostat.h" #define BUTTON_PIN 9 // Boot button for C6/H2 #define THERMOSTAT_ENDPOINT_NUMBER 5 diff --git a/libraries/Zigbee/src/Zigbee_core.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp similarity index 90% rename from libraries/Zigbee/src/Zigbee_core.cpp rename to libraries/Zigbee/src/ZigbeeCore.cpp index 569ac06ae83..e42c089e2f2 100644 --- a/libraries/Zigbee/src/Zigbee_core.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -1,10 +1,12 @@ -/* Zigbee Common Functions */ -#include "Zigbee_core.h" -#include "Zigbee_handlers.cpp" -#include "Arduino.h" +/* Zigbee Core Functions */ + +#include "ZigbeeCore.h" +#if SOC_IEEE802154_SUPPORTED +#include "ZigbeeHandlers.cpp" +#include "Arduino.h" -Zigbee_Core::Zigbee_Core() { +ZigbeeCore::ZigbeeCore() { _radio_config = ZIGBEE_DEFAULT_RADIO_CONFIG(); _host_config = ZIGBEE_DEFAULT_HOST_CONFIG(); _zb_ep_list = esp_zb_ep_list_create(); @@ -13,12 +15,12 @@ Zigbee_Core::Zigbee_Core() { _scan_status = ZB_SCAN_FAILED; _started = false; } -Zigbee_Core::~Zigbee_Core() {} +ZigbeeCore::~ZigbeeCore() {} //forward declaration static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message); -bool Zigbee_Core::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { +bool ZigbeeCore::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { if (!zigbeeInit(role_cfg, erase_nvs)){ return false; } @@ -26,7 +28,7 @@ bool Zigbee_Core::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { return true; } -bool Zigbee_Core::begin(zigbee_role_t role, bool erase_nvs) { +bool ZigbeeCore::begin(zigbee_role_t role, bool erase_nvs) { bool status = true; switch (role) { @@ -55,13 +57,13 @@ bool Zigbee_Core::begin(zigbee_role_t role, bool erase_nvs) { return status; } -void Zigbee_Core::addEndpoint(Zigbee_EP *ep) { +void ZigbeeCore::addEndpoint(ZigbeeEP *ep) { ep_objects.push_back(ep); log_d("Endpoint: %d, Device ID: 0x%04x", ep->_endpoint, ep->_device_id); - //Register clusters and ep_list to the Zigbee_Core class's ep_list + //Register clusters and ep_list to the ZigbeeCore class's ep_list if (ep->_ep_config.endpoint == 0 || ep->_cluster_list == nullptr) { - log_e("Endpoint config or Cluster list is not initialized, EP not added to Zigbee_Core's EP list"); + log_e("Endpoint config or Cluster list is not initialized, EP not added to ZigbeeCore's EP list"); return; } @@ -75,7 +77,7 @@ static void esp_zb_task(void *pvParameters) { } // Zigbee core init function -bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { +bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { // Zigbee platform configuration esp_zb_platform_config_t platform_config = { .radio_config = _radio_config, @@ -105,7 +107,7 @@ bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { //print the list of Zigbee EPs from ep_objects log_i("List of registered Zigbee EPs:"); - for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { + for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); } } @@ -128,27 +130,27 @@ bool Zigbee_Core::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { return true; } -void Zigbee_Core::setRadioConfig(esp_zb_radio_config_t config) { +void ZigbeeCore::setRadioConfig(esp_zb_radio_config_t config) { _radio_config = config; } -esp_zb_radio_config_t Zigbee_Core::getRadioConfig() { +esp_zb_radio_config_t ZigbeeCore::getRadioConfig() { return _radio_config; } -void Zigbee_Core::setHostConfig(esp_zb_host_config_t config) { +void ZigbeeCore::setHostConfig(esp_zb_host_config_t config) { _host_config = config; } -esp_zb_host_config_t Zigbee_Core::getHostConfig() { +esp_zb_host_config_t ZigbeeCore::getHostConfig() { return _host_config; } -void Zigbee_Core::setPrimaryChannelMask(uint32_t mask) { +void ZigbeeCore::setPrimaryChannelMask(uint32_t mask) { _primary_channel_mask = mask; } -void Zigbee_Core::setRebootOpenNetwork(uint8_t time) { +void ZigbeeCore::setRebootOpenNetwork(uint8_t time) { _open_network = time; } @@ -258,7 +260,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { */ // for each endpoint in the list call the find_endpoint function if not bounded or allowed to bind multiple devices - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (!(*it)->_is_bound || (*it)->_allow_multiple_binding) { (*it)->find_endpoint(&cmd_req); } @@ -280,16 +282,16 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } -void Zigbee_Core::factoryReset() { +void ZigbeeCore::factoryReset() { log_v("Factory reseting Zigbee stack, device will reboot"); esp_zb_factory_reset(); } -bool Zigbee_Core::isStarted() { +bool ZigbeeCore::isStarted() { return _started; } -void Zigbee_Core::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor){ +void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor){ log_v("Zigbee network scan complete"); if(zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_v("Found %d networks", count); @@ -310,7 +312,7 @@ void Zigbee_Core::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t c } } -void Zigbee_Core::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { +void ZigbeeCore::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { if(!_started) { log_e("Zigbee stack is not started, cannot scan networks"); return; @@ -320,15 +322,15 @@ void Zigbee_Core::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { _scan_status = ZB_SCAN_RUNNING; } -int16_t Zigbee_Core::scanComplete(){ +int16_t ZigbeeCore::scanComplete(){ return _scan_status; } -zigbee_scan_result_t* Zigbee_Core::getScanResult() { +zigbee_scan_result_t* ZigbeeCore::getScanResult() { return _scan_result; } -void Zigbee_Core::scanDelete() { +void ZigbeeCore::scanDelete() { if (_scan_result != nullptr) { free(_scan_result); _scan_result = nullptr; @@ -337,7 +339,7 @@ void Zigbee_Core::scanDelete() { } // Function to convert enum value to string -const char* Zigbee_Core::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { +const char* ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { switch (deviceId) { case ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID: return "General On/Off switch"; case ESP_ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID: return "Level Control Switch"; @@ -381,4 +383,6 @@ const char* Zigbee_Core::getDeviceTypeString(esp_zb_ha_standard_devices_t device } } -Zigbee_Core Zigbee = Zigbee_Core(); +ZigbeeCore Zigbee = ZigbeeCore(); + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/Zigbee_core.h b/libraries/Zigbee/src/ZigbeeCore.h similarity index 87% rename from libraries/Zigbee/src/Zigbee_core.h rename to libraries/Zigbee/src/ZigbeeCore.h index 4384e2877a7..beeafb2225d 100644 --- a/libraries/Zigbee/src/Zigbee_core.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -2,12 +2,15 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "esp_zigbee_core.h" #include "zdo/esp_zigbee_zdo_common.h" #include #include -#include "Zigbee_ep.h" -class Zigbee_EP; +#include "ZigbeeEP.h" +class ZigbeeEP; typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtrArg)(void *); @@ -28,10 +31,10 @@ typedef enum { } zigbee_role_t; // default Zigbee configuration for each role -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define MAX_CHILDREN 10 +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define MAX_CHILDREN 10 #define ZB_SCAN_RUNNING (-1) #define ZB_SCAN_FAILED (-2) @@ -51,7 +54,7 @@ typedef enum { #define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, \ .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ .nwk_cfg = { \ .zczr_cfg = \ @@ -81,7 +84,7 @@ typedef enum { #define ZIGBEE_DEFAULT_HOST_CONFIG() \ { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } -class Zigbee_Core { +class ZigbeeCore { private: esp_zb_radio_config_t _radio_config; esp_zb_host_config_t _host_config; @@ -97,19 +100,19 @@ class Zigbee_Core { zigbee_role_t _role; bool _started; uint8_t _open_network; - std::list ep_objects; + std::list ep_objects; zigbee_scan_result_t *_scan_result; - Zigbee_Core(); - ~Zigbee_Core(); + ZigbeeCore(); + ~ZigbeeCore(); bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); bool isStarted(); // bool end(); - void addEndpoint(Zigbee_EP *ep); - //void removeEndpoint(Zigbee_EP *ep); + void addEndpoint(ZigbeeEP *ep); + //void removeEndpoint(ZigbeeEP *ep); void setRadioConfig(esp_zb_radio_config_t config); esp_zb_radio_config_t getRadioConfig(); @@ -132,4 +135,6 @@ class Zigbee_Core { const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); }; -extern Zigbee_Core Zigbee; +extern ZigbeeCore Zigbee; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/Zigbee_ep.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp similarity index 85% rename from libraries/Zigbee/src/Zigbee_ep.cpp rename to libraries/Zigbee/src/ZigbeeEP.cpp index f5cfcdbc4f1..b4fb8cecef5 100644 --- a/libraries/Zigbee/src/Zigbee_ep.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -1,28 +1,31 @@ /* Common Class for Zigbee End Point */ -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" + +#if SOC_IEEE802154_SUPPORTED + #include "esp_zigbee_cluster.h" -uint8_t Zigbee_EP::_endpoint = 0; -bool Zigbee_EP::_is_bound = false; -bool Zigbee_EP::_allow_multiple_binding = false; +uint8_t ZigbeeEP::_endpoint = 0; +bool ZigbeeEP::_is_bound = false; +bool ZigbeeEP::_allow_multiple_binding = false; /* Zigbee End Device Class */ -Zigbee_EP::Zigbee_EP(uint8_t endpoint) { +ZigbeeEP::ZigbeeEP(uint8_t endpoint) { _endpoint = endpoint; _ep_config.endpoint = 0; _cluster_list = nullptr; } -Zigbee_EP::~Zigbee_EP() { +ZigbeeEP::~ZigbeeEP() { } -void Zigbee_EP::setVersion(uint8_t version) { +void ZigbeeEP::setVersion(uint8_t version) { _ep_config.app_device_version = version; } -void Zigbee_EP::setManufacturerAndModel(const char *name, const char *model) { +void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) { // Convert manufacturer to ZCL string size_t length = strlen(name); if (length > 32) { @@ -59,7 +62,7 @@ void Zigbee_EP::setManufacturerAndModel(const char *name, const char *model) { // esp_zb_cluster_add_attr function } -void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { +void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { /* Read peer Manufacture Name & Model Identifier */ esp_zb_zcl_read_attr_cmd_t read_req; read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -78,7 +81,7 @@ void Zigbee_EP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) esp_zb_zcl_read_attr_cmd_req(&read_req); } -void Zigbee_EP::printBoundDevices() { +void ZigbeeEP::printBoundDevices() { log_i("Bound devices:"); for(const auto& device : _bound_devices) { log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); @@ -86,7 +89,7 @@ void Zigbee_EP::printBoundDevices() { } } -void Zigbee_EP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { +void ZigbeeEP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { zbstring_t *zbstr = (zbstring_t *)attribute->data.value; @@ -107,3 +110,5 @@ void Zigbee_EP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute free(string); } } + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/Zigbee_ep.h b/libraries/Zigbee/src/ZigbeeEP.h similarity index 85% rename from libraries/Zigbee/src/Zigbee_ep.h rename to libraries/Zigbee/src/ZigbeeEP.h index ff34783d9f5..9a2ed59710f 100644 --- a/libraries/Zigbee/src/Zigbee_ep.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -1,21 +1,23 @@ -/* Common Class for Zigbee End Device */ +/* Common Class for Zigbee End point */ #pragma once -#include "Zigbee_core.h" +#include "ZigbeeCore.h" +#if SOC_IEEE802154_SUPPORTED + #include /* Usefull defines */ -#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) +#define ZB_ARRAY_LENTH(arr) (sizeof(arr)/ sizeof(arr[0])) #define print_ieee_addr(addr) log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) #define XYZ_to_RGB(X, Y, Z, r, g, b) \ { \ r = (float)( 3.240479*(X) -1.537150*(Y) -0.498535*(Z)); \ g = (float)(-0.969256*(X) +1.875992*(Y) +0.041556*(Z)); \ b = (float)( 0.055648*(X) -0.204043*(Y) +1.057311*(Z)); \ - if(r>1){r=1;} \ - if(g>1){g=1;} \ - if(b>1){b=1;} \ + if(r > 1){r = 1;} \ + if(g > 1){g = 1;} \ + if(b > 1){b = 1;} \ } #define RGB_to_XYZ(r, g, b, X, Y, Z) \ @@ -38,10 +40,10 @@ typedef struct zb_device_params_s { } zb_device_params_t; /* Zigbee End Device Class */ -class Zigbee_EP { +class ZigbeeEP { public: - Zigbee_EP(uint8_t endpoint = 10); - ~Zigbee_EP(); + ZigbeeEP(uint8_t endpoint = 10); + ~ZigbeeEP(); // Find endpoint may be implemented by EPs virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; @@ -83,3 +85,5 @@ class Zigbee_EP { friend class ZigbeeCore; }; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/Zigbee_handlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp similarity index 93% rename from libraries/Zigbee/src/Zigbee_handlers.cpp rename to libraries/Zigbee/src/ZigbeeHandlers.cpp index f46aed3afe9..cf94a7f26f2 100644 --- a/libraries/Zigbee/src/Zigbee_handlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -1,7 +1,9 @@ /* Zigbee Common Functions */ -#include "Zigbee_core.h" +#include "ZigbeeCore.h" #include "Arduino.h" +#if SOC_IEEE802154_SUPPORTED + // forward declaration of all implemented handlers static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message); static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message); @@ -37,7 +39,7 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag ); // List through all Zigbee EPs and call the callback function, with the message - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->info.dst_endpoint == (*it)->_endpoint) { (*it)->attribute_set(message); //method zb_attribute_set_handler in the EP } @@ -57,7 +59,7 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes message->dst_endpoint, message->cluster ); // List through all Zigbee EPs and call the callback function, with the message - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->dst_endpoint == (*it)->_endpoint) { (*it)->attribute_read(message->cluster, &message->attribute); //method attribute_read must be implemented in specific EP class } @@ -77,7 +79,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster ); - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->info.dst_endpoint == (*it)->_endpoint) { esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; while (variable) { @@ -131,3 +133,5 @@ static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_m ); return ESP_OK; } + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp similarity index 99% rename from libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp rename to libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index bddbb7eac4d..6ba0e0e31ce 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmable_light.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -1,6 +1,6 @@ -#include "ep_color_dimmable_light.h" +#include "ZigbeeColorDimmableLight.h" -ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; esp_zb_color_dimmable_light_cfg_t light_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); diff --git a/libraries/Zigbee/src/ep/ep_color_dimmable_light.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h similarity index 92% rename from libraries/Zigbee/src/ep/ep_color_dimmable_light.h rename to libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h index b1f960fa429..6eb651f7aa3 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmable_light.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -2,10 +2,10 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" -class ZigbeeColorDimmableLight : public Zigbee_EP { +class ZigbeeColorDimmableLight : public ZigbeeEP { public: ZigbeeColorDimmableLight(uint8_t endpoint); ~ZigbeeColorDimmableLight(); diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp similarity index 99% rename from libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp rename to libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 47b0811ce50..11d470acbc2 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -1,9 +1,9 @@ -#include "ep_color_dimmer_switch.h" +#include "ZigbeeColorDimmerSwitch.h" // Initialize the static instance pointer ZigbeeColorDimmerSwitch* ZigbeeColorDimmerSwitch::_instance = nullptr; -ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; _instance = this; // Set the static pointer to this instance diff --git a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h similarity index 96% rename from libraries/Zigbee/src/ep/ep_color_dimmer_switch.h rename to libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index 48a02282b06..b3ca79bd2d9 100644 --- a/libraries/Zigbee/src/ep/ep_color_dimmer_switch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -2,10 +2,10 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" -class ZigbeeColorDimmerSwitch : public Zigbee_EP { +class ZigbeeColorDimmerSwitch : public ZigbeeEP { public: ZigbeeColorDimmerSwitch(uint8_t endpoint); ~ZigbeeColorDimmerSwitch(); diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp similarity index 96% rename from libraries/Zigbee/src/ep/ep_on_off_light.cpp rename to libraries/Zigbee/src/ep/ZigbeeLight.cpp index 0eea501ef47..7aab7a07631 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -1,6 +1,6 @@ -#include "ep_on_off_light.h" +#include "ZigbeeLight.h" -ZigbeeLight::ZigbeeLight(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); diff --git a/libraries/Zigbee/src/ep/ep_on_off_light.h b/libraries/Zigbee/src/ep/ZigbeeLight.h similarity index 89% rename from libraries/Zigbee/src/ep/ep_on_off_light.h rename to libraries/Zigbee/src/ep/ZigbeeLight.h index 8df9c5a06e3..21c3495083d 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_light.h +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -2,10 +2,10 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" -class ZigbeeLight : public Zigbee_EP { +class ZigbeeLight : public ZigbeeEP { public: ZigbeeLight(uint8_t endpoint); ~ZigbeeLight(); diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp similarity index 98% rename from libraries/Zigbee/src/ep/ep_on_off_switch.cpp rename to libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index d3b0ced99ef..de6a7dbde30 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -1,9 +1,9 @@ -#include "ep_on_off_switch.h" +#include "ZigbeeSwitch.h" // Initialize the static instance pointer ZigbeeSwitch* ZigbeeSwitch::_instance = nullptr; -ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; _instance = this; // Set the static pointer to this instance diff --git a/libraries/Zigbee/src/ep/ep_on_off_switch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h similarity index 96% rename from libraries/Zigbee/src/ep/ep_on_off_switch.h rename to libraries/Zigbee/src/ep/ZigbeeSwitch.h index b058402b3b2..c6698af1494 100644 --- a/libraries/Zigbee/src/ep/ep_on_off_switch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -2,10 +2,10 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" -class ZigbeeSwitch : public Zigbee_EP { +class ZigbeeSwitch : public ZigbeeEP { public: ZigbeeSwitch(uint8_t endpoint); ~ZigbeeSwitch(); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp similarity index 97% rename from libraries/Zigbee/src/ep/ep_temperature_sensor.cpp rename to libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index a3e988ae894..4f567812a0f 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -1,6 +1,6 @@ -#include "ep_temperature_sensor.h" +#include "ZigbeeTempSensor.h" -ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); diff --git a/libraries/Zigbee/src/ep/ep_temperature_sensor.h b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h similarity index 91% rename from libraries/Zigbee/src/ep/ep_temperature_sensor.h rename to libraries/Zigbee/src/ep/ZigbeeTempSensor.h index 0e92b87b095..a98823bee9f 100644 --- a/libraries/Zigbee/src/ep/ep_temperature_sensor.h +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h @@ -2,10 +2,10 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" -class ZigbeeTempSensor : public Zigbee_EP { +class ZigbeeTempSensor : public ZigbeeEP { public: ZigbeeTempSensor(uint8_t endpoint); ~ZigbeeTempSensor(); diff --git a/libraries/Zigbee/src/ep/ep_thermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp similarity index 98% rename from libraries/Zigbee/src/ep/ep_thermostat.cpp rename to libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index 69d3b26004a..ab99ea12d87 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -1,4 +1,4 @@ -#include "ep_thermostat.h" +#include "ZigbeeThermostat.h" static float zb_s16_to_temperature(int16_t value) { return 1.0 * value / 100; @@ -7,7 +7,7 @@ static float zb_s16_to_temperature(int16_t value) { // Initialize the static instance of the class ZigbeeThermostat* ZigbeeThermostat::_instance = nullptr; -ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : Zigbee_EP(endpoint) { +ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; _instance = this; // Set the static pointer to this instance diff --git a/libraries/Zigbee/src/ep/ep_thermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h similarity index 98% rename from libraries/Zigbee/src/ep/ep_thermostat.h rename to libraries/Zigbee/src/ep/ZigbeeThermostat.h index 6f32c518409..759f7ada6ba 100644 --- a/libraries/Zigbee/src/ep/ep_thermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -2,7 +2,7 @@ #pragma once -#include "Zigbee_ep.h" +#include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" //define the thermostat configuration to avoid narrowing conversion issue in zigbee-sdk @@ -26,7 +26,7 @@ .system_mode = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE, \ }, \ } -class ZigbeeThermostat : public Zigbee_EP { +class ZigbeeThermostat : public ZigbeeEP { public: ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat(); From 495a24fde3a967ff1c585fd1ff435b03b2eb2724 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:27:53 +0200 Subject: [PATCH 18/34] Add check for SOC_IEEE802154_SUPPORTED --- .../Zigbee/src/ep/ZigbeeColorDimmableLight.cpp | 5 ++++- libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h | 7 ++++++- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 2 ++ libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h | 5 +++++ libraries/Zigbee/src/ep/ZigbeeLight.cpp | 3 +++ libraries/Zigbee/src/ep/ZigbeeLight.h | 7 ++++++- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 3 +++ libraries/Zigbee/src/ep/ZigbeeSwitch.h | 14 ++++---------- libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp | 5 ++++- libraries/Zigbee/src/ep/ZigbeeTempSensor.h | 7 ++++++- libraries/Zigbee/src/ep/ZigbeeThermostat.cpp | 3 +++ libraries/Zigbee/src/ep/ZigbeeThermostat.h | 7 ++++++- 12 files changed, 52 insertions(+), 16 deletions(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index 6ba0e0e31ce..e971bdd5b10 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -1,4 +1,5 @@ #include "ZigbeeColorDimmableLight.h" +#if SOC_IEEE802154_SUPPORTED ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; @@ -147,4 +148,6 @@ void ZigbeeColorDimmableLight::setColorSaturation(uint8_t value) { void ZigbeeColorDimmableLight::setColorHue(uint8_t value) { //set color hue log_v("Function not overwritten, set color hue: %d", value); -} \ No newline at end of file +} + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h index 6eb651f7aa3..79903456a6b 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -28,4 +31,6 @@ class ZigbeeColorDimmableLight : public ZigbeeEP { private: void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; -}; \ No newline at end of file +}; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 11d470acbc2..8de20230d01 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -1,4 +1,5 @@ #include "ZigbeeColorDimmerSwitch.h" +#if SOC_IEEE802154_SUPPORTED // Initialize the static instance pointer ZigbeeColorDimmerSwitch* ZigbeeColorDimmerSwitch::_instance = nullptr; @@ -405,3 +406,4 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t } } +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index b3ca79bd2d9..9498d0e80bf 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -54,3 +57,5 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); }; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 7aab7a07631..608d2a925fa 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -1,4 +1,5 @@ #include "ZigbeeLight.h" +#if SOC_IEEE802154_SUPPORTED ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; @@ -61,3 +62,5 @@ void ZigbeeLight::setOffWaitTime(uint16_t value) { //set off wait time log_v("Function not overwritten, set off wait time: %d", value); } + +#endif //SOC_IEEE802154_SUPPORTED \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.h b/libraries/Zigbee/src/ep/ZigbeeLight.h index 21c3495083d..2ecb05e60d4 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -19,4 +22,6 @@ class ZigbeeLight : public ZigbeeEP { private: void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; -}; \ No newline at end of file +}; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index de6a7dbde30..5a3de96ca9e 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -1,4 +1,5 @@ #include "ZigbeeSwitch.h" +#if SOC_IEEE802154_SUPPORTED // Initialize the static instance pointer ZigbeeSwitch* ZigbeeSwitch::_instance = nullptr; @@ -237,3 +238,5 @@ void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, log_e("Light not bound"); } } + +#endif //SOC_IEEE802154_SUPPORTED \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h index c6698af1494..fa859952e6f 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -37,13 +40,4 @@ class ZigbeeSwitch : public ZigbeeEP { }; -//NOTE: -/* ON/OFF switch commands for light control */ -// typedef enum { -// ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID = 0x00, /*!< "Turn off" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_ID = 0x01, /*!< "Turn on" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID = 0x02, /*!< "Toggle state" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_OFF_WITH_EFFECT_ID = 0x40, /*!< "Off with effect" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_RECALL_GLOBAL_SCENE_ID = 0x41, /*!< "On with recall global scene" command. */ -// ESP_ZB_ZCL_CMD_ON_OFF_ON_WITH_TIMED_OFF_ID = 0x42, /*!< "On with timed off" command. */ -// } esp_zb_zcl_on_off_cmd_id_t; +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index 4f567812a0f..e4bba80246d 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -1,4 +1,5 @@ #include "ZigbeeTempSensor.h" +#if SOC_IEEE802154_SUPPORTED ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; @@ -86,4 +87,6 @@ void ZigbeeTempSensor::reportTemperature() { esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); esp_zb_lock_release(); log_v("Temperature report sent"); -} \ No newline at end of file +} + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h index a98823bee9f..2f15e6029f6 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -22,4 +25,6 @@ class ZigbeeTempSensor : public ZigbeeEP { // Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C) void setReporting(uint16_t min_interval, uint16_t max_interval, float delta); void reportTemperature(); -}; \ No newline at end of file +}; + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index ab99ea12d87..25312891515 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -1,4 +1,5 @@ #include "ZigbeeThermostat.h" +#if SOC_IEEE802154_SUPPORTED static float zb_s16_to_temperature(int16_t value) { return 1.0 * value / 100; @@ -193,3 +194,5 @@ void ZigbeeThermostat::temperatureMax(float temp){ void ZigbeeThermostat::temperatureTolerance(float tolerance){ log_v("Function not overwritten, temperature tolerance: %.2f °C", tolerance); } + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h index 759f7ada6ba..e39d82853e0 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -2,6 +2,9 @@ #pragma once +#include "soc/soc_caps.h" +#if SOC_IEEE802154_SUPPORTED + #include "ZigbeeEP.h" #include "ha/esp_zigbee_ha_standard.h" @@ -49,4 +52,6 @@ class ZigbeeThermostat : public ZigbeeEP { private: void attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override; -}; \ No newline at end of file +}; + +#endif //SOC_IEEE802154_SUPPORTED From b000bea136e8956da8ae7b534147342ed9ecbba3 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:39:02 +0200 Subject: [PATCH 19/34] Ignore false positive unused variable/function --- libraries/Zigbee/src/ZigbeeEP.cpp | 5 +++++ libraries/Zigbee/src/ZigbeeHandlers.cpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index b4fb8cecef5..2a02f3e5627 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -81,6 +81,9 @@ void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { esp_zb_zcl_read_attr_cmd_req(&read_req); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + void ZigbeeEP::printBoundDevices() { log_i("Bound devices:"); for(const auto& device : _bound_devices) { @@ -89,6 +92,8 @@ void ZigbeeEP::printBoundDevices() { } } +#pragma GCC diagnostic pop + void ZigbeeEP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index cf94a7f26f2..be811ece81d 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -11,6 +11,10 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message); static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" + // Zigbee action handlers static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; @@ -25,6 +29,8 @@ static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, return ret; } +#pragma GCC diagnostic pop + static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { if (!message) { log_e("Empty message"); From 96c18c49f4c3db2e51ce4341cf915bd3d9251db5 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 2 Sep 2024 12:27:08 +0200 Subject: [PATCH 20/34] Fix compilation errors in examples --- .../examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino | 2 +- .../examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino | 2 +- .../Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index 67a3e643a1c..89cdd2b7256 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -192,6 +192,6 @@ void loop() { static uint32_t last_print = 0; if (millis() - last_print > 10000) { last_print = millis(); - zbSwitch.printBoundLights(); + zbSwitch.printBoundDevices(); } } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino index f74b52de9bd..0a9f8b234c0 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -52,7 +52,7 @@ void printScannedNetworks(uint16_t networksFound) { Serial.print(" | "); Serial.printf("0x%04hx", scan_result[i].short_pan_id); Serial.print(" | "); - Serial.printf("%2ld", scan_result[i].logic_channel); + Serial.printf("%2d", scan_result[i].logic_channel); Serial.print(" | "); Serial.printf("%-14.14s", scan_result[i].permit_joining ? "Yes" : "No"); Serial.print(" | "); diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index a40987367fe..13aa7b14cf9 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -125,6 +125,6 @@ void loop() { if (millis() - last_print > 10000) { last_print = millis(); int temp_percent = (int)((zbThermostat.temperature - zbThermostat.min_temperature) / (zbThermostat.max_temperature - zbThermostat.min_temperature) * 100); - Serial.printf("Temperature: %.2f°C (%d '%')\n", zbThermostat.temperature, temp_percent); + Serial.printf("Temperature: %.2f°C (%d %%)\n", zbThermostat.temperature, temp_percent); } } From 4edfb8c7827f597d05cbcd01d74f84c2620cc891 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:01:09 +0200 Subject: [PATCH 21/34] Fill keyworkds.txt, remove unnecessary defines --- libraries/Zigbee/keywords.txt | 51 +++++++++++++++---- libraries/Zigbee/src/ZigbeeCore.h | 27 +++------- libraries/Zigbee/src/ZigbeeEP.h | 5 +- .../src/ep/ZigbeeColorDimmableLight.cpp | 2 +- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 2 +- 5 files changed, 54 insertions(+), 33 deletions(-) diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt index da8f18cc2f1..86809209eb5 100644 --- a/libraries/Zigbee/keywords.txt +++ b/libraries/Zigbee/keywords.txt @@ -2,26 +2,59 @@ # Syntax Coloring Map For Zigbee ####################################### -####################################### -# Library (KEYWORD3) -####################################### - -#TODO: - ####################################### # Datatypes (KEYWORD1) ####################################### -#TODO: +ZigbeeCore KEYWORD1 +Zigbee KEYWORD1 +ZigbeeEP KEYWORD1 +ZigbeeLight KEYWORD1 +ZigbeeSwitch KEYWORD1 +ZigbeeColorDimmableLight KEYWORD1 +ZigbeeColorDimmerSwitch KEYWORD1 +ZigbeeTempSensor KEYWORD1 +ZigbeeThermostat KEYWORD1 +zigbee_role_t KEYWORD1 +zbstring_t KEYWORD1 +zb_device_params_t KEYWORD1 +zigbee_scan_result_t KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### -#TODO: +isStarted KEYWORD2 +addEndpoint KEYWORD2 +setRadioConfig KEYWORD2 +setHostConfig KEYWORD2 +getRadioConfig KEYWORD2 +getHostConfig KEYWORD2 +setPrimaryChannelMask KEYWORD2 +setRebootOpenNetwork KEYWORD2 +scanNetworks KEYWORD2 +scanComplete KEYWORD2 +getScanResult KEYWORD2 +scanDelete KEYWORD2 +factoryReset KEYWORD2 +setVersion KEYWORD2 +setManufacturerAndModel KEYWORD2 +is_bound KEYWORD2 +printBoundDevices KEYWORD2 +allowMultipleBinding KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### -#TODO: \ No newline at end of file +ZIGBEE_COORDINATOR LITERAL1 +ZIGBEE_ROUTER LITERAL1 +ZIGBEE_END_DEVICE LITERAL1 +ZIGBEE_DEFAULT_ED_CONFIG LITERAL1 +ZIGBEE_DEFAULT_ROUTER_CONFIG LITERAL1 +ZIGBEE_DEFAULT_COORDINATOR_CONFIG LITERAL1 +ZIGBEE_DEFAULT_RADIO_CONFIG LITERAL1 +ZIGBEE_DEFAULT_HOST_CONFIG LITERAL1 +ZB_ARRAY_LENTH LITERAL1 +XYZ_TO_RGB LITERAL1 +RGB_TO_XYZ LITERAL1 diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index beeafb2225d..89466a0579b 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -15,12 +15,6 @@ class ZigbeeEP; typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtrArg)(void *); -// structure to store callback function and argument -typedef struct { - voidFuncPtr fn; - void *arg; -} zigbee_cb_t; - typedef esp_zb_network_descriptor_t zigbee_scan_result_t; // enum of Zigbee Roles @@ -30,24 +24,18 @@ typedef enum { ZIGBEE_END_DEVICE = 2 } zigbee_role_t; -// default Zigbee configuration for each role -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN -#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ -#define MAX_CHILDREN 10 - #define ZB_SCAN_RUNNING (-1) #define ZB_SCAN_FAILED (-2) #define ZIGBEE_DEFAULT_ED_CONFIG() \ { \ .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ - .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .install_code_policy = false, \ .nwk_cfg = { \ .zed_cfg = \ { \ - .ed_timeout = ED_AGING_TIMEOUT, \ - .keep_alive = ED_KEEP_ALIVE, \ + .ed_timeout = ESP_ZB_ED_AGING_TIMEOUT_64MIN, \ + .keep_alive = 3000, \ }, \ }, \ } @@ -55,11 +43,11 @@ typedef enum { #define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ { \ .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, \ - .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .install_code_policy = false, \ .nwk_cfg = { \ .zczr_cfg = \ { \ - .max_children = MAX_CHILDREN, \ + .max_children = 10, \ }, \ } \ } @@ -68,11 +56,11 @@ typedef enum { #define ZIGBEE_DEFAULT_COORDINATOR_CONFIG() \ { \ .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ - .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .install_code_policy = false, \ .nwk_cfg = { \ .zczr_cfg = \ { \ - .max_children = MAX_CHILDREN, \ + .max_children = 10, \ }, \ } \ } @@ -91,7 +79,6 @@ class ZigbeeCore { uint32_t _primary_channel_mask; int16_t _scan_status; - bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index 9a2ed59710f..7b9b8198d74 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -10,7 +10,7 @@ /* Usefull defines */ #define ZB_ARRAY_LENTH(arr) (sizeof(arr)/ sizeof(arr[0])) #define print_ieee_addr(addr) log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) -#define XYZ_to_RGB(X, Y, Z, r, g, b) \ +#define XYZ_TO_RGB(X, Y, Z, r, g, b) \ { \ r = (float)( 3.240479*(X) -1.537150*(Y) -0.498535*(Z)); \ g = (float)(-0.969256*(X) +1.875992*(Y) +0.041556*(Z)); \ @@ -20,7 +20,7 @@ if(b > 1){b = 1;} \ } -#define RGB_to_XYZ(r, g, b, X, Y, Z) \ +#define RGB_TO_XYZ(r, g, b, X, Y, Z) \ { \ X = (float)(0.412453*(r) + 0.357580*(g) + 0.180423*(b)); \ Y = (float)(0.212671*(r) + 0.715160*(g) + 0.072169*(b)); \ @@ -67,6 +67,7 @@ class ZigbeeEP { static bool is_bound() { return _is_bound; } void printBoundDevices(); + //TODO: getBoundDevices() method to recieve list of bound devices static bool _allow_multiple_binding; static void allowMultipleBinding(bool bind) { _allow_multiple_binding = bind; } diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index e971bdd5b10..c9deb8693b5 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -34,7 +34,7 @@ void ZigbeeColorDimmableLight::calculateRGB( uint16_t x, uint16_t y, uint8_t &re float color_X = color_x / color_y; float color_Z = (1 - color_x - color_y) / color_y; - XYZ_to_RGB(color_X, 1, color_Z, r, g, b); + XYZ_TO_RGB(color_X, 1, color_Z, r, g, b); red = (uint8_t)(r * (float)255); green = (uint8_t)(g * (float)255); diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 8de20230d01..6a14b7e2b66 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -26,7 +26,7 @@ void ZigbeeColorDimmerSwitch::calculateXY(uint8_t red, uint8_t green, uint8_t bl float b = (float)blue / 255.0f; float X, Y, Z; - RGB_to_XYZ(r, g, b, X, Y, Z); + RGB_TO_XYZ(r, g, b, X, Y, Z); // Convert XYZ to xy chromaticity coordinates float color_x = X / (X + Y + Z); From 6e220ecff9f87717c4f217cce1f2569009adc83a Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:41:37 +0200 Subject: [PATCH 22/34] Rename methods, variables + make private/protected --- .../Zigbee_Color_Dimmer_Switch.ino | 2 +- .../Zigbee_On_Off_Switch.ino | 2 +- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 2 +- libraries/Zigbee/keywords.txt | 45 ++++++++++++++++++ libraries/Zigbee/src/ZigbeeCore.cpp | 22 ++++----- libraries/Zigbee/src/ZigbeeCore.h | 23 ++++++---- libraries/Zigbee/src/ZigbeeEP.cpp | 2 +- libraries/Zigbee/src/ZigbeeEP.h | 46 ++++++++++--------- libraries/Zigbee/src/ZigbeeHandlers.cpp | 14 +++--- .../src/ep/ZigbeeColorDimmableLight.cpp | 2 +- .../Zigbee/src/ep/ZigbeeColorDimmableLight.h | 5 +- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 14 +++--- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.h | 15 +++--- libraries/Zigbee/src/ep/ZigbeeLight.cpp | 2 +- libraries/Zigbee/src/ep/ZigbeeLight.h | 2 +- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 10 ++-- libraries/Zigbee/src/ep/ZigbeeSwitch.h | 12 ++--- libraries/Zigbee/src/ep/ZigbeeThermostat.cpp | 14 +++--- libraries/Zigbee/src/ep/ZigbeeThermostat.h | 15 +++--- 19 files changed, 150 insertions(+), 99 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index 61d11c2dc37..e611e6d9857 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -70,7 +70,7 @@ void setup() { Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while(!zbSwitch.is_bound()) + while(!zbSwitch.isBound()) { Serial.printf("."); delay(500); diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index 89cdd2b7256..fb36459e1f9 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -146,7 +146,7 @@ void setup() { Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while(!zbSwitch.is_bound()) + while(!zbSwitch.isBound()) { Serial.printf("."); delay(500); diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 13aa7b14cf9..1c100ad6d46 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -95,7 +95,7 @@ void setup() { Serial.println("Waiting for Temperature sensor to bound to the switch"); //Wait for switch to bound to a light: - while(!zbThermostat.is_bound()) + while(!zbThermostat.isBound()) { Serial.printf("."); delay(500); diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt index 86809209eb5..53ce5fffe2a 100644 --- a/libraries/Zigbee/keywords.txt +++ b/libraries/Zigbee/keywords.txt @@ -6,15 +6,20 @@ # Datatypes (KEYWORD1) ####################################### +# Base Classes ZigbeeCore KEYWORD1 Zigbee KEYWORD1 ZigbeeEP KEYWORD1 + +# Endpoint Classes ZigbeeLight KEYWORD1 ZigbeeSwitch KEYWORD1 ZigbeeColorDimmableLight KEYWORD1 ZigbeeColorDimmerSwitch KEYWORD1 ZigbeeTempSensor KEYWORD1 ZigbeeThermostat KEYWORD1 + +# Other zigbee_role_t KEYWORD1 zbstring_t KEYWORD1 zb_device_params_t KEYWORD1 @@ -24,6 +29,7 @@ zigbee_scan_result_t KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### +# ZigbeeCore isStarted KEYWORD2 addEndpoint KEYWORD2 setRadioConfig KEYWORD2 @@ -37,12 +43,51 @@ scanComplete KEYWORD2 getScanResult KEYWORD2 scanDelete KEYWORD2 factoryReset KEYWORD2 + +# Common ZigbeeEP setVersion KEYWORD2 setManufacturerAndModel KEYWORD2 is_bound KEYWORD2 printBoundDevices KEYWORD2 allowMultipleBinding KEYWORD2 +# ZigbeeLight + ZigbeeColorDimmableLight +setOnOff KEYWORD2 +sceneControl KEYWORD2 +setOnOffTime KEYWORD2 +setOffWaitTime KEYWORD2 +setLevel KEYWORD2 +setColor KEYWORD2 +setColorSaturation KEYWORD2 +setColorHue KEYWORD2 + +# ZigbeeSwitch + ZigbeeColorDimmerSwitch +lightToggle KEYWORD2 +lightOn KEYWORD2 +lightOff KEYWORD2 +lightOffWithEffect KEYWORD2 +lightOnWithTimedOff KEYWORD2 +lightOnWithSceneRecall KEYWORD2 +setLightLevel KEYWORD2 +setLightColor KEYWORD2 +setLightColorSaturation KEYWORD2 +setLightColorHue KEYWORD2 + +# ZigbeeTempSensor +setTemperature KEYWORD2 +setMinMaxValue KEYWORD2 +setTolerance KEYWORD2 +setReporting KEYWORD2 +reportTemperature KEYWORD2 + +# ZigbeeThermostat +temperatureRead KEYWORD2 +temperatureMin KEYWORD2 +temperatureMax KEYWORD2 +temperatureTolerance KEYWORD2 +getTemperature KEYWORD2 +setTemperatureReporting KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index e42c089e2f2..789955f52aa 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -178,7 +178,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); if (esp_zb_bdb_is_factory_new()) { // Role specific code - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { log_i("Start network formation"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_FORMATION); } else { @@ -190,7 +190,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } else { log_i("Device rebooted"); Zigbee._started = true; - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { log_i("Openning network for joining for %d seconds", Zigbee._open_network); esp_zb_bdb_open_network(Zigbee._open_network); } @@ -201,7 +201,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { esp_zb_ieee_addr_t extended_pan_id; esp_zb_get_extended_pan_id(extended_pan_id); @@ -219,7 +219,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { break; case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device Zigbee._started = true; - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { log_i("Network steering started"); } @@ -240,7 +240,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } break; case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); esp_zb_zdo_match_desc_req_param_t cmd_req; @@ -259,16 +259,16 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { Bit 7 – Reserved */ - // for each endpoint in the list call the find_endpoint function if not bounded or allowed to bind multiple devices + // for each endpoint in the list call the findEndpoint function if not bounded or allowed to bind multiple devices for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (!(*it)->_is_bound || (*it)->_allow_multiple_binding) { - (*it)->find_endpoint(&cmd_req); + if (!(*it)->isBound() || (*it)->epAllowMultipleBinding()) { + (*it)->findEndpoint(&cmd_req); } } } break; case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator - if ((zigbee_role_t)Zigbee._role == ZIGBEE_COORDINATOR) { + if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { log_i("Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)); @@ -287,10 +287,6 @@ void ZigbeeCore::factoryReset() { esp_zb_factory_reset(); } -bool ZigbeeCore::isStarted() { - return _started; -} - void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor){ log_v("Zigbee network scan complete"); if(zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index 89466a0579b..0e322b066ea 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -78,26 +78,31 @@ class ZigbeeCore { esp_zb_host_config_t _host_config; uint32_t _primary_channel_mask; int16_t _scan_status; - - bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); - static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); - - public: + esp_zb_ep_list_t *_zb_ep_list; zigbee_role_t _role; bool _started; + uint8_t _open_network; - std::list ep_objects; zigbee_scan_result_t *_scan_result; + bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); + const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); + + public: ZigbeeCore(); ~ZigbeeCore(); + std::list ep_objects; + bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); - bool isStarted(); // bool end(); + bool isStarted() { return _started; } + zigbee_role_t getRole() { return _role; } + void addEndpoint(ZigbeeEP *ep); //void removeEndpoint(ZigbeeEP *ep); @@ -119,7 +124,9 @@ class ZigbeeCore { void factoryReset(); - const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); + // Friend function declaration to allow access to private members + friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct); + }; extern ZigbeeCore Zigbee; diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 2a02f3e5627..84b2f30a297 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -94,7 +94,7 @@ void ZigbeeEP::printBoundDevices() { #pragma GCC diagnostic pop -void ZigbeeEP::readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { +void ZigbeeEP::zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { zbstring_t *zbstr = (zbstring_t *)attribute->data.value; diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index 7b9b8198d74..8eb7bdc554a 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -45,46 +45,50 @@ class ZigbeeEP { ZigbeeEP(uint8_t endpoint = 10); ~ZigbeeEP(); - // Find endpoint may be implemented by EPs - virtual void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; - - static uint8_t _endpoint; - esp_zb_ha_standard_devices_t _device_id; //type of device - - esp_zb_endpoint_config_t _ep_config; - esp_zb_cluster_list_t *_cluster_list; - std::list _bound_devices; - - static bool _is_bound; - // Set ep config and cluster list - void set_ep_config(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { + void setEpConfig(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { _ep_config = ep_config; _cluster_list = cluster_list; } void setVersion(uint8_t version); + uint8_t getEndpoint() { return _endpoint; } - static bool is_bound() { return _is_bound; } void printBoundDevices(); - //TODO: getBoundDevices() method to recieve list of bound devices + std::list getBoundDevices() const { return _bound_devices;} - static bool _allow_multiple_binding; + static bool isBound() { return _is_bound; } static void allowMultipleBinding(bool bind) { _allow_multiple_binding = bind; } // Manufacturer name and model implemented void setManufacturerAndModel(const char *name, const char *model); void readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr); - + // Methods to be implemented by EPs to recieve manufacturer and model name virtual void readManufacturer(char* manufacturer) {}; virtual void readModel(char* model) {}; + bool epAllowMultipleBinding() { return _allow_multiple_binding; } + + // findEndpoind may be implemented by EPs to find and bind devices + virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; + //list of all handlers function calls, to be overide by EPs implementation - virtual void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) {}; - virtual void attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {}; - virtual void readBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented + 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 zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented + + private: + static bool _allow_multiple_binding; + + protected: + static uint8_t _endpoint; + esp_zb_ha_standard_devices_t _device_id; + esp_zb_endpoint_config_t _ep_config; + esp_zb_cluster_list_t *_cluster_list; + static bool _is_bound; + std::list _bound_devices; - friend class ZigbeeCore; + friend class ZigbeeCore; }; #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index be811ece81d..2328dc1ea36 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -46,8 +46,8 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag // List through all Zigbee EPs and call the callback function, with the message for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (message->info.dst_endpoint == (*it)->_endpoint) { - (*it)->attribute_set(message); //method zb_attribute_set_handler in the EP + if (message->info.dst_endpoint == (*it)->getEndpoint()){ + (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class } } return ESP_OK; @@ -66,8 +66,8 @@ 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::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (message->dst_endpoint == (*it)->_endpoint) { - (*it)->attribute_read(message->cluster, &message->attribute); //method attribute_read must be implemented in specific EP class + if (message->dst_endpoint == (*it)->getEndpoint()) { + (*it)->zbAttributeRead(message->cluster, &message->attribute); //method zbAttributeRead must be implemented in specific EP class } } return ESP_OK; @@ -86,7 +86,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re ); for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (message->info.dst_endpoint == (*it)->_endpoint) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; while (variable) { log_v( @@ -95,10 +95,10 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re ); if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - (*it)->readBasicCluster(message->info.cluster, &variable->attribute); //method readBasicCluster implemented in the common EP class + (*it)->zbReadBasicCluster(message->info.cluster, &variable->attribute); //method zbReadBasicCluster implemented in the common EP class } else { - (*it)->attribute_read(message->info.cluster, &variable->attribute); //method attribute_read must be implemented in specific EP class + (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class } } variable = variable->next; diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index c9deb8693b5..16f264a8e5a 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -42,7 +42,7 @@ void ZigbeeColorDimmableLight::calculateRGB( uint16_t x, uint16_t y, uint8_t &re } //set attribude method -> methon overriden in child class -void ZigbeeColorDimmableLight::attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) { +void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h index 79903456a6b..be69f28a72d 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -16,7 +16,7 @@ class ZigbeeColorDimmableLight : public ZigbeeEP { uint8_t getCurrentLevel(); uint16_t getCurrentColorX(); uint16_t getCurrentColorY(); - void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); + // methods to be implemented by the user by overwritting them virtual void setOnOff(bool value); @@ -29,7 +29,8 @@ class ZigbeeColorDimmableLight : public ZigbeeEP { virtual void setColorHue(uint8_t value); private: - void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); }; diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 6a14b7e2b66..420053e3d81 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -37,7 +37,7 @@ void ZigbeeColorDimmerSwitch::calculateXY(uint8_t red, uint8_t green, uint8_t bl y = (uint16_t)(color_y * 65535.0f); } -void ZigbeeColorDimmerSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { +void ZigbeeColorDimmerSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Bound successfully!"); if (user_ctx) { @@ -54,7 +54,7 @@ void ZigbeeColorDimmerSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user } } -void ZigbeeColorDimmerSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { +void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); esp_zb_zdo_bind_req_param_t bind_req; @@ -70,20 +70,20 @@ void ZigbeeColorDimmerSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t a bind_req.dst_endp = endpoint; bind_req.req_dst_addr = esp_zb_get_short_address(); log_v("Try to bind on/off control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; log_v("Try to bind level control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; log_v("Try to bind color control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); } else { log_v("No color dimmable light endpoint found"); } } // find on_off light endpoint -void ZigbeeColorDimmerSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { +void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL}; esp_zb_zdo_match_desc_req_param_t color_dimmable_light_req = { @@ -94,7 +94,7 @@ void ZigbeeColorDimmerSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *c .num_out_clusters = 3, .cluster_list = cluster_list, }; - esp_zb_zdo_match_cluster(&color_dimmable_light_req, find_cb, NULL); + esp_zb_zdo_match_cluster(&color_dimmable_light_req, findCb, NULL); } // Methods to control the light diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index 9498d0e80bf..fb75e2125c8 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -13,11 +13,6 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { ZigbeeColorDimmerSwitch(uint8_t endpoint); ~ZigbeeColorDimmerSwitch(); - // save instance of the class in order to use it in static functions - static ZigbeeColorDimmerSwitch* _instance; - - void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); - // methods to control the color dimmable light void lightToggle(); void lightToggle(uint16_t group_addr); @@ -52,10 +47,14 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { void setLightColorHue(uint8_t value, uint8_t endpoint, uint16_t short_addr); private: - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + // save instance of the class in order to use it in static functions + static ZigbeeColorDimmerSwitch* _instance; + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + + void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); }; #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 608d2a925fa..5932a0c6e99 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -15,7 +15,7 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { } //set attribude method -> methon overriden in child class -void ZigbeeLight::attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) { +void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.h b/libraries/Zigbee/src/ep/ZigbeeLight.h index 2ecb05e60d4..c98e15023fd 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -20,7 +20,7 @@ class ZigbeeLight : public ZigbeeEP { virtual void setOffWaitTime(uint16_t value); private: - void attribute_set(const esp_zb_zcl_set_attr_value_message_t *message) override; + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; }; diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 5a3de96ca9e..e1c875d9977 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -19,7 +19,7 @@ ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { }; } -void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { +void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Bound successfully!"); if (user_ctx) { @@ -35,7 +35,7 @@ void ZigbeeSwitch::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { } } -void ZigbeeSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { +void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); esp_zb_zdo_bind_req_param_t bind_req; @@ -51,14 +51,14 @@ void ZigbeeSwitch::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_ bind_req.dst_endp = endpoint; bind_req.req_dst_addr = esp_zb_get_short_address(); log_i("Try to bind On/Off"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)light); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); } else { log_d("No light endpoint found"); } } // find on_off light endpoint -void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { +void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF}; esp_zb_zdo_match_desc_req_param_t on_off_req = { .dst_nwk_addr = cmd_req->dst_nwk_addr, @@ -69,7 +69,7 @@ void ZigbeeSwitch::find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { .cluster_list = cluster_list, }; - esp_zb_zdo_match_cluster(&on_off_req, find_cb, NULL); + esp_zb_zdo_match_cluster(&on_off_req, findCb, NULL); } // Methods to control the light diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h index fa859952e6f..322c7b7443b 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -13,9 +13,6 @@ class ZigbeeSwitch : public ZigbeeEP { ZigbeeSwitch(uint8_t endpoint); ~ZigbeeSwitch(); - // save instance of the class in order to use it in static functions - static ZigbeeSwitch* _instance; - // methods to control the on/off light void lightToggle(); void lightToggle(uint16_t group_addr); @@ -34,9 +31,12 @@ class ZigbeeSwitch : public ZigbeeEP { void lightOnWithSceneRecall(); private: - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + // save instance of the class in order to use it in static functions + static ZigbeeSwitch* _instance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); }; diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index 25312891515..24159a60bdc 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -33,7 +33,7 @@ ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : ZigbeeEP(endpoint) { }; } -void ZigbeeThermostat::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { +void ZigbeeThermostat::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { if (user_ctx) { zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; @@ -51,7 +51,7 @@ void ZigbeeThermostat::bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { } } -void ZigbeeThermostat::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { +void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Found temperature sensor"); esp_zb_zdo_bind_req_param_t bind_req; @@ -78,7 +78,7 @@ void ZigbeeThermostat::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, ui bind_req.dst_endp = _endpoint; log_i("Request temperature sensor to bind us"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, NULL); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); /* 2. Send binding request to self */ bind_req.req_dst_addr = esp_zb_get_short_address(); @@ -94,20 +94,20 @@ void ZigbeeThermostat::find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, ui bind_req.dst_endp = endpoint; log_i("Bind temperature sensor"); - esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *)sensor); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)sensor); } } -void ZigbeeThermostat::find_endpoint(esp_zb_zdo_match_desc_req_param_t *param) { +void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) { uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; param->num_in_clusters = 1; param->num_out_clusters = 0; param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, find_cb, NULL); + esp_zb_zdo_match_cluster(param, findCb, NULL); } -void ZigbeeThermostat::attribute_read(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) { 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; diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h index e39d82853e0..4fd38deca7b 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -34,13 +34,6 @@ class ZigbeeThermostat : public ZigbeeEP { ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat(); - // save instance of the class in order to use it in static functions - static ZigbeeThermostat* _instance; - - void find_endpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - virtual void temperatureRead(float temp); virtual void temperatureMin(float temp); virtual void temperatureMax(float temp); @@ -50,8 +43,14 @@ class ZigbeeThermostat : public ZigbeeEP { void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); private: - void attribute_read(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override; + // save instance of the class in order to use it in static functions + static ZigbeeThermostat* _instance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(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; }; #endif //SOC_IEEE802154_SUPPORTED From 4eb37aa5983125ef7cbfad1c5213071725b6e626 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:46:34 +0200 Subject: [PATCH 23/34] Remove unnecesary defaults defines --- libraries/Zigbee/src/ZigbeeCore.cpp | 4 ++-- libraries/Zigbee/src/ZigbeeCore.h | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index 789955f52aa..c2909209401 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -7,8 +7,8 @@ #include "Arduino.h" ZigbeeCore::ZigbeeCore() { - _radio_config = ZIGBEE_DEFAULT_RADIO_CONFIG(); - _host_config = ZIGBEE_DEFAULT_HOST_CONFIG(); + _radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; // Use the native 15.4 radio + _host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; // Disable host connection _zb_ep_list = esp_zb_ep_list_create(); _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; _open_network = 0; diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index 0e322b066ea..79df4c61193 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -65,13 +65,6 @@ typedef enum { } \ } -// default Zigbee radio and host configuration -#define ZIGBEE_DEFAULT_RADIO_CONFIG() \ - { .radio_mode = ZB_RADIO_MODE_NATIVE, } - -#define ZIGBEE_DEFAULT_HOST_CONFIG() \ - { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - class ZigbeeCore { private: esp_zb_radio_config_t _radio_config; From 59335bb08a1a53d38ba0b45be567570d991df9b6 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:57:05 +0200 Subject: [PATCH 24/34] Remove outdated comments --- libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 1 - libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 420053e3d81..5c397cf9265 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -45,7 +45,6 @@ void ZigbeeColorDimmerSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ //Read manufacturer and model automatically after successful bind _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - //TODO: call user method to notify about the light and pass all the info ???? _instance->_bound_devices.push_back(light); } _is_bound = true; diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index e1c875d9977..8b071a44e8e 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -27,7 +27,6 @@ void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { //Read manufacturer and model automatically after successful bind _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - //TODO: call user method to notify about the light and pass all the info ???? _instance->_bound_devices.push_back(light); //free(light); } From 2fdeef7f958455f45f56963d5e02ef5c5ea7b5a4 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:24:22 +0200 Subject: [PATCH 25/34] Update Scan networks Readme --- .../Zigbee/examples/Zigbee_Scan_Networks/README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md index dbdbb7ce554..51939a84b55 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md @@ -11,7 +11,17 @@ Currently, this example supports the following targets. ## Example Output -//TODO: + Setup done + Loop running... + Loop running... + Loop running... + Loop running... + + Scan done + 2 networks found: + Nr | PAN ID | CH | Permit Joining | Router Capacity | End Device Capacity | Extended PAN ID + 1 | 0xe6f0 | 14 | Yes | Yes | Yes | f0:f5:bd:ff:fe:02:3f:24 + 2 | 0xa9bb | 24 | No | Yes | Yes | 60:55:f9:00:00:f7:52:d0 ## Hardware Required From 9a86d6ff90eb9a016fd9c903998a0e79ab7aabee Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:47:24 +0200 Subject: [PATCH 26/34] fix(example): Use proper naming of func and variables --- .../Zigbee_On_Off_Switch.ino | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index fb36459e1f9..27896f15f2b 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -37,7 +37,7 @@ #define SWITCH_ENDPOINT_NUMBER 5 /* Switch configuration */ -#define GPIO_INPUT_IO_TOGGLE_SWITCH GPIO_NUM_9 +#define GPIO_INPUT_IO_TOGGLE_SWITCH 9 #define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0])) typedef enum { @@ -48,12 +48,12 @@ typedef enum { SWITCH_LEVEL_DOWN_CONTROL, SWITCH_LEVEL_CYCLE_CONTROL, SWITCH_COLOR_CONTROL, -} switch_func_t; +} SwitchFunction; typedef struct { uint8_t pin; - switch_func_t func; -} switch_func_pair_t; + SwitchFunction func; +} SwitchData; typedef enum { SWITCH_IDLE, @@ -61,9 +61,9 @@ typedef enum { SWITCH_PRESS_DETECTED, SWITCH_PRESSED, SWITCH_RELEASE_DETECTED, -} switch_state_t; +} SwitchState; -static switch_func_pair_t button_func_pair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; +static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; /* Zigbee switch */ class MyZigbeeSwitch : public ZigbeeSwitch { @@ -85,7 +85,7 @@ public: MyZigbeeSwitch zbSwitch = MyZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); /********************* Zigbee functions **************************/ -static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { +static void onZbButton(SwitchData *button_func_pair) { if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) { // Send toggle command to the light zbSwitch.lightToggle(); @@ -95,16 +95,16 @@ static void esp_zb_buttons_handler(switch_func_pair_t *button_func_pair) { /********************* GPIO functions **************************/ static QueueHandle_t gpio_evt_queue = NULL; -static void IRAM_ATTR gpio_isr_handler(void *arg) { - xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL); +static void IRAM_ATTR onGpioInterrupt(void *arg) { + xQueueSendFromISR(gpio_evt_queue, (SwitchData *)arg, NULL); } -static void switch_gpios_intr_enabled(bool enabled) { - for (int i = 0; i < PAIR_SIZE(button_func_pair); ++i) { +static void enableGpioInterrupt(bool enabled) { + for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); ++i) { if (enabled) { - enableInterrupt((button_func_pair[i]).pin); + enableInterrupt((buttonFunctionPair[i]).pin); } else { - disableInterrupt((button_func_pair[i]).pin); + disableInterrupt((buttonFunctionPair[i]).pin); } } } @@ -129,15 +129,15 @@ void setup() { // Init button switch - for (int i = 0; i < PAIR_SIZE(button_func_pair); i++) { - pinMode(button_func_pair[i].pin, INPUT_PULLUP); + for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) { + pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP); /* create a queue to handle gpio event from isr */ - gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t)); + gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData)); if (gpio_evt_queue == 0) { log_e("Queue was not created and must not be used"); while (1); } - attachInterruptArg(button_func_pair[i].pin, gpio_isr_handler, (void *)(button_func_pair + i), FALLING); + attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING); } // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode @@ -157,41 +157,41 @@ void setup() { void loop() { // Handle button switch in loop() uint8_t pin = 0; - switch_func_pair_t button_func_pair; - static switch_state_t switch_state = SWITCH_IDLE; - bool evt_flag = false; + SwitchData buttonSwitch; + static SwitchState buttonState = SWITCH_IDLE; + bool eventFlag = false; - /* check if there is any queue received, if yes read out the button_func_pair */ - if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) { - pin = button_func_pair.pin; - switch_gpios_intr_enabled(false); - evt_flag = true; + /* check if there is any queue received, if yes read out the buttonSwitch */ + if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) { + pin = buttonSwitch.pin; + enableGpioInterrupt(false); + eventFlag = true; } - while (evt_flag) { + while (eventFlag) { bool value = digitalRead(pin); - switch (switch_state) { - case SWITCH_IDLE: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; - case SWITCH_PRESS_DETECTED: switch_state = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; + switch (buttonState) { + case SWITCH_IDLE: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break; + case SWITCH_PRESS_DETECTED: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break; case SWITCH_RELEASE_DETECTED: - switch_state = SWITCH_IDLE; + buttonState = SWITCH_IDLE; /* callback to button_handler */ - (*esp_zb_buttons_handler)(&button_func_pair); + (*onZbButton)(&buttonSwitch); break; default: break; } - if (switch_state == SWITCH_IDLE) { - switch_gpios_intr_enabled(true); - evt_flag = false; + if (buttonState == SWITCH_IDLE) { + enableGpioInterrupt(true); + eventFlag = false; break; } vTaskDelay(10 / portTICK_PERIOD_MS); } // print the bound lights every 10 seconds - static uint32_t last_print = 0; - if (millis() - last_print > 10000) { - last_print = millis(); + static uint32_t lastPrint = 0; + if (millis() - lastPrint > 10000) { + lastPrint = millis(); zbSwitch.printBoundDevices(); } } From 9a354ae50319613920f240babe39a802ab43fb45 Mon Sep 17 00:00:00 2001 From: Jan Prochazka <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:43:51 +0200 Subject: [PATCH 27/34] Change virtual methods to callbacks (TODO) --- libraries/Zigbee/src/ZigbeeEP.cpp | 6 ++++++ libraries/Zigbee/src/ep/ZigbeeThermostat.cpp | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 84b2f30a297..0bcd16fb19e 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -62,6 +62,7 @@ void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) { // esp_zb_cluster_add_attr function } +//TODO: Separate manufacturer and model reading void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { /* Read peer Manufacture Name & Model Identifier */ esp_zb_zcl_read_attr_cmd_t read_req; @@ -79,8 +80,13 @@ void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { read_req.attr_field = attributes; esp_zb_zcl_read_attr_cmd_req(&read_req); + + //Wait for response or timeout + //Semaphore take } + + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index 24159a60bdc..c3f4fcb77b7 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -137,7 +137,25 @@ void ZigbeeThermostat::getTemperature(){ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; uint16_t attributes[] = { - ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + 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"); + 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; + 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; + + 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 From f321d43262320a9bd485cd6641b6f905f107c385 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: Thu, 26 Sep 2024 22:23:43 +0200 Subject: [PATCH 28/34] Refactor classes methods + implement Identify command --- .../Zigbee_Color_Dimmable_Light.ino | 73 ++++++-------- .../Zigbee_Color_Dimmer_Switch.ino | 2 +- .../Zigbee_On_Off_Light.ino | 23 ++--- .../Zigbee_On_Off_Switch.ino | 31 +++--- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 69 ++++++------- libraries/Zigbee/src/ZigbeeEP.cpp | 69 ++++++++++--- libraries/Zigbee/src/ZigbeeEP.h | 22 ++++- libraries/Zigbee/src/ZigbeeHandlers.cpp | 9 +- .../src/ep/ZigbeeColorDimmableLight.cpp | 97 ++++++------------- .../Zigbee/src/ep/ZigbeeColorDimmableLight.h | 28 +++--- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 2 - libraries/Zigbee/src/ep/ZigbeeLight.cpp | 40 ++------ libraries/Zigbee/src/ep/ZigbeeLight.h | 14 +-- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 2 - libraries/Zigbee/src/ep/ZigbeeThermostat.cpp | 48 ++++----- libraries/Zigbee/src/ep/ZigbeeThermostat.h | 13 ++- 16 files changed, 252 insertions(+), 290 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index fb05c4ec9e9..7a68b830b2f 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -36,53 +36,28 @@ #define LED_PIN RGB_BUILTIN #define BUTTON_PIN 9 // C6/H2 Boot button -#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ZIGBEE_LIGHT_ENDPOINT 10 -class MyZigbeeColorLight : public ZigbeeColorDimmableLight { -public: - // Constructor that passes parameters to the base class constructor - MyZigbeeColorLight(uint8_t endpoint) : ZigbeeColorDimmableLight(endpoint) {} +ZigbeeColorDimmableLight zbColorLight = ZigbeeColorDimmableLight(ZIGBEE_LIGHT_ENDPOINT); - // Override the set_on_off function - void setOnOff(bool value) override { - if (value == false) { - rgbLedWrite(LED_PIN, 0, 0, 0); // Turn off light - } else { - updateLight(); // Turn on light on last color and level - } - } - - // Override the set_level function - void setLevel(uint8_t level) override { - if (level == 0) { - rgbLedWrite(LED_PIN, 0, 0, 0); // Turn off light and dont update ratio - return; - } - _ratio = (float)level / 255; - updateLight(); - } - - // Override the set_color function - void setColor(uint8_t red, uint8_t green, uint8_t blue) override { - _red = red; - _green = green; - _blue = blue; - updateLight(); - } - - void updateLight() { - rgbLedWrite(LED_PIN, _red * _ratio, _green * _ratio, _blue * _ratio); // Update light - } -private: - // Add your custom attributes and methods here - float _ratio = 1.0; - uint8_t _red = 255; - uint8_t _green = 255; - uint8_t _blue = 255; - -}; +/********************* RGB LED functions **************************/ +void setRGBLight(bool state, uint8_t red, uint8_t green, uint8_t blue, uint8_t level) { + float brightness = (float)level / 255; + rgbLedWrite(LED_PIN, red * brightness, green * brightness, blue * brightness); +} -MyZigbeeColorLight zbColorLight = MyZigbeeColorLight(ZIGBEE_LIGHT_ENDPOINT); +// Create a task on identify call to handle the identify function +void identify(uint16_t time) { + static uint8_t blink = 1; + log_d("Identify called for %d seconds", time); + if (time == 0) { + // If identify time is 0, stop blinking and restore light as it was used for identify + zbColorLight.restoreLight(); + return; + } + rgbLedWrite(LED_PIN, 255 * blink, 255 * blink, 255 * blink); + blink = !blink; +} /********************* Arduino functions **************************/ void setup() { @@ -92,10 +67,16 @@ void setup() { // Init button for factory reset pinMode(BUTTON_PIN, INPUT); - //Optional: set Zigbee device name and model + // Set callback function for light change + zbColorLight.onLightChange(setRGBLight); + + // Optional: Set callback function for device identify + zbColorLight.onIdentify(identify); + + // Optional: Set Zigbee device name and model zbColorLight.setManufacturerAndModel("Espressif", "ZBColorLightBulb"); - //Add endpoint to Zigbee Core + // Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbColorLight); diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index e611e6d9857..b1738e44a8b 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -39,7 +39,7 @@ #include "ep/ZigbeeColorDimmerSwitch.h" /* Switch configuration */ -#define SWITCH_PIN 9 //Boot button for C6/H2 +#define SWITCH_PIN 9 // ESP32-C6/H2 Boot button #define SWITCH_ENDPOINT_NUMBER 5 /* Zigbee switch */ diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index db22c3dcc8e..6b19ecc6ad5 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -34,21 +34,15 @@ #include "ep/ZigbeeLight.h" #define LED_PIN RGB_BUILTIN -#define BUTTON_PIN 9 // C6/H2 Boot button -#define ZIGBEE_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button +#define ZIGBEE_LIGHT_ENDPOINT 10 -class MyZigbeeLight : public ZigbeeLight { -public: - // Constructor that passes parameters to the base class constructor - MyZigbeeLight(uint8_t endpoint) : ZigbeeLight(endpoint) {} +ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); - // Override the set_on_off function - void setOnOff(bool value) override { - rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); // Toggle light - } -}; - -MyZigbeeLight zbLight = MyZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); +/********************* RGB LED functions **************************/ +void setLED(bool value) { + rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); +} /********************* Arduino functions **************************/ void setup() { @@ -61,6 +55,9 @@ void setup() { //Optional: set Zigbee device name and model zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb"); + // Set callback function for light change + zbLight.onLightChange(setLED); + //Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index 27896f15f2b..dd4c72621e5 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -65,24 +65,7 @@ typedef enum { static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}}; -/* Zigbee switch */ -class MyZigbeeSwitch : public ZigbeeSwitch { -public: - // Constructor that passes parameters to the base class constructor - MyZigbeeSwitch(uint8_t endpoint) : ZigbeeSwitch(endpoint) {} - - // Override the set_on_off function - void readManufacturer(char* manufacturer) override { - //Do what you want with the manufacturer string - Serial.printf("Manufacturer: %s\n", manufacturer); - } - void readModel(char* model) override { - //Do what you want with the model string - Serial.printf("Model: %s\n", model); - } -}; - -MyZigbeeSwitch zbSwitch = MyZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); +ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER); /********************* Zigbee functions **************************/ static void onZbButton(SwitchData *button_func_pair) { @@ -127,7 +110,6 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - // Init button switch for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) { pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP); @@ -151,6 +133,17 @@ void setup() { Serial.printf("."); delay(500); } + + // Optional: read manufacturer and model name from the bound light + std::list boundLights = zbSwitch.getBoundDevices(); + //List all bound lights + for (const auto& device : boundLights) { + Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr); + Serial.printf("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7]); + Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr)); + Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr)); + } + Serial.println(); } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 1c100ad6d46..24a31515cf9 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -37,50 +37,37 @@ #define BUTTON_PIN 9 // Boot button for C6/H2 #define THERMOSTAT_ENDPOINT_NUMBER 5 -class MyZigbeeThermostat : public ZigbeeThermostat { - public: - // Constructor that passes parameters to the base class constructor - MyZigbeeThermostat(uint8_t endpoint) : ZigbeeThermostat(endpoint) {} - - // Override virtual functions from ZigbeeThermostat to handle temperature sensor data - void temperatureRead(float temp) override { - if (temperature != temp) { - Serial.printf("Temperature sensor value changed to: %.2f°C\n", temp); - temperature = temp; - } - } - - void temperatureMin(float temp) override { - Serial.printf("Temperature sensor min value: %.2f°C\n", temp); - min_temperature = temp; - } - - void temperatureMax(float temp) override { - Serial.printf("Temperature sensor max value: %.2f°C\n", temp); - max_temperature = temp; - } - - void temperatureTolerance(float tolerance) override { - Serial.printf("Temperature sensor tolerance: %.2f°C\n", tolerance); - temp_tolerance = tolerance; - } - - float temperature; - float max_temperature; - float min_temperature; - float temp_tolerance; -}; - -MyZigbeeThermostat zbThermostat = MyZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); +ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); + +// Save temperature sensor data +float sensor_temp; +float sensor_max_temp; +float sensor_min_temp; +float sensor_tolerance; + +/****************** Temperature sensor handling *******************/ +void recieveSensorTemp(float temperature) { + Serial.printf("Temperature sensor value: %.2f°C\n", temperature); + sensor_temp = temperature; +} +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); + sensor_min_temp = min_temp; + sensor_max_temp = max_temp; + sensor_tolerance = tolerance; +} /********************* Arduino functions **************************/ void setup() { - Serial.begin(115200); // Init button switch pinMode(BUTTON_PIN, INPUT); + // Set callback functions for temperature and configuration recieve + zbThermostat.onTempRecieve(recieveSensorTemp); + zbThermostat.onConfigRecieve(recieveSensorConfig); + //Optional: set Zigbee device name and model zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat"); @@ -94,6 +81,7 @@ void setup() { Zigbee.begin(ZIGBEE_COORDINATOR); Serial.println("Waiting for Temperature sensor to bound to the switch"); + //Wait for switch to bound to a light: while(!zbThermostat.isBound()) { @@ -101,9 +89,8 @@ void setup() { delay(500); } - // Get temperature sensor value to update min and max values - zbThermostat.getTemperature(); - + // Get temperature sensor configuration + zbThermostat.getSensorSettings(); Serial.println(); } @@ -124,7 +111,7 @@ void loop() { static uint32_t last_print = 0; if (millis() - last_print > 10000) { last_print = millis(); - int temp_percent = (int)((zbThermostat.temperature - zbThermostat.min_temperature) / (zbThermostat.max_temperature - zbThermostat.min_temperature) * 100); - Serial.printf("Temperature: %.2f°C (%d %%)\n", zbThermostat.temperature, temp_percent); + 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); } } diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 0bcd16fb19e..4977b3a5a09 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -15,6 +15,14 @@ ZigbeeEP::ZigbeeEP(uint8_t endpoint) { _endpoint = endpoint; _ep_config.endpoint = 0; _cluster_list = nullptr; +#if !CONFIG_DISABLE_HAL_LOCKS + if (!lock) { + lock = xSemaphoreCreateBinary(); + if (lock == NULL) { + log_e("Semaphore creation failed"); + } + } +#endif } ZigbeeEP::~ZigbeeEP() { @@ -57,13 +65,9 @@ void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) { esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); - - //NOTE: - // esp_zb_cluster_add_attr function } -//TODO: Separate manufacturer and model reading -void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { +char* ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr) { /* Read peer Manufacture Name & Model Identifier */ esp_zb_zcl_read_attr_cmd_t read_req; read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -74,18 +78,51 @@ void ZigbeeEP::readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr) { uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, - ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, }; read_req.attr_number = ZB_ARRAY_LENTH(attributes); read_req.attr_field = attributes; + + // clear read manufacturer + _read_manufacturer = nullptr; + esp_zb_zcl_read_attr_cmd_req(&read_req); //Wait for response or timeout - //Semaphore take + if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ + log_e("Error while reading manufacturer"); + } + return _read_manufacturer; + } +char* ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { + /* Read peer Manufacture Name & Model Identifier */ + 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_BASIC; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + + // clear read model + _read_model = nullptr; + esp_zb_zcl_read_attr_cmd_req(&read_req); + + //Wait for response or timeout + //Semaphore take + if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ + log_e("Error while reading model"); + } + return _read_model; +} #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" @@ -100,7 +137,7 @@ void ZigbeeEP::printBoundDevices() { #pragma GCC diagnostic pop -void ZigbeeEP::zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { +void ZigbeeEP::zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { zbstring_t *zbstr = (zbstring_t *)attribute->data.value; @@ -108,8 +145,8 @@ void ZigbeeEP::zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribut memcpy(string, zbstr->data, zbstr->len); string[zbstr->len] = '\0'; log_i("Peer Manufacturer is \"%s\"", string); - readManufacturer(string); - free(string); + _read_manufacturer = string; + xSemaphoreGive(lock); } if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { zbstring_t *zbstr = (zbstring_t *)attribute->data.value; @@ -117,9 +154,17 @@ void ZigbeeEP::zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribut memcpy(string, zbstr->data, zbstr->len); string[zbstr->len] = '\0'; log_i("Peer Model is \"%s\"", string); - readModel(string); - free(string); + _read_model = string; + xSemaphoreGive(lock); } } +void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) { + if (message->attribute.id == ESP_ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + _on_identify(*(uint16_t *)message->attribute.data.value); + } else { + log_w("Other identify commands are not implemented yet."); + } +} + #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index 8eb7bdc554a..cdd52fbcd78 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -39,6 +39,11 @@ typedef struct zb_device_params_s { uint16_t short_addr; } zb_device_params_t; +typedef enum { + SINGLE_COLOR = 0, + RGB = 1 +} zb_identify_led_type_t; + /* Zigbee End Device Class */ class ZigbeeEP { public: @@ -62,10 +67,10 @@ class ZigbeeEP { // Manufacturer name and model implemented void setManufacturerAndModel(const char *name, const char *model); - void readManufacturerAndModel(uint8_t endpoint, uint16_t short_addr); - // Methods to be implemented by EPs to recieve manufacturer and model name - virtual void readManufacturer(char* manufacturer) {}; - virtual void readModel(char* model) {}; + + // Methods to read manufacturer and model name from selected endpoint and short address + char* readManufacturer(uint8_t endpoint, uint16_t short_addr); + char* readModel(uint8_t endpoint, uint16_t short_addr); bool epAllowMultipleBinding() { return _allow_multiple_binding; } @@ -75,10 +80,16 @@ class ZigbeeEP { //list of all handlers function calls, to be overide 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 zbReadBasicCluster(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute); //already implemented + 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); + + void onIdentify(void (*callback)(uint16_t)) { _on_identify = callback; } private: static bool _allow_multiple_binding; + char* _read_manufacturer; + char* _read_model; + void (*_on_identify)(uint16_t time); protected: static uint8_t _endpoint; @@ -87,6 +98,7 @@ class ZigbeeEP { esp_zb_cluster_list_t *_cluster_list; static bool _is_bound; std::list _bound_devices; + SemaphoreHandle_t lock; friend class ZigbeeCore; }; diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index 2328dc1ea36..75b83e247b0 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -47,7 +47,12 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag // List through all Zigbee EPs and call the callback function, with the message for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->info.dst_endpoint == (*it)->getEndpoint()){ - (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class + if(message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY){ + (*it)->zbIdentify(message); //method zbIdentify implemented in the common EP class + } + else { + (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class + } } } return ESP_OK; @@ -95,7 +100,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re ); if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - (*it)->zbReadBasicCluster(message->info.cluster, &variable->attribute); //method zbReadBasicCluster implemented in the common EP class + (*it)->zbReadBasicCluster(&variable->attribute); //method zbReadBasicCluster implemented in the common EP class } else { (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index 16f264a8e5a..745b022ea82 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -12,10 +12,13 @@ ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP( .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0 }; -} -uint8_t ZigbeeColorDimmableLight::getCurrentLevel(){ - return (*(uint8_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID)->data_p); + //set default values + _current_state = false; + _current_level = 255; + _current_red = 255; + _current_green = 255; + _current_blue = 255; } uint16_t ZigbeeColorDimmableLight::getCurrentColorX(){ @@ -46,27 +49,23 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - setOnOff(*(bool *)message->attribute.data.value); - } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - sceneControl(*(bool *)message->attribute.data.value); - } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - setOnOffTime(*(uint16_t *)message->attribute.data.value); + if(_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - setOffWaitTime(*(uint16_t *)message->attribute.data.value); - } - // else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - // //TODO: more info needed, not implemented for now - // } else { log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { - setLevel(*(uint8_t *)message->attribute.data.value); + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; } else { log_w("Recieved message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); @@ -75,33 +74,32 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - log_v("Light color x changes to 0x%x", *(uint16_t *)message->attribute.data.value); uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value); uint16_t light_color_y = getCurrentColorY(); //calculate RGB from XY and call setColor() uint8_t red, green, blue; calculateRGB(light_color_x, light_color_y, red, green, blue); - setColor(red, green, blue); + _current_blue = blue; + _current_green = green; + _current_red = red; + lightChanged(); + return; } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - log_v("Light color x changes to 0x%x", *(uint16_t *)message->attribute.data.value); uint16_t light_color_x = getCurrentColorX(); uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value); //calculate RGB from XY and call setColor() uint8_t red, green, blue; calculateRGB(light_color_x, light_color_y, red, green, blue); - setColor(red, green, blue); - } - else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_SATURATION_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { - setColorSaturation(*(uint8_t *)message->attribute.data.value); - } - else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_HUE_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { - setColorHue(*(uint8_t *)message->attribute.data.value); + _current_blue = blue; + _current_green = green; + _current_red = red; + lightChanged(); + return; } else { log_w("Recieved message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); - //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_color_control.h } } else { @@ -109,45 +107,10 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me } } -//default method to set on/off -void ZigbeeColorDimmableLight::setOnOff(bool value) { - //set on/off - log_v("Function not overwritten, set on/off: %d", value); -} - -void ZigbeeColorDimmableLight::sceneControl(bool value) { - //set scene control - log_v("Function not overwritten, set scene control: %d", value); -} - -void ZigbeeColorDimmableLight::setOnOffTime(uint16_t value) { - //set on/off time - log_v("Function not overwritten, set on/off time: %d", value); -} - -void ZigbeeColorDimmableLight::setOffWaitTime(uint16_t value) { - //set off wait time - log_v("Function not overwritten, set off wait time: %d", value); -} - -void ZigbeeColorDimmableLight::setLevel(uint8_t value) { - //set level - log_v("Function not overwritten, set level: %d", value); -} - -void ZigbeeColorDimmableLight::setColor(uint8_t r, uint8_t g, uint8_t b) { - //set color - log_v("Function not overwritten, set color: r: %d, g: %d, b: %d", r, g, b); -} - -void ZigbeeColorDimmableLight::setColorSaturation(uint8_t value) { - //set color saturation - log_v("Function not overwritten, set color saturation: %d", value); -} - -void ZigbeeColorDimmableLight::setColorHue(uint8_t value) { - //set color hue - log_v("Function not overwritten, set color hue: %d", value); +void ZigbeeColorDimmableLight::lightChanged() { + if(_on_light_change) { + _on_light_change(_current_state, _current_red, _current_green, _current_blue, _current_level); + } } #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h index be69f28a72d..b46aff75bee 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -13,25 +13,25 @@ class ZigbeeColorDimmableLight : public ZigbeeEP { ZigbeeColorDimmableLight(uint8_t endpoint); ~ZigbeeColorDimmableLight(); - uint8_t getCurrentLevel(); - uint16_t getCurrentColorX(); - uint16_t getCurrentColorY(); - - - // methods to be implemented by the user by overwritting them - virtual void setOnOff(bool value); - virtual void sceneControl(bool value); - virtual void setOnOffTime(uint16_t value); - virtual void setOffWaitTime(uint16_t value); - virtual void setLevel(uint8_t value); - virtual void setColor(uint8_t red, uint8_t green, uint8_t blue); - virtual void setColorSaturation(uint8_t value); - virtual void setColorHue(uint8_t value); + void onLightChange(void (*callback)(bool, uint8_t, uint8_t, uint8_t, uint8_t)) { _on_light_change = callback; } + void restoreLight() { lightChanged(); } private: void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); + uint16_t getCurrentColorX(); + uint16_t getCurrentColorY(); + + void lightChanged(); + //callback function to be called on light change (State, R, G, B, Level) + void (*_on_light_change)(bool, uint8_t, uint8_t, uint8_t, uint8_t); + + bool _current_state; + uint8_t _current_level; + uint16_t _current_red; + uint16_t _current_green; + uint16_t _current_blue; }; #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 5c397cf9265..76a97d8e84c 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -42,8 +42,6 @@ void ZigbeeColorDimmerSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ log_i("Bound successfully!"); if (user_ctx) { zb_device_params_t *light = (zb_device_params_t *)user_ctx; - //Read manufacturer and model automatically after successful bind - _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); _instance->_bound_devices.push_back(light); } diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 5932a0c6e99..21007bca714 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -19,20 +19,9 @@ void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *mess //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - setOnOff(*(bool *)message->attribute.data.value); + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - sceneControl(*(bool *)message->attribute.data.value); - } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - setOnOffTime(*(uint16_t *)message->attribute.data.value); - } - else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_OFF_WAIT_TIME && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - setOffWaitTime(*(uint16_t *)message->attribute.data.value); - } - // else if(message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_START_UP_ON_OFF && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - // //TODO: more info needed, not implemented for now - // } else { log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } @@ -42,25 +31,12 @@ void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *mess } } -//default method to set on/off -void ZigbeeLight::setOnOff(bool value) { - //set on/off - log_v("Function not overwritten, set on/off: %d", value); -} - -void ZigbeeLight::sceneControl(bool value) { - //set scene control - log_v("Function not overwritten, set scene control: %d", value); -} - -void ZigbeeLight::setOnOffTime(uint16_t value) { - //set on/off time - log_v("Function not overwritten, set on/off time: %d", value); -} - -void ZigbeeLight::setOffWaitTime(uint16_t value) { - //set off wait time - log_v("Function not overwritten, set off wait time: %d", value); +void ZigbeeLight::lightChanged() { + if(_on_light_change) { + _on_light_change(_current_state); + } else { + log_w("No callback function set for light change"); + } } #endif //SOC_IEEE802154_SUPPORTED \ No newline at end of file diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.h b/libraries/Zigbee/src/ep/ZigbeeLight.h index c98e15023fd..20b1e71ea9b 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -13,15 +13,17 @@ class ZigbeeLight : public ZigbeeEP { ZigbeeLight(uint8_t endpoint); ~ZigbeeLight(); - // methods to be implemented by the user by overwritting them - virtual void setOnOff(bool value); - virtual void sceneControl(bool value); - virtual void setOnOffTime(uint16_t value); - virtual void setOffWaitTime(uint16_t value); + // Use tp set a cb function to be called on light change + void onLightChange(void (*callback)(bool)) { _on_light_change = callback; } + void restoreLight() { lightChanged(); } private: void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; - + //callback function to be called on light change + void (*_on_light_change)(bool); + void lightChanged(); + + bool _current_state; }; #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 8b071a44e8e..899d5f23e1e 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -24,8 +24,6 @@ void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { log_i("Bound successfully!"); if (user_ctx) { zb_device_params_t *light = (zb_device_params_t *)user_ctx; - //Read manufacturer and model automatically after successful bind - _instance->readManufacturerAndModel(light->endpoint, light->short_addr); log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); _instance->_bound_devices.push_back(light); //free(light); diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index c3f4fcb77b7..86c1a8fc18c 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -37,8 +37,6 @@ void ZigbeeThermostat::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { if (user_ctx) { zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; - //Read manufacturer and model automatically after successful bind - _instance->readManufacturerAndModel(sensor->endpoint, sensor->short_addr); log_i("The temperature sensor originating from address(0x%x) on endpoint(%d)", sensor->short_addr, sensor->endpoint); _instance->_bound_devices.push_back(sensor); } @@ -108,23 +106,32 @@ void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) { } void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { + 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) { int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - log_v("Raw temperature value: %d", value); - temperatureRead(zb_s16_to_temperature(value)); + if(_on_temp_recieve){ + _on_temp_recieve(zb_s16_to_temperature(value)); + } } 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; - temperatureMin(zb_s16_to_temperature(min_value)); + _min_temp = zb_s16_to_temperature(min_value); + read_config++; } 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; - temperatureMax(zb_s16_to_temperature(max_value)); + _max_temp = zb_s16_to_temperature(max_value); + read_config++; } 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; - temperatureTolerance(1.0 * tolerance / 100); + _tolerance = 1.0 * tolerance / 100; + read_config++; + } + if(read_config == 3){ + read_config = 0; + xSemaphoreGive(lock); } } } @@ -167,6 +174,16 @@ void ZigbeeThermostat::getSensorSettings(){ 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, portMAX_DELAY) != 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::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta){ @@ -196,21 +213,4 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m esp_zb_lock_release(); } -// default methods for thermostat -void ZigbeeThermostat::temperatureRead(float temp){ - log_v("Function not overwritten, measured temperature: %.2f °C", temp); -} - -void ZigbeeThermostat::temperatureMin(float temp){ - log_v("Function not overwritten, min temperature: %.2f °C", temp); -} - -void ZigbeeThermostat::temperatureMax(float temp){ - log_v("Function not overwritten, max temperature: %.2f °C", temp); -} - -void ZigbeeThermostat::temperatureTolerance(float tolerance){ - log_v("Function not overwritten, temperature tolerance: %.2f °C", tolerance); -} - #endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h index 4fd38deca7b..f0c1b5588e1 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -34,18 +34,23 @@ class ZigbeeThermostat : public ZigbeeEP { ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat(); - virtual void temperatureRead(float temp); - virtual void temperatureMin(float temp); - virtual void temperatureMax(float temp); - virtual void temperatureTolerance(float tolerance); + void onTempRecieve(void (*callback)(float)) { _on_temp_recieve = callback; } + void onConfigRecieve(void (*callback)(float, float, float)) { _on_config_recieve = callback; } void getTemperature(); + void getSensorSettings(); void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); private: // save instance of the class in order to use it in static functions static ZigbeeThermostat* _instance; + void (*_on_temp_recieve)(float); + void (*_on_config_recieve)(float, float, float); + float _min_temp; + float _max_temp; + float _tolerance; + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); From 27ecf2342bb73ff99264996ccb9478d9094582ea 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: Fri, 27 Sep 2024 09:05:27 +0200 Subject: [PATCH 29/34] Apply suggestions from code review by @lucasssvaz Co-authored-by: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> --- .../Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino | 3 +++ libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md | 2 +- .../examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino | 3 +++ .../examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino | 3 +++ .../Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino | 3 +++ .../Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino | 3 +++ libraries/Zigbee/library.properties | 2 +- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 1 - 8 files changed, 17 insertions(+), 3 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index b1738e44a8b..b8cb061a91c 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -49,6 +49,9 @@ ZigbeeColorDimmerSwitch zbSwitch = ZigbeeColorDimmerSwitch(SWITCH_ENDPOINT_NUMBE void setup() { Serial.begin(115200); + while (!Serial) { + delay(10); + } //Init button switch pinMode(SWITCH_PIN, INPUT); diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md index 1b9d9725aa0..68b0741b189 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md @@ -18,7 +18,7 @@ Currently, this example supports the following targets. ### Configure the Project Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. -By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. +By default, the `rgbLedWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. #### Using Arduino IDE diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index dd4c72621e5..f9f7c9a711d 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -96,6 +96,9 @@ static void enableGpioInterrupt(bool enabled) { void setup() { Serial.begin(115200); + while (!Serial) { + delay(10); + } //Optional: set Zigbee device name and model zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch"); diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino index 0a9f8b234c0..3d67d74c8fe 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -75,6 +75,9 @@ void printScannedNetworks(uint16_t networksFound) { void setup() { Serial.begin(115200); + while (!Serial) { + delay(10); + } // Initialize Zigbee stack without any EPs just for scanning Zigbee.begin(role); diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 5882d78ddae..7a25319c983 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -54,6 +54,9 @@ static void temp_sensor_value_update(void *arg) { void setup() { Serial.begin(115200); + while (!Serial) { + delay(10); + } // Init button switch pinMode(BUTTON_PIN, INPUT); diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 24a31515cf9..94f7a1aba4e 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -60,6 +60,9 @@ void recieveSensorConfig(float min_temp, float max_temp, float tolerance) { /********************* Arduino functions **************************/ void setup() { Serial.begin(115200); + while (!Serial) { + delay(10); + } // Init button switch pinMode(BUTTON_PIN, INPUT); diff --git a/libraries/Zigbee/library.properties b/libraries/Zigbee/library.properties index ce00e64a730..4d66f470378 100644 --- a/libraries/Zigbee/library.properties +++ b/libraries/Zigbee/library.properties @@ -1,5 +1,5 @@ name=Zigbee -version=1.0.0 +version=3.0.5 author=P-R-O-C-H-Y maintainer=Jan Procházka sentence=Enables zigbee connection with the ESP32 diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 899d5f23e1e..9ed087a7b81 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -26,7 +26,6 @@ void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { zb_device_params_t *light = (zb_device_params_t *)user_ctx; log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); _instance->_bound_devices.push_back(light); - //free(light); } _is_bound = true; } From 04e0f75562803e45286f24637af8521e4f784690 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: Fri, 27 Sep 2024 09:31:44 +0200 Subject: [PATCH 30/34] Update READMEs + add openNetwork fucntion --- .../Zigbee_Color_Dimmable_Light/README.md | 14 +++++++++----- .../examples/Zigbee_Color_Dimmer_Switch/README.md | 13 ++++++++----- .../Zigbee/examples/Zigbee_On_Off_Light/README.md | 15 ++++++++++----- .../examples/Zigbee_On_Off_Switch/README.md | 13 ++++++++----- .../examples/Zigbee_Scan_Networks/README.md | 10 +--------- .../examples/Zigbee_Temperature_Sensor/README.md | 14 +++++++++----- .../Zigbee/examples/Zigbee_Thermostat/README.md | 11 +++++++---- libraries/Zigbee/src/ZigbeeCore.cpp | 7 +++++++ libraries/Zigbee/src/ZigbeeCore.h | 1 + libraries/Zigbee/src/ZigbeeEP.cpp | 5 ----- libraries/Zigbee/src/ep/ZigbeeLight.cpp | 2 +- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 2 +- 12 files changed, 62 insertions(+), 45 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md index e14ad0b7000..4da23c8c7d2 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/README.md @@ -27,17 +27,21 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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 before flashing it to the board. It is recommended to do this if you did changes to the coordinator. +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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* 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 open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. +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*** diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md index 89a578191bd..8dd63a78c5e 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/README.md @@ -27,18 +27,21 @@ To get more information about the Espressif boards see [Espressif Development Ki * Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. +* 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 the example `Zigbee_Light_Bulb` 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. +If the End device flashed with the example `Zigbee_Color_Dimmable_Light` 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`. -* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. -By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. +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*** diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md index 68b0741b189..e74c7505ddb 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/README.md @@ -28,17 +28,22 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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 before flashing it to the board. It is recommended to do this if you did changes to the coordinator. +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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* 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. -By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md index 90a95c3fc34..b70f57d6e89 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/README.md @@ -27,18 +27,21 @@ To get more information about the Espressif boards see [Espressif Development Ki * Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. +* 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 the example `Zigbee_Light_Bulb` 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. +If the End device flashed with the example `Zigbee_On_Off_Light` 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`. -* In the `Zigbee_Light_Bulb` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* In the `Zigbee_On_Off_Light` example sketch call `Zigbee.factoryReset();`. -By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. +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*** diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md index 51939a84b55..0b2b2f94695 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/README.md @@ -42,18 +42,10 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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 before flashing it to the board. It is recommended to do this if you did changes to 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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. - -By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. - ***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. diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md index c52d7b710cc..f3dd9248f87 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/README.md @@ -38,17 +38,21 @@ To get more information about the Espressif boards see [Espressif Development Ki * 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 before flashing it to the board. It is recommended to do this if you did changes to the coordinator. +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` -* In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* 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 open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. +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*** diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/README.md b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md index 2e6d9ca471c..e61173f6f4d 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/README.md +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/README.md @@ -38,7 +38,7 @@ To get more information about the Espressif boards see [Espressif Development Ki * Select the Coordinator Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (coordinator/router)`. * 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 info to see logs from Zigbee stack: `Tools -> Core Debug Level: Info`. +* Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. ## Troubleshooting @@ -46,10 +46,13 @@ If the End device flashed with the example `Zigbee_Temperature_Sensor` is not co You can do the following: * In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. -* In the `Zigbee_Temperature_Sensor` example sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. +* In the `Zigbee_Temperature_Sensor` example sketch call `Zigbee.factoryReset();`. -By default, the coordinator network is open for 180s after rebooting or flashing new firmware. After that, the network is closed for adding new devices. -You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. +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*** diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index c2909209401..737f2459368 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -154,6 +154,13 @@ void ZigbeeCore::setRebootOpenNetwork(uint8_t time) { _open_network = time; } +void ZigbeeCore::openNetwork(uint8_t time) { + if (_started) { + log_v("Openning network for joining for %d seconds", time); + esp_zb_bdb_open_network(time); + } +} + static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); } diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index 79df4c61193..0a7f52e1b42 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -107,6 +107,7 @@ class ZigbeeCore { void setPrimaryChannelMask(uint32_t mask); void setRebootOpenNetwork(uint8_t time); + void openNetwork(uint8_t time); //scan_duration Time spent scanning each channel, in units of ((1 << scan_duration) + 1) * a beacon time. (15.36 microseconds) void scanNetworks(uint32_t channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK, uint8_t scan_duration = 5); diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 4977b3a5a09..c53cf691111 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -124,9 +124,6 @@ char* ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { return _read_model; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - void ZigbeeEP::printBoundDevices() { log_i("Bound devices:"); for(const auto& device : _bound_devices) { @@ -135,8 +132,6 @@ void ZigbeeEP::printBoundDevices() { } } -#pragma GCC diagnostic pop - void ZigbeeEP::zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute) { /* Basic cluster attributes */ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 21007bca714..75e72bbac35 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -39,4 +39,4 @@ void ZigbeeLight::lightChanged() { } } -#endif //SOC_IEEE802154_SUPPORTED \ No newline at end of file +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 9ed087a7b81..15b1ce89de0 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -235,4 +235,4 @@ void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, } } -#endif //SOC_IEEE802154_SUPPORTED \ No newline at end of file +#endif //SOC_IEEE802154_SUPPORTED From 2eedc2eda1262ec3d616357da460c4c4622d3550 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: Fri, 27 Sep 2024 09:38:20 +0200 Subject: [PATCH 31/34] Use [[maybe_unused]] instead of #pragma --- libraries/Zigbee/src/ZigbeeEP.cpp | 2 +- libraries/Zigbee/src/ZigbeeHandlers.cpp | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index c53cf691111..1f5823a7bfd 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -126,7 +126,7 @@ char* ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { void ZigbeeEP::printBoundDevices() { log_i("Bound devices:"); - for(const auto& device : _bound_devices) { + for( [[maybe_unused]] const auto& device : _bound_devices) { log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); print_ieee_addr(device->ieee_addr); } diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index 75b83e247b0..692103709c8 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -11,12 +11,8 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message); static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message); - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" - // Zigbee action handlers -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { +[[maybe_unused]] static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; switch (callback_id) { case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; @@ -29,8 +25,6 @@ static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, return ret; } -#pragma GCC diagnostic pop - static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message) { if (!message) { log_e("Empty message"); From 6e569366ab34c0a2991368b401cdeda27c2bb1c7 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: Fri, 27 Sep 2024 12:08:10 +0200 Subject: [PATCH 32/34] Use gpio calls for OnOff Light example --- .../examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index 6b19ecc6ad5..2bbe5ba3e7b 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -41,13 +41,14 @@ ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); /********************* RGB LED functions **************************/ void setLED(bool value) { - rgbLedWrite(LED_PIN, 255 * value, 255 * value, 255 * value); + digitalWrite(LED_PIN, value); } /********************* Arduino functions **************************/ void setup() { - // Init RMT and leave light OFF - rgbLedWrite(LED_PIN, 0, 0, 0); + // Init LED and turn it OFF (if LED_PIN == RGB_BUILTIN, the rgbLedWrite() will be used under the hood) + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, LOW); // Init button for factory reset pinMode(BUTTON_PIN, INPUT); From 3961642925e627f61c9cb63d1c714baaaf322304 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:27:22 -0300 Subject: [PATCH 33/34] ci(pre-commit): Apply automatic fixes --- .../Zigbee_Color_Dimmable_Light.ino | 18 +- .../Zigbee_Color_Dimmable_Light/ci.json | 14 +- .../Zigbee_Color_Dimmer_Switch.ino | 15 +- .../Zigbee_Color_Dimmer_Switch/ci.json | 14 +- .../Zigbee_On_Off_Light.ino | 12 +- .../examples/Zigbee_On_Off_Light/ci.json | 14 +- .../Zigbee_On_Off_Switch.ino | 21 +- .../examples/Zigbee_On_Off_Switch/ci.json | 14 +- .../Zigbee_Scan_Networks.ino | 15 +- .../examples/Zigbee_Scan_Networks/ci.json | 14 +- .../Zigbee_Temperature_Sensor.ino | 8 +- .../Zigbee_Temperature_Sensor/ci.json | 14 +- .../Zigbee_Thermostat/Zigbee_Thermostat.ino | 13 +- .../Zigbee/examples/Zigbee_Thermostat/ci.json | 14 +- libraries/Zigbee/src/ZigbeeCore.cpp | 167 ++--- libraries/Zigbee/src/ZigbeeCore.h | 151 ++-- libraries/Zigbee/src/ZigbeeEP.cpp | 231 +++---- libraries/Zigbee/src/ZigbeeEP.h | 174 ++--- libraries/Zigbee/src/ZigbeeHandlers.cpp | 49 +- .../src/ep/ZigbeeColorDimmableLight.cpp | 174 +++-- .../Zigbee/src/ep/ZigbeeColorDimmableLight.h | 52 +- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp | 649 +++++++++--------- .../Zigbee/src/ep/ZigbeeColorDimmerSwitch.h | 72 +- libraries/Zigbee/src/ep/ZigbeeLight.cpp | 47 +- libraries/Zigbee/src/ep/ZigbeeLight.h | 36 +- libraries/Zigbee/src/ep/ZigbeeSwitch.cpp | 359 +++++----- libraries/Zigbee/src/ep/ZigbeeSwitch.h | 59 +- libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp | 129 ++-- libraries/Zigbee/src/ep/ZigbeeTempSensor.h | 26 +- libraries/Zigbee/src/ep/ZigbeeThermostat.cpp | 217 +++--- libraries/Zigbee/src/ep/ZigbeeThermostat.h | 85 +-- 31 files changed, 1437 insertions(+), 1440 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index 7a68b830b2f..c12ecadbd64 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -15,7 +15,7 @@ /** * @brief This example demonstrates Zigbee Color Dimmable light bulb. * - * The example demonstrates how to use Zigbee library to create an end device with + * The example demonstrates how to use Zigbee library to create an end device with * color dimmable light end point. * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. * @@ -23,7 +23,7 @@ * 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/) */ @@ -34,9 +34,9 @@ #include "ZigbeeCore.h" #include "ep/ZigbeeColorDimmableLight.h" -#define LED_PIN RGB_BUILTIN -#define BUTTON_PIN 9 // C6/H2 Boot button -#define ZIGBEE_LIGHT_ENDPOINT 10 +#define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // C6/H2 Boot button +#define ZIGBEE_LIGHT_ENDPOINT 10 ZigbeeColorDimmableLight zbColorLight = ZigbeeColorDimmableLight(ZIGBEE_LIGHT_ENDPOINT); @@ -52,7 +52,7 @@ void identify(uint16_t time) { log_d("Identify called for %d seconds", time); if (time == 0) { // If identify time is 0, stop blinking and restore light as it was used for identify - zbColorLight.restoreLight(); + zbColorLight.restoreLight(); return; } rgbLedWrite(LED_PIN, 255 * blink, 255 * blink, 255 * blink); @@ -79,7 +79,7 @@ void setup() { // Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbColorLight); - + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE log_d("Calling Zigbee.begin()"); Zigbee.begin(); @@ -93,7 +93,7 @@ void loop() { int startTime = millis(); while (digitalRead(BUTTON_PIN) == LOW) { delay(50); - if((millis() - startTime) > 3000) { + if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); @@ -101,4 +101,4 @@ void loop() { } } delay(100); -} \ No newline at end of file +} diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json index 83af1395ee6..3aaf44eb376 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index b8cb061a91c..fac0a92316f 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -19,7 +19,7 @@ * The RGB light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator (Switch). * To turn on/off the light, push the button on the switch. * To change the color or level of the light, send serial commands to the switch. - * + * * By setting the switch to allow multiple binding, so it can bind to multiple lights. * Also every 30 seconds, all bound lights are printed to the serial console. * @@ -27,7 +27,7 @@ * 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/) */ @@ -39,7 +39,7 @@ #include "ep/ZigbeeColorDimmerSwitch.h" /* Switch configuration */ -#define SWITCH_PIN 9 // ESP32-C6/H2 Boot button +#define SWITCH_PIN 9 // ESP32-C6/H2 Boot button #define SWITCH_ENDPOINT_NUMBER 5 /* Zigbee switch */ @@ -47,7 +47,7 @@ ZigbeeColorDimmerSwitch zbSwitch = ZigbeeColorDimmerSwitch(SWITCH_ENDPOINT_NUMBE /********************* Arduino functions **************************/ void setup() { - + Serial.begin(115200); while (!Serial) { delay(10); @@ -67,14 +67,13 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - + //When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode Zigbee.begin(ZIGBEE_COORDINATOR); - + Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while(!zbSwitch.isBound()) - { + while (!zbSwitch.isBound()) { Serial.printf("."); delay(500); } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json index 203fce34b38..c916121b991 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index 2bbe5ba3e7b..576623e990a 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -22,7 +22,7 @@ * 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/) */ @@ -33,8 +33,8 @@ #include "ZigbeeCore.h" #include "ep/ZigbeeLight.h" -#define LED_PIN RGB_BUILTIN -#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button +#define LED_PIN RGB_BUILTIN +#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button #define ZIGBEE_LIGHT_ENDPOINT 10 ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); @@ -62,7 +62,7 @@ void setup() { //Add endpoint to Zigbee Core log_d("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); - + // When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE log_d("Calling Zigbee.begin()"); Zigbee.begin(); @@ -76,7 +76,7 @@ void loop() { int startTime = millis(); while (digitalRead(BUTTON_PIN) == LOW) { delay(50); - if((millis() - startTime) > 3000) { + if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); @@ -84,4 +84,4 @@ void loop() { } } delay(100); -} \ No newline at end of file +} diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json index 83af1395ee6..3aaf44eb376 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index f9f7c9a711d..09487dea05d 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -23,7 +23,7 @@ * 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/) */ @@ -94,7 +94,7 @@ static void enableGpioInterrupt(bool enabled) { /********************* Arduino functions **************************/ void setup() { - + Serial.begin(115200); while (!Serial) { delay(10); @@ -112,7 +112,7 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - + // Init button switch for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) { pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP); @@ -128,21 +128,23 @@ void setup() { // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode log_d("Calling Zigbee.begin()"); Zigbee.begin(ZIGBEE_COORDINATOR); - + Serial.println("Waiting for Light to bound to the switch"); //Wait for switch to bound to a light: - while(!zbSwitch.isBound()) - { + while (!zbSwitch.isBound()) { Serial.printf("."); delay(500); } // Optional: read manufacturer and model name from the bound light - std::list boundLights = zbSwitch.getBoundDevices(); + std::list boundLights = zbSwitch.getBoundDevices(); //List all bound lights - for (const auto& device : boundLights) { + for (const auto &device : boundLights) { Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr); - Serial.printf("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7]); + Serial.printf( + "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], + device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7] + ); Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr)); Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr)); } @@ -156,7 +158,6 @@ void loop() { SwitchData buttonSwitch; static SwitchState buttonState = SWITCH_IDLE; bool eventFlag = false; - /* check if there is any queue received, if yes read out the buttonSwitch */ if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) { diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json index 203fce34b38..c916121b991 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino index 3d67d74c8fe..a72ade201ae 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/Zigbee_Scan_Networks.ino @@ -21,7 +21,7 @@ * with proper Zigbee partition scheme 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/) */ @@ -32,9 +32,9 @@ #include "ZigbeeCore.h" #ifdef ZIGBEE_MODE_ZCZR -zigbee_role_t role = ZIGBEE_ROUTER; // or can be ZIGBEE_COORDINATOR, but it wont scan itself +zigbee_role_t role = ZIGBEE_ROUTER; // or can be ZIGBEE_COORDINATOR, but it wont scan itself #else -zigbee_role_t role = ZIGBEE_END_DEVICE; +zigbee_role_t role = ZIGBEE_END_DEVICE; #endif void printScannedNetworks(uint16_t networksFound) { @@ -60,10 +60,11 @@ void printScannedNetworks(uint16_t networksFound) { Serial.print(" | "); Serial.printf("%-19.19s", scan_result[i].end_device_capacity ? "Yes" : "No"); Serial.print(" | "); - Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", scan_result[i].extended_pan_id[7], scan_result[i].extended_pan_id[6], - scan_result[i].extended_pan_id[5], scan_result[i].extended_pan_id[4], - scan_result[i].extended_pan_id[3], scan_result[i].extended_pan_id[2], - scan_result[i].extended_pan_id[1], scan_result[i].extended_pan_id[0]); + Serial.printf( + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", scan_result[i].extended_pan_id[7], scan_result[i].extended_pan_id[6], scan_result[i].extended_pan_id[5], + scan_result[i].extended_pan_id[4], scan_result[i].extended_pan_id[3], scan_result[i].extended_pan_id[2], scan_result[i].extended_pan_id[1], + scan_result[i].extended_pan_id[0] + ); Serial.println(); delay(10); } diff --git a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json index 83af1395ee6..3aaf44eb376 100644 --- a/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Scan_Networks/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index 7a25319c983..bfb578663db 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -33,7 +33,7 @@ #include "ZigbeeCore.h" #include "ep/ZigbeeTempSensor.h" -#define BUTTON_PIN 9 //Boot button for C6/H2 +#define BUTTON_PIN 9 //Boot button for C6/H2 #define TEMP_SENSOR_ENDPOINT_NUMBER 10 ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); @@ -52,7 +52,7 @@ static void temp_sensor_value_update(void *arg) { /********************* Arduino functions **************************/ void setup() { - + Serial.begin(115200); while (!Serial) { delay(10); @@ -65,7 +65,7 @@ void setup() { 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); + zbTempSensor.setMinMaxValue(10, 50); // Set tolerance for temperature measurement in °C (lowest possible value is 0.01°C) zbTempSensor.setTolerance(1); @@ -95,7 +95,7 @@ void loop() { int startTime = millis(); while (digitalRead(BUTTON_PIN) == LOW) { delay(50); - if((millis() - startTime) > 3000) { + if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json index 83af1395ee6..3aaf44eb376 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee,ZigbeeMode=ed" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee,ZigbeeMode=ed" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 94f7a1aba4e..0fef83f0ad7 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -23,7 +23,7 @@ * 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/) */ @@ -34,7 +34,7 @@ #include "ZigbeeCore.h" #include "ep/ZigbeeThermostat.h" -#define BUTTON_PIN 9 // Boot button for C6/H2 +#define BUTTON_PIN 9 // Boot button for C6/H2 #define THERMOSTAT_ENDPOINT_NUMBER 5 ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); @@ -79,15 +79,14 @@ void setup() { //Open network for 180 seconds after boot Zigbee.setRebootOpenNetwork(180); - + // When all EPs are registered, start Zigbee with ZIGBEE_COORDINATOR mode Zigbee.begin(ZIGBEE_COORDINATOR); - + Serial.println("Waiting for Temperature sensor to bound to the switch"); //Wait for switch to bound to a light: - while(!zbThermostat.isBound()) - { + while (!zbThermostat.isBound()) { Serial.printf("."); delay(500); } @@ -109,7 +108,7 @@ void loop() { // Set reporting interval for temperature sensor zbThermostat.setTemperatureReporting(0, 10, 2); } - + // Print temperature sensor data each 10 seconds static uint32_t last_print = 0; if (millis() - last_print > 10000) { diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json index 203fce34b38..c916121b991 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/ci.json @@ -1,16 +1,16 @@ { - "targets": { - "esp32": false, - "esp32c3": false, - "esp32s2": false, - "esp32s3": false - }, - "fqbn": { + "fqbn": { "esp32c6": [ "espressif:esp32:esp32c6:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ], "esp32h2": [ "espressif:esp32:esp32h2:PartitionScheme=zigbee_zczr,ZigbeeMode=zczr" ] + }, + "targets": { + "esp32": false, + "esp32c3": false, + "esp32s2": false, + "esp32s3": false } } diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index 737f2459368..2b089cf03ec 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -7,8 +7,8 @@ #include "Arduino.h" ZigbeeCore::ZigbeeCore() { - _radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; // Use the native 15.4 radio - _host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; // Disable host connection + _radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; // Use the native 15.4 radio + _host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; // Disable host connection _zb_ep_list = esp_zb_ep_list_create(); _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK; _open_network = 0; @@ -21,7 +21,7 @@ ZigbeeCore::~ZigbeeCore() {} static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message); bool ZigbeeCore::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { - if (!zigbeeInit(role_cfg, erase_nvs)){ + if (!zigbeeInit(role_cfg, erase_nvs)) { return false; } _role = (zigbee_role_t)role_cfg->esp_zb_role; @@ -30,36 +30,36 @@ bool ZigbeeCore::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) { bool ZigbeeCore::begin(zigbee_role_t role, bool erase_nvs) { bool status = true; - switch (role) - { - case ZIGBEE_COORDINATOR: { + switch (role) { + case ZIGBEE_COORDINATOR: + { _role = ZIGBEE_COORDINATOR; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_COORDINATOR_CONFIG(); status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } - case ZIGBEE_ROUTER: { + case ZIGBEE_ROUTER: + { _role = ZIGBEE_ROUTER; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ROUTER_CONFIG(); status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } - case ZIGBEE_END_DEVICE: { + case ZIGBEE_END_DEVICE: + { _role = ZIGBEE_END_DEVICE; esp_zb_cfg_t zb_nwk_cfg = ZIGBEE_DEFAULT_ED_CONFIG(); status = zigbeeInit(&zb_nwk_cfg, erase_nvs); break; } - default: - log_e("Invalid Zigbee Role"); - return false; + default: log_e("Invalid Zigbee Role"); return false; } return status; } void ZigbeeCore::addEndpoint(ZigbeeEP *ep) { ep_objects.push_back(ep); - + log_d("Endpoint: %d, Device ID: 0x%04x", ep->_endpoint, ep->_device_id); //Register clusters and ep_list to the ZigbeeCore class's ep_list if (ep->_ep_config.endpoint == 0 || ep->_cluster_list == nullptr) { @@ -84,7 +84,7 @@ bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { .host_config = _host_config, }; - esp_err_t err = esp_zb_platform_config(&platform_config); + esp_err_t err = esp_zb_platform_config(&platform_config); if (err != ESP_OK) { log_e("Failed to configure Zigbee platform"); return false; @@ -94,8 +94,8 @@ bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { log_d("Initialize Zigbee stack"); esp_zb_init(zb_cfg); - // Register all Zigbee EPs in list - if(ep_objects.empty()) { + // Register all Zigbee EPs in list + if (ep_objects.empty()) { log_w("No Zigbee EPs to register"); } else { log_d("Register all Zigbee EPs in list"); @@ -104,10 +104,10 @@ bool ZigbeeCore::zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs) { log_e("Failed to register Zigbee EPs"); return false; } - + //print the list of Zigbee EPs from ep_objects log_i("List of registered Zigbee EPs:"); - for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { + for (std::list::iterator it = ep_objects.begin(); it != ep_objects.end(); ++it) { log_i("Device type: %s, Endpoint: %d, Device ID: 0x%04x", getDeviceTypeString((*it)->_device_id), (*it)->_endpoint, (*it)->_device_id); } } @@ -175,12 +175,12 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { //main switch switch (sig_type) { - case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common log_i("Zigbee stack initialized"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); break; - case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Common - case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: // Common + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Common + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: // Common if (err_status == ESP_OK) { log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); if (esp_zb_bdb_is_factory_new()) { @@ -207,7 +207,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { log_e("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); } break; - case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator + case ESP_ZB_BDB_SIGNAL_FORMATION: // Coordinator if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { esp_zb_ieee_addr_t extended_pan_id; @@ -224,14 +224,13 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } break; - case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device + case ESP_ZB_BDB_SIGNAL_STEERING: // Router and End Device Zigbee._started = true; if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { log_i("Network steering started"); } - } - else { + } else { if (err_status == ESP_OK) { esp_zb_ieee_addr_t extended_pan_id; esp_zb_get_extended_pan_id(extended_pan_id); @@ -246,7 +245,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } break; - case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator + case ESP_ZB_ZDO_SIGNAL_DEVICE_ANNCE: // Coordinator if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { dev_annce_params = (esp_zb_zdo_signal_device_annce_params_t *)esp_zb_app_signal_get_params(p_sg_p); log_i("New device commissioned or rejoined (short: 0x%04hx)", dev_annce_params->device_short_addr); @@ -255,26 +254,26 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { cmd_req.addr_of_interest = dev_annce_params->device_short_addr; log_v("Device capabilities: 0x%02x", dev_annce_params->capability); /* - capability: + capability: Bit 0 – Alternate PAN Coordinator Bit 1 – Device type: 1- ZigBee Router; 0 – End Device - Bit 2 – Power Source: 1 Main powered + Bit 2 – Power Source: 1 Main powered Bit 3 – Receiver on when Idle - Bit 4 – Reserved - Bit 5 – Reserved + Bit 4 – Reserved + Bit 5 – Reserved Bit 6 – Security capability Bit 7 – Reserved */ // for each endpoint in the list call the findEndpoint function if not bounded or allowed to bind multiple devices - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (!(*it)->isBound() || (*it)->epAllowMultipleBinding()) { (*it)->findEndpoint(&cmd_req); } } } break; - case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator + case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: // Coordinator if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR) { if (err_status == ESP_OK) { if (*(uint8_t *)esp_zb_app_signal_get_params(p_sg_p)) { @@ -294,14 +293,20 @@ void ZigbeeCore::factoryReset() { esp_zb_factory_reset(); } -void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor){ +void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor) { log_v("Zigbee network scan complete"); - if(zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_v("Found %d networks", count); //print Zigbee networks for (int i = 0; i < count; i++) { - log_v("Network %d: PAN ID: 0x%04hx, Permit Joining: %s, Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, Channel: %d, Router Capacity: %s, End Device Capacity: %s", - i, nwk_descriptor[i].short_pan_id, nwk_descriptor[i].permit_joining ? "Yes" : "No", nwk_descriptor[i].extended_pan_id[7], nwk_descriptor[i].extended_pan_id[6], nwk_descriptor[i].extended_pan_id[5], nwk_descriptor[i].extended_pan_id[4], nwk_descriptor[i].extended_pan_id[3], nwk_descriptor[i].extended_pan_id[2], nwk_descriptor[i].extended_pan_id[1], nwk_descriptor[i].extended_pan_id[0], nwk_descriptor[i].logic_channel, nwk_descriptor[i].router_capacity ? "Yes" : "No", nwk_descriptor[i].end_device_capacity ? "Yes" : "No"); + log_v( + "Network %d: PAN ID: 0x%04hx, Permit Joining: %s, Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, Channel: %d, Router Capacity: %s, End " + "Device Capacity: %s", + i, nwk_descriptor[i].short_pan_id, nwk_descriptor[i].permit_joining ? "Yes" : "No", nwk_descriptor[i].extended_pan_id[7], + nwk_descriptor[i].extended_pan_id[6], nwk_descriptor[i].extended_pan_id[5], nwk_descriptor[i].extended_pan_id[4], nwk_descriptor[i].extended_pan_id[3], + nwk_descriptor[i].extended_pan_id[2], nwk_descriptor[i].extended_pan_id[1], nwk_descriptor[i].extended_pan_id[0], nwk_descriptor[i].logic_channel, + nwk_descriptor[i].router_capacity ? "Yes" : "No", nwk_descriptor[i].end_device_capacity ? "Yes" : "No" + ); } //save scan result and update scan status //copy network descriptor to _scan_result to keep the data after the callback @@ -316,7 +321,7 @@ void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t co } void ZigbeeCore::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { - if(!_started) { + if (!_started) { log_e("Zigbee stack is not started, cannot scan networks"); return; } @@ -325,11 +330,11 @@ void ZigbeeCore::scanNetworks(u_int32_t channel_mask, u_int8_t scan_duration) { _scan_status = ZB_SCAN_RUNNING; } -int16_t ZigbeeCore::scanComplete(){ +int16_t ZigbeeCore::scanComplete() { return _scan_status; } -zigbee_scan_result_t* ZigbeeCore::getScanResult() { +zigbee_scan_result_t *ZigbeeCore::getScanResult() { return _scan_result; } @@ -342,50 +347,50 @@ void ZigbeeCore::scanDelete() { } // Function to convert enum value to string -const char* ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { - switch (deviceId) { - case ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID: return "General On/Off switch"; - case ESP_ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID: return "Level Control Switch"; - case ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID: return "General On/Off output"; - case ESP_ZB_HA_LEVEL_CONTROLLABLE_OUTPUT_DEVICE_ID: return "Level Controllable Output"; - case ESP_ZB_HA_SCENE_SELECTOR_DEVICE_ID: return "Scene Selector"; - case ESP_ZB_HA_CONFIGURATION_TOOL_DEVICE_ID: return "Configuration Tool"; - case ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID: return "Remote Control"; - case ESP_ZB_HA_COMBINED_INTERFACE_DEVICE_ID: return "Combined Interface"; - case ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID: return "Range Extender"; - case ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID: return "Mains Power Outlet"; - case ESP_ZB_HA_DOOR_LOCK_DEVICE_ID: return "Door lock client"; - case ESP_ZB_HA_DOOR_LOCK_CONTROLLER_DEVICE_ID: return "Door lock controller"; - case ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID: return "Simple Sensor device"; - case ESP_ZB_HA_CONSUMPTION_AWARENESS_DEVICE_ID: return "Consumption Awareness Device"; - case ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID: return "Home Gateway"; - case ESP_ZB_HA_SMART_PLUG_DEVICE_ID: return "Smart plug"; - case ESP_ZB_HA_WHITE_GOODS_DEVICE_ID: return "White Goods"; - case ESP_ZB_HA_METER_INTERFACE_DEVICE_ID: return "Meter Interface"; - case ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID: return "On/Off Light Device"; - case ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID: return "Dimmable Light Device"; - case ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID: return "Color Dimmable Light Device"; - case ESP_ZB_HA_DIMMER_SWITCH_DEVICE_ID: return "Dimmer Switch Device"; - case ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID: return "Color Dimmer Switch Device"; - case ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID: return "Light Sensor"; - case ESP_ZB_HA_SHADE_DEVICE_ID: return "Shade"; - case ESP_ZB_HA_SHADE_CONTROLLER_DEVICE_ID: return "Shade controller"; - case ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID: return "Window Covering client"; - case ESP_ZB_HA_WINDOW_COVERING_CONTROLLER_DEVICE_ID: return "Window Covering controller"; - case ESP_ZB_HA_HEATING_COOLING_UNIT_DEVICE_ID: return "Heating/Cooling Unit device"; - case ESP_ZB_HA_THERMOSTAT_DEVICE_ID: return "Thermostat Device"; - case ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID: return "Temperature Sensor"; - case ESP_ZB_HA_IAS_CONTROL_INDICATING_EQUIPMENT_ID: return "IAS Control and Indicating Equipment"; - case ESP_ZB_HA_IAS_ANCILLARY_CONTROL_EQUIPMENT_ID: return "IAS Ancillary Control Equipment"; - case ESP_ZB_HA_IAS_ZONE_ID: return "IAS Zone"; - case ESP_ZB_HA_IAS_WARNING_DEVICE_ID: return "IAS Warning Device"; - case ESP_ZB_HA_TEST_DEVICE_ID: return "Custom HA device for test"; - case ESP_ZB_HA_CUSTOM_TUNNEL_DEVICE_ID: return "Custom Tunnel device"; - case ESP_ZB_HA_CUSTOM_ATTR_DEVICE_ID: return "Custom Attributes Device"; - default: return "Unknown device type"; - } +const char *ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { + switch (deviceId) { + case ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID: return "General On/Off switch"; + case ESP_ZB_HA_LEVEL_CONTROL_SWITCH_DEVICE_ID: return "Level Control Switch"; + case ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID: return "General On/Off output"; + case ESP_ZB_HA_LEVEL_CONTROLLABLE_OUTPUT_DEVICE_ID: return "Level Controllable Output"; + case ESP_ZB_HA_SCENE_SELECTOR_DEVICE_ID: return "Scene Selector"; + case ESP_ZB_HA_CONFIGURATION_TOOL_DEVICE_ID: return "Configuration Tool"; + case ESP_ZB_HA_REMOTE_CONTROL_DEVICE_ID: return "Remote Control"; + case ESP_ZB_HA_COMBINED_INTERFACE_DEVICE_ID: return "Combined Interface"; + case ESP_ZB_HA_RANGE_EXTENDER_DEVICE_ID: return "Range Extender"; + case ESP_ZB_HA_MAINS_POWER_OUTLET_DEVICE_ID: return "Mains Power Outlet"; + case ESP_ZB_HA_DOOR_LOCK_DEVICE_ID: return "Door lock client"; + case ESP_ZB_HA_DOOR_LOCK_CONTROLLER_DEVICE_ID: return "Door lock controller"; + case ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID: return "Simple Sensor device"; + case ESP_ZB_HA_CONSUMPTION_AWARENESS_DEVICE_ID: return "Consumption Awareness Device"; + case ESP_ZB_HA_HOME_GATEWAY_DEVICE_ID: return "Home Gateway"; + case ESP_ZB_HA_SMART_PLUG_DEVICE_ID: return "Smart plug"; + case ESP_ZB_HA_WHITE_GOODS_DEVICE_ID: return "White Goods"; + case ESP_ZB_HA_METER_INTERFACE_DEVICE_ID: return "Meter Interface"; + case ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID: return "On/Off Light Device"; + case ESP_ZB_HA_DIMMABLE_LIGHT_DEVICE_ID: return "Dimmable Light Device"; + case ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID: return "Color Dimmable Light Device"; + case ESP_ZB_HA_DIMMER_SWITCH_DEVICE_ID: return "Dimmer Switch Device"; + case ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID: return "Color Dimmer Switch Device"; + case ESP_ZB_HA_LIGHT_SENSOR_DEVICE_ID: return "Light Sensor"; + case ESP_ZB_HA_SHADE_DEVICE_ID: return "Shade"; + case ESP_ZB_HA_SHADE_CONTROLLER_DEVICE_ID: return "Shade controller"; + case ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID: return "Window Covering client"; + case ESP_ZB_HA_WINDOW_COVERING_CONTROLLER_DEVICE_ID: return "Window Covering controller"; + case ESP_ZB_HA_HEATING_COOLING_UNIT_DEVICE_ID: return "Heating/Cooling Unit device"; + case ESP_ZB_HA_THERMOSTAT_DEVICE_ID: return "Thermostat Device"; + case ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID: return "Temperature Sensor"; + case ESP_ZB_HA_IAS_CONTROL_INDICATING_EQUIPMENT_ID: return "IAS Control and Indicating Equipment"; + case ESP_ZB_HA_IAS_ANCILLARY_CONTROL_EQUIPMENT_ID: return "IAS Ancillary Control Equipment"; + case ESP_ZB_HA_IAS_ZONE_ID: return "IAS Zone"; + case ESP_ZB_HA_IAS_WARNING_DEVICE_ID: return "IAS Warning Device"; + case ESP_ZB_HA_TEST_DEVICE_ID: return "Custom HA device for test"; + case ESP_ZB_HA_CUSTOM_TUNNEL_DEVICE_ID: return "Custom Tunnel device"; + case ESP_ZB_HA_CUSTOM_ATTR_DEVICE_ID: return "Custom Attributes Device"; + default: return "Unknown device type"; + } } ZigbeeCore Zigbee = ZigbeeCore(); -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index 0a7f52e1b42..1044a9c737c 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -19,110 +19,107 @@ typedef esp_zb_network_descriptor_t zigbee_scan_result_t; // enum of Zigbee Roles typedef enum { - ZIGBEE_COORDINATOR = 0, - ZIGBEE_ROUTER = 1, - ZIGBEE_END_DEVICE = 2 + ZIGBEE_COORDINATOR = 0, + ZIGBEE_ROUTER = 1, + ZIGBEE_END_DEVICE = 2 } zigbee_role_t; #define ZB_SCAN_RUNNING (-1) #define ZB_SCAN_FAILED (-2) -#define ZIGBEE_DEFAULT_ED_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ - .install_code_policy = false, \ - .nwk_cfg = { \ - .zed_cfg = \ - { \ - .ed_timeout = ESP_ZB_ED_AGING_TIMEOUT_64MIN, \ - .keep_alive = 3000, \ - }, \ - }, \ +#define ZIGBEE_DEFAULT_ED_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = false, \ + .nwk_cfg = { \ + .zed_cfg = \ + { \ + .ed_timeout = ESP_ZB_ED_AGING_TIMEOUT_64MIN, \ + .keep_alive = 3000, \ + }, \ + }, \ } -#define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, \ - .install_code_policy = false, \ - .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = 10, \ - }, \ - } \ +#define ZIGBEE_DEFAULT_ROUTER_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, .install_code_policy = false, .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = 10, \ + }, \ + } \ } - -#define ZIGBEE_DEFAULT_COORDINATOR_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, \ - .install_code_policy = false, \ - .nwk_cfg = { \ - .zczr_cfg = \ - { \ - .max_children = 10, \ - }, \ - } \ +#define ZIGBEE_DEFAULT_COORDINATOR_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_COORDINATOR, .install_code_policy = false, .nwk_cfg = { \ + .zczr_cfg = \ + { \ + .max_children = 10, \ + }, \ + } \ } class ZigbeeCore { - private: - esp_zb_radio_config_t _radio_config; - esp_zb_host_config_t _host_config; - uint32_t _primary_channel_mask; - int16_t _scan_status; - - esp_zb_ep_list_t *_zb_ep_list; - zigbee_role_t _role; - bool _started; +private: + esp_zb_radio_config_t _radio_config; + esp_zb_host_config_t _host_config; + uint32_t _primary_channel_mask; + int16_t _scan_status; - uint8_t _open_network; - zigbee_scan_result_t *_scan_result; + esp_zb_ep_list_t *_zb_ep_list; + zigbee_role_t _role; + bool _started; - bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); - static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); - const char* getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); + uint8_t _open_network; + zigbee_scan_result_t *_scan_result; - public: - ZigbeeCore(); - ~ZigbeeCore(); + bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); + static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); + const char *getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); - std::list ep_objects; +public: + ZigbeeCore(); + ~ZigbeeCore(); - bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); - bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); - // bool end(); + std::list ep_objects; - bool isStarted() { return _started; } - zigbee_role_t getRole() { return _role; } + bool begin(zigbee_role_t role = ZIGBEE_END_DEVICE, bool erase_nvs = false); + bool begin(esp_zb_cfg_t *role_cfg, bool erase_nvs = false); + // bool end(); - void addEndpoint(ZigbeeEP *ep); - //void removeEndpoint(ZigbeeEP *ep); + bool isStarted() { + return _started; + } + zigbee_role_t getRole() { + return _role; + } - void setRadioConfig(esp_zb_radio_config_t config); - esp_zb_radio_config_t getRadioConfig(); + void addEndpoint(ZigbeeEP *ep); + //void removeEndpoint(ZigbeeEP *ep); - void setHostConfig(esp_zb_host_config_t config); - esp_zb_host_config_t getHostConfig(); + void setRadioConfig(esp_zb_radio_config_t config); + esp_zb_radio_config_t getRadioConfig(); - void setPrimaryChannelMask(uint32_t mask); - void setRebootOpenNetwork(uint8_t time); - void openNetwork(uint8_t time); + void setHostConfig(esp_zb_host_config_t config); + esp_zb_host_config_t getHostConfig(); - //scan_duration Time spent scanning each channel, in units of ((1 << scan_duration) + 1) * a beacon time. (15.36 microseconds) - void scanNetworks(uint32_t channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK, uint8_t scan_duration = 5); - // Zigbee scan complete status check, -2: failed or not started, -1: running, 0: no networks found, >0: number of networks found - int16_t scanComplete(); - zigbee_scan_result_t* getScanResult(); - void scanDelete(); + void setPrimaryChannelMask(uint32_t mask); + void setRebootOpenNetwork(uint8_t time); + void openNetwork(uint8_t time); - void factoryReset(); + //scan_duration Time spent scanning each channel, in units of ((1 << scan_duration) + 1) * a beacon time. (15.36 microseconds) + void scanNetworks(uint32_t channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK, uint8_t scan_duration = 5); + // Zigbee scan complete status check, -2: failed or not started, -1: running, 0: no networks found, >0: number of networks found + int16_t scanComplete(); + zigbee_scan_result_t *getScanResult(); + void scanDelete(); - // Friend function declaration to allow access to private members - friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct); + void factoryReset(); + // Friend function declaration to allow access to private members + friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct); }; extern ZigbeeCore Zigbee; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 1f5823a7bfd..af237739327 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -12,154 +12,151 @@ bool ZigbeeEP::_allow_multiple_binding = false; /* Zigbee End Device Class */ ZigbeeEP::ZigbeeEP(uint8_t endpoint) { - _endpoint = endpoint; - _ep_config.endpoint = 0; - _cluster_list = nullptr; + _endpoint = endpoint; + _ep_config.endpoint = 0; + _cluster_list = nullptr; #if !CONFIG_DISABLE_HAL_LOCKS - if (!lock) { - lock = xSemaphoreCreateBinary(); - if (lock == NULL) { - log_e("Semaphore creation failed"); - } + if (!lock) { + lock = xSemaphoreCreateBinary(); + if (lock == NULL) { + log_e("Semaphore creation failed"); } + } #endif } -ZigbeeEP::~ZigbeeEP() { - -} +ZigbeeEP::~ZigbeeEP() {} void ZigbeeEP::setVersion(uint8_t version) { - _ep_config.app_device_version = version; + _ep_config.app_device_version = version; } void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) { - // Convert manufacturer to ZCL string - size_t length = strlen(name); - if (length > 32) { - log_e("Manufacturer name is too long"); - return; - } - // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) - char* zb_name = new char[length + 2]; - // Store the length as the first element - zb_name[0] = static_cast(length); // Cast size_t to char - // Use memcpy to copy the characters to the result array - memcpy(zb_name + 1, name, length); - // Null-terminate the array - zb_name[length + 1] = '\0'; - - // Convert model to ZCL string - length = strlen(model); - if (length > 32) { - log_e("Model name is too long"); - delete[] zb_name; - return; - } - char* zb_model = new char[length + 2]; - zb_model[0] = static_cast(length); - memcpy(zb_model + 1, model, length); - zb_model[length + 1] = '\0'; - - // Get the basic cluster and update the manufacturer and model attributes - esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); - esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); + // Convert manufacturer to ZCL string + size_t length = strlen(name); + if (length > 32) { + log_e("Manufacturer name is too long"); + return; + } + // Allocate a new array of size length + 2 (1 for the length, 1 for null terminator) + char *zb_name = new char[length + 2]; + // Store the length as the first element + zb_name[0] = static_cast(length); // Cast size_t to char + // Use memcpy to copy the characters to the result array + memcpy(zb_name + 1, name, length); + // Null-terminate the array + zb_name[length + 1] = '\0'; + + // Convert model to ZCL string + length = strlen(model); + if (length > 32) { + log_e("Model name is too long"); + delete[] zb_name; + return; + } + char *zb_model = new char[length + 2]; + zb_model[0] = static_cast(length); + memcpy(zb_model + 1, model, length); + zb_model[length + 1] = '\0'; + + // Get the basic cluster and update the manufacturer and model attributes + esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name); + esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model); } -char* ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr) { - /* Read peer Manufacture Name & Model Identifier */ - 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_BASIC; +char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr) { + /* Read peer Manufacture Name & Model Identifier */ + 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_BASIC; - uint16_t attributes[] = { + uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, - }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); - read_req.attr_field = attributes; + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; + // clear read manufacturer + _read_manufacturer = nullptr; - // clear read manufacturer - _read_manufacturer = nullptr; - - esp_zb_zcl_read_attr_cmd_req(&read_req); - - //Wait for response or timeout - if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ - log_e("Error while reading manufacturer"); - } - return _read_manufacturer; + esp_zb_zcl_read_attr_cmd_req(&read_req); + //Wait for response or timeout + if (xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE) { + log_e("Error while reading manufacturer"); + } + return _read_manufacturer; } -char* ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { - /* Read peer Manufacture Name & Model Identifier */ - 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_BASIC; +char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { + /* Read peer Manufacture Name & Model Identifier */ + 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_BASIC; - uint16_t attributes[] = { + uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, - }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); - read_req.attr_field = attributes; + }; + read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_field = attributes; - // clear read model - _read_model = nullptr; + // clear read model + _read_model = nullptr; - esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_zcl_read_attr_cmd_req(&read_req); - //Wait for response or timeout - //Semaphore take - if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){ - log_e("Error while reading model"); - } - return _read_model; + //Wait for response or timeout + //Semaphore take + if (xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE) { + log_e("Error while reading model"); + } + return _read_model; } void ZigbeeEP::printBoundDevices() { - log_i("Bound devices:"); - for( [[maybe_unused]] const auto& device : _bound_devices) { - log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); - print_ieee_addr(device->ieee_addr); - } + log_i("Bound devices:"); + for ([[maybe_unused]] + const auto &device : _bound_devices) { + log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); + print_ieee_addr(device->ieee_addr); + } } void ZigbeeEP::zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute) { - /* Basic cluster attributes */ - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Manufacturer is \"%s\"", string); - _read_manufacturer = string; - xSemaphoreGive(lock); - } - if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { - zbstring_t *zbstr = (zbstring_t *)attribute->data.value; - char *string = (char *)malloc(zbstr->len + 1); - memcpy(string, zbstr->data, zbstr->len); - string[zbstr->len] = '\0'; - log_i("Peer Model is \"%s\"", string); - _read_model = string; - xSemaphoreGive(lock); - } + /* Basic cluster attributes */ + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Manufacturer is \"%s\"", string); + _read_manufacturer = string; + xSemaphoreGive(lock); + } + if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data.value) { + zbstring_t *zbstr = (zbstring_t *)attribute->data.value; + char *string = (char *)malloc(zbstr->len + 1); + memcpy(string, zbstr->data, zbstr->len); + string[zbstr->len] = '\0'; + log_i("Peer Model is \"%s\"", string); + _read_model = string; + xSemaphoreGive(lock); + } } void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) { - if (message->attribute.id == ESP_ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - _on_identify(*(uint16_t *)message->attribute.data.value); - } else { - log_w("Other identify commands are not implemented yet."); - } -} + if (message->attribute.id == ESP_ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + _on_identify(*(uint16_t *)message->attribute.data.value); + } else { + log_w("Other identify commands are not implemented yet."); + } +} -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index cdd52fbcd78..beb045559b3 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -8,30 +8,36 @@ #include /* Usefull defines */ -#define ZB_ARRAY_LENTH(arr) (sizeof(arr)/ sizeof(arr[0])) -#define print_ieee_addr(addr) log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) -#define XYZ_TO_RGB(X, Y, Z, r, g, b) \ -{ \ - r = (float)( 3.240479*(X) -1.537150*(Y) -0.498535*(Z)); \ - g = (float)(-0.969256*(X) +1.875992*(Y) +0.041556*(Z)); \ - b = (float)( 0.055648*(X) -0.204043*(Y) +1.057311*(Z)); \ - if(r > 1){r = 1;} \ - if(g > 1){g = 1;} \ - if(b > 1){b = 1;} \ -} - -#define RGB_TO_XYZ(r, g, b, X, Y, Z) \ -{ \ - X = (float)(0.412453*(r) + 0.357580*(g) + 0.180423*(b)); \ - Y = (float)(0.212671*(r) + 0.715160*(g) + 0.072169*(b)); \ - Z = (float)(0.019334*(r) + 0.119193*(g) + 0.950227*(b)); \ -} +#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) +#define print_ieee_addr(addr) \ + log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) +#define XYZ_TO_RGB(X, Y, Z, r, g, b) \ + { \ + r = (float)(3.240479 * (X) - 1.537150 * (Y) - 0.498535 * (Z)); \ + g = (float)(-0.969256 * (X) + 1.875992 * (Y) + 0.041556 * (Z)); \ + b = (float)(0.055648 * (X) - 0.204043 * (Y) + 1.057311 * (Z)); \ + if (r > 1) { \ + r = 1; \ + } \ + if (g > 1) { \ + g = 1; \ + } \ + if (b > 1) { \ + b = 1; \ + } \ + } + +#define RGB_TO_XYZ(r, g, b, X, Y, Z) \ + { \ + X = (float)(0.412453 * (r) + 0.357580 * (g) + 0.180423 * (b)); \ + Y = (float)(0.212671 * (r) + 0.715160 * (g) + 0.072169 * (b)); \ + Z = (float)(0.019334 * (r) + 0.119193 * (g) + 0.950227 * (b)); \ + } typedef struct zbstring_s { - uint8_t len; - char data[]; -} ESP_ZB_PACKED_STRUCT -zbstring_t; + uint8_t len; + char data[]; +} ESP_ZB_PACKED_STRUCT zbstring_t; typedef struct zb_device_params_s { esp_zb_ieee_addr_t ieee_addr; @@ -40,67 +46,79 @@ typedef struct zb_device_params_s { } zb_device_params_t; typedef enum { - SINGLE_COLOR = 0, - RGB = 1 + SINGLE_COLOR = 0, + RGB = 1 } zb_identify_led_type_t; /* Zigbee End Device Class */ class ZigbeeEP { - public: - ZigbeeEP(uint8_t endpoint = 10); - ~ZigbeeEP(); - - // Set ep config and cluster list - void setEpConfig(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { - _ep_config = ep_config; - _cluster_list = cluster_list; - } - - void setVersion(uint8_t version); - uint8_t getEndpoint() { return _endpoint; } - - void printBoundDevices(); - std::list getBoundDevices() const { return _bound_devices;} - - static bool isBound() { return _is_bound; } - static void allowMultipleBinding(bool bind) { _allow_multiple_binding = bind; } - - // Manufacturer name and model implemented - void setManufacturerAndModel(const char *name, const char *model); - - // Methods to read manufacturer and model name from selected endpoint and short address - char* readManufacturer(uint8_t endpoint, uint16_t short_addr); - char* readModel(uint8_t endpoint, uint16_t short_addr); - - bool epAllowMultipleBinding() { return _allow_multiple_binding; } - - // findEndpoind may be implemented by EPs to find and bind devices - virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; - - //list of all handlers function calls, to be overide 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 zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented - virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message); - - void onIdentify(void (*callback)(uint16_t)) { _on_identify = callback; } - - private: - static bool _allow_multiple_binding; - char* _read_manufacturer; - char* _read_model; - void (*_on_identify)(uint16_t time); - - protected: - static uint8_t _endpoint; - esp_zb_ha_standard_devices_t _device_id; - esp_zb_endpoint_config_t _ep_config; - esp_zb_cluster_list_t *_cluster_list; - static bool _is_bound; - std::list _bound_devices; - SemaphoreHandle_t lock; +public: + ZigbeeEP(uint8_t endpoint = 10); + ~ZigbeeEP(); + + // Set ep config and cluster list + void setEpConfig(esp_zb_endpoint_config_t ep_config, esp_zb_cluster_list_t *cluster_list) { + _ep_config = ep_config; + _cluster_list = cluster_list; + } + + void setVersion(uint8_t version); + uint8_t getEndpoint() { + return _endpoint; + } + + void printBoundDevices(); + std::list getBoundDevices() const { + return _bound_devices; + } + + static bool isBound() { + return _is_bound; + } + static void allowMultipleBinding(bool bind) { + _allow_multiple_binding = bind; + } + + // Manufacturer name and model implemented + void setManufacturerAndModel(const char *name, const char *model); + + // Methods to read manufacturer and model name from selected endpoint and short address + char *readManufacturer(uint8_t endpoint, uint16_t short_addr); + char *readModel(uint8_t endpoint, uint16_t short_addr); + + bool epAllowMultipleBinding() { + return _allow_multiple_binding; + } + + // findEndpoind may be implemented by EPs to find and bind devices + virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; + + //list of all handlers function calls, to be overide 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 zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented + virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message); + + void onIdentify(void (*callback)(uint16_t)) { + _on_identify = callback; + } + +private: + static bool _allow_multiple_binding; + char *_read_manufacturer; + char *_read_model; + void (*_on_identify)(uint16_t time); + +protected: + static uint8_t _endpoint; + esp_zb_ha_standard_devices_t _device_id; + esp_zb_endpoint_config_t _ep_config; + esp_zb_cluster_list_t *_cluster_list; + static bool _is_bound; + std::list _bound_devices; + SemaphoreHandle_t lock; friend class ZigbeeCore; }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index 692103709c8..9522b0ba1a8 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -12,15 +12,16 @@ static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_re static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_message_t *message); // Zigbee action handlers -[[maybe_unused]] static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { +[[maybe_unused]] +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { esp_err_t ret = ESP_OK; switch (callback_id) { - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; - case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; - case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; - case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; - case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break; - default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_set_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; + case ESP_ZB_CORE_REPORT_ATTR_CB_ID: ret = zb_attribute_reporting_handler((esp_zb_zcl_report_attr_message_t *)message); break; + case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: ret = zb_cmd_read_attr_resp_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_REPORT_CONFIG_RESP_CB_ID: ret = zb_configure_report_resp_handler((esp_zb_zcl_cmd_config_report_resp_message_t *)message); break; + case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break; + default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break; } return ret; } @@ -39,13 +40,12 @@ static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_messag ); // List through all Zigbee EPs and call the callback function, with the message - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { - if (message->info.dst_endpoint == (*it)->getEndpoint()){ - if(message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY){ - (*it)->zbIdentify(message); //method zbIdentify implemented in the common EP class - } - else { - (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if (message->info.dst_endpoint == (*it)->getEndpoint()) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY) { + (*it)->zbIdentify(message); //method zbIdentify implemented in the common EP class + } else { + (*it)->zbAttributeSet(message); //method zbAttributeSet must be implemented in specific EP class } } } @@ -63,10 +63,10 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes "Received report from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->src_address.u.short_addr, message->src_endpoint, message->dst_endpoint, message->cluster ); - // List through all Zigbee EPs and call the callback function, with the message - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + // List through all Zigbee EPs and call the callback function, with the message + for (std::list::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); //method zbAttributeRead must be implemented in specific EP class } } return ESP_OK; @@ -84,7 +84,7 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster ); - for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->info.dst_endpoint == (*it)->getEndpoint()) { esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables; while (variable) { @@ -94,10 +94,9 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re ); if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) { if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_BASIC) { - (*it)->zbReadBasicCluster(&variable->attribute); //method zbReadBasicCluster implemented in the common EP class - } - else { - (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class + (*it)->zbReadBasicCluster(&variable->attribute); //method zbReadBasicCluster implemented in the common EP class + } else { + (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class } } variable = variable->next; @@ -133,10 +132,10 @@ static esp_err_t zb_cmd_default_resp_handler(const esp_zb_zcl_cmd_default_resp_m log_e("Received message: error status(%d)", message->info.status); } log_v( - "Received default response: from address(0x%x), src_endpoint(%d) to dst_endpoint(%d), cluster(0x%x) with status 0x%x", message->info.src_address.u.short_addr, - message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster, message->status_code + "Received default response: from address(0x%x), src_endpoint(%d) to dst_endpoint(%d), cluster(0x%x) with status 0x%x", + message->info.src_address.u.short_addr, message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster, message->status_code ); return ESP_OK; } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index 745b022ea82..b823d3879d1 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -2,115 +2,111 @@ #if SOC_IEEE802154_SUPPORTED ZigbeeColorDimmableLight::ZigbeeColorDimmableLight(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; + _device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID; - esp_zb_color_dimmable_light_cfg_t light_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); - _cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg); - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, - .app_device_version = 0 - }; + esp_zb_color_dimmable_light_cfg_t light_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); + _cluster_list = esp_zb_color_dimmable_light_clusters_create(&light_cfg); + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMABLE_LIGHT_DEVICE_ID, .app_device_version = 0 + }; - //set default values - _current_state = false; - _current_level = 255; - _current_red = 255; - _current_green = 255; - _current_blue = 255; + //set default values + _current_state = false; + _current_level = 255; + _current_red = 255; + _current_green = 255; + _current_blue = 255; } -uint16_t ZigbeeColorDimmableLight::getCurrentColorX(){ - return (*(uint16_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID)->data_p); +uint16_t ZigbeeColorDimmableLight::getCurrentColorX() { + return (*(uint16_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID + ) + ->data_p); } -uint16_t ZigbeeColorDimmableLight::getCurrentColorY(){ - return (*(uint16_t *)esp_zb_zcl_get_attribute(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID)->data_p); +uint16_t ZigbeeColorDimmableLight::getCurrentColorY() { + return (*(uint16_t *)esp_zb_zcl_get_attribute( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID + ) + ->data_p); } -void ZigbeeColorDimmableLight::calculateRGB( uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue){ - float r, g, b, color_x, color_y; - color_x = (float)x / 65535; - color_y = (float)y / 65535; - - float color_X = color_x / color_y; - float color_Z = (1 - color_x - color_y) / color_y; +void ZigbeeColorDimmableLight::calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue) { + float r, g, b, color_x, color_y; + color_x = (float)x / 65535; + color_y = (float)y / 65535; - XYZ_TO_RGB(color_X, 1, color_Z, r, g, b); + float color_X = color_x / color_y; + float color_Z = (1 - color_x - color_y) / color_y; - red = (uint8_t)(r * (float)255); - green = (uint8_t)(g * (float)255); - blue = (uint8_t)(b * (float)255); + XYZ_TO_RGB(color_X, 1, color_Z, r, g, b); + + red = (uint8_t)(r * (float)255); + green = (uint8_t)(g * (float)255); + blue = (uint8_t)(b * (float)255); } //set attribude method -> methon overriden in child class void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { - //check the data and call right method - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - if(_current_state != *(bool *)message->attribute.data.value) { - _current_state = *(bool *)message->attribute.data.value; - lightChanged(); - } - return; - } - else { - log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); - } + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + if (_current_state != *(bool *)message->attribute.data.value) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } - else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { - if (_current_level != *(uint8_t *)message->attribute.data.value) { - _current_level = *(uint8_t *)message->attribute.data.value; - lightChanged(); - } - return; - } - else { - log_w("Recieved message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); - //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h - } + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + if (_current_level != *(uint8_t *)message->attribute.data.value) { + _current_level = *(uint8_t *)message->attribute.data.value; + lightChanged(); + } + return; + } else { + log_w("Recieved message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h } - else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value); - uint16_t light_color_y = getCurrentColorY(); - //calculate RGB from XY and call setColor() - uint8_t red, green, blue; - calculateRGB(light_color_x, light_color_y, red, green, blue); - _current_blue = blue; - _current_green = green; - _current_red = red; - lightChanged(); - return; + } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + uint16_t light_color_x = (*(uint16_t *)message->attribute.data.value); + uint16_t light_color_y = getCurrentColorY(); + //calculate RGB from XY and call setColor() + uint8_t red, green, blue; + calculateRGB(light_color_x, light_color_y, red, green, blue); + _current_blue = blue; + _current_green = green; + _current_red = red; + lightChanged(); + return; - } - else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { - uint16_t light_color_x = getCurrentColorX(); - uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value); - //calculate RGB from XY and call setColor() - uint8_t red, green, blue; - calculateRGB(light_color_x, light_color_y, red, green, blue); - _current_blue = blue; - _current_green = green; - _current_red = red; - lightChanged(); - return; - } - else { - log_w("Recieved message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); - } - } - else { - log_w("Recieved message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); + } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { + uint16_t light_color_x = getCurrentColorX(); + uint16_t light_color_y = (*(uint16_t *)message->attribute.data.value); + //calculate RGB from XY and call setColor() + uint8_t red, green, blue; + calculateRGB(light_color_x, light_color_y, red, green, blue); + _current_blue = blue; + _current_green = green; + _current_red = red; + lightChanged(); + return; + } else { + log_w("Recieved message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); } + } else { + log_w("Recieved message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); + } } void ZigbeeColorDimmableLight::lightChanged() { - if(_on_light_change) { - _on_light_change(_current_state, _current_red, _current_green, _current_blue, _current_level); - } + if (_on_light_change) { + _on_light_change(_current_state, _current_red, _current_green, _current_blue, _current_level); + } } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h index b46aff75bee..992c2573654 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.h @@ -9,29 +9,33 @@ #include "ha/esp_zigbee_ha_standard.h" class ZigbeeColorDimmableLight : public ZigbeeEP { - public: - ZigbeeColorDimmableLight(uint8_t endpoint); - ~ZigbeeColorDimmableLight(); - - void onLightChange(void (*callback)(bool, uint8_t, uint8_t, uint8_t, uint8_t)) { _on_light_change = callback; } - void restoreLight() { lightChanged(); } - - private: - void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; - void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); - - uint16_t getCurrentColorX(); - uint16_t getCurrentColorY(); - - void lightChanged(); - //callback function to be called on light change (State, R, G, B, Level) - void (*_on_light_change)(bool, uint8_t, uint8_t, uint8_t, uint8_t); - - bool _current_state; - uint8_t _current_level; - uint16_t _current_red; - uint16_t _current_green; - uint16_t _current_blue; +public: + ZigbeeColorDimmableLight(uint8_t endpoint); + ~ZigbeeColorDimmableLight(); + + void onLightChange(void (*callback)(bool, uint8_t, uint8_t, uint8_t, uint8_t)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + void calculateRGB(uint16_t x, uint16_t y, uint8_t &red, uint8_t &green, uint8_t &blue); + + uint16_t getCurrentColorX(); + uint16_t getCurrentColorY(); + + void lightChanged(); + //callback function to be called on light change (State, R, G, B, Level) + void (*_on_light_change)(bool, uint8_t, uint8_t, uint8_t, uint8_t); + + bool _current_state; + uint8_t _current_level; + uint16_t _current_red; + uint16_t _current_green; + uint16_t _current_blue; }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 76a97d8e84c..c30599aadac 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -2,405 +2,402 @@ #if SOC_IEEE802154_SUPPORTED // Initialize the static instance pointer -ZigbeeColorDimmerSwitch* ZigbeeColorDimmerSwitch::_instance = nullptr; +ZigbeeColorDimmerSwitch *ZigbeeColorDimmerSwitch::_instance = nullptr; ZigbeeColorDimmerSwitch::ZigbeeColorDimmerSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; - _instance = this; // Set the static pointer to this instance - - esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); - _cluster_list = esp_zb_color_dimmable_switch_clusters_create(&switch_cfg); - - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID, - .app_device_version = 0 - }; + _device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID; + _instance = this; // Set the static pointer to this instance + + esp_zb_color_dimmable_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_COLOR_DIMMABLE_SWITCH_CONFIG(); + _cluster_list = esp_zb_color_dimmable_switch_clusters_create(&switch_cfg); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_COLOR_DIMMER_SWITCH_DEVICE_ID, .app_device_version = 0 + }; } void ZigbeeColorDimmerSwitch::calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y) { - // Convert RGB to XYZ - float r = (float)red / 255.0f; - float g = (float)green / 255.0f; - float b = (float)blue / 255.0f; + // Convert RGB to XYZ + float r = (float)red / 255.0f; + float g = (float)green / 255.0f; + float b = (float)blue / 255.0f; - float X, Y, Z; - RGB_TO_XYZ(r, g, b, X, Y, Z); + float X, Y, Z; + RGB_TO_XYZ(r, g, b, X, Y, Z); - // Convert XYZ to xy chromaticity coordinates - float color_x = X / (X + Y + Z); - float color_y = Y / (X + Y + Z); + // Convert XYZ to xy chromaticity coordinates + float color_x = X / (X + Y + Z); + float color_y = Y / (X + Y + Z); - // Convert normalized xy to 16-bit values - x = (uint16_t)(color_x * 65535.0f); - y = (uint16_t)(color_y * 65535.0f); + // Convert normalized xy to 16-bit values + x = (uint16_t)(color_x * 65535.0f); + y = (uint16_t)(color_y * 65535.0f); } void ZigbeeColorDimmerSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Bound successfully!"); - if (user_ctx) { - zb_device_params_t *light = (zb_device_params_t *)user_ctx; - log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - _instance->_bound_devices.push_back(light); - } - _is_bound = true; - } else { - log_e("Binding failed!"); + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + zb_device_params_t *light = (zb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + _instance->_bound_devices.push_back(light); } + _is_bound = true; + } else { + log_e("Binding failed!"); + } } void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req; - zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); - light->endpoint = endpoint; - light->short_addr = addr; - esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); - esp_zb_get_long_address(bind_req.src_address); - bind_req.src_endp = _endpoint; - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; - bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req.dst_endp = endpoint; - bind_req.req_dst_addr = esp_zb_get_short_address(); - log_v("Try to bind on/off control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; - log_v("Try to bind level control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; - log_v("Try to bind color control of dimmable light"); - esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); - } else { - log_v("No color dimmable light endpoint found"); - } + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = _endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_v("Try to bind on/off control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL; + log_v("Try to bind level control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, NULL); + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL; + log_v("Try to bind color control of dimmable light"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); + } else { + log_v("No color dimmable light endpoint found"); + } } // find on_off light endpoint void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, - ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL}; - esp_zb_zdo_match_desc_req_param_t color_dimmable_light_req = { - .dst_nwk_addr = cmd_req->dst_nwk_addr, - .addr_of_interest = cmd_req->addr_of_interest, - .profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .num_in_clusters = 3, - .num_out_clusters = 3, - .cluster_list = cluster_list, - }; - esp_zb_zdo_match_cluster(&color_dimmable_light_req, findCb, NULL); + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL, + ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL}; + esp_zb_zdo_match_desc_req_param_t color_dimmable_light_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 3, + .num_out_clusters = 3, + .cluster_list = cluster_list, + }; + esp_zb_zdo_match_cluster(&color_dimmable_light_req, findCb, NULL); } // Methods to control the light void ZigbeeColorDimmerSwitch::lightToggle() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light toggle' command"); - //esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - //esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light toggle' command"); + //esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + //esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to group address 0x%x", group_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOn() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light on' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light on' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to group address 0x%x", group_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOff() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light off' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to group address 0x%x", group_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } 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; - 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; - cmd_req.effect_variant = effect_variant; - log_i("Sending 'light off with effect' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + 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; + cmd_req.effect_variant = effect_variant; + log_i("Sending 'light off with effect' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { - if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; - cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - log_i("Sending 'light on with scene recall' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_i("Sending 'light on with scene recall' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } 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; - 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 - cmd_req.on_time = time_on; - cmd_req.off_wait_time = time_off; - log_i("Sending 'light on with time off' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + 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 + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_i("Sending 'light on with time off' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { - if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; - 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; - cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + 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; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; - 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; - cmd_req.level = level; - cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command to group address 0x%x", group_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + 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; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } 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; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.level = level; - cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_move_to_level_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_i("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue) { - if (_is_bound) { - //Convert RGB to XY - uint16_t color_x, color_y; - calculateXY(red, green, blue, color_x, color_y); - - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; - 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 = color_x; - cmd_req.color_y = color_y; - cmd_req.transition_time = 0; - log_i("Sending 'set light color' command"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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 = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr) { - if (_is_bound) { - //Convert RGB to XY - uint16_t color_x, color_y; - calculateXY(red, green, blue, color_x, color_y); - - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; - 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; - cmd_req.color_x = color_x; - cmd_req.color_y = color_y; - cmd_req.transition_time = 0; - log_i("Sending 'set light color' command to group address 0x%x", group_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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; + cmd_req.color_x = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - //Convert RGB to XY - uint16_t color_x, color_y; - calculateXY(red, green, blue, color_x, color_y); - - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.color_x = color_x; - cmd_req.color_y = color_y; - cmd_req.transition_time = 0; - log_i("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); - esp_zb_lock_release(); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.color_x = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_i("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index fb75e2125c8..2263f3235ca 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -9,52 +9,52 @@ #include "ha/esp_zigbee_ha_standard.h" class ZigbeeColorDimmerSwitch : public ZigbeeEP { - public: - ZigbeeColorDimmerSwitch(uint8_t endpoint); - ~ZigbeeColorDimmerSwitch(); +public: + ZigbeeColorDimmerSwitch(uint8_t endpoint); + ~ZigbeeColorDimmerSwitch(); - // methods to control the color dimmable light - void lightToggle(); - void lightToggle(uint16_t group_addr); - void lightToggle(uint8_t endpoint, uint16_t short_addr); + // methods to control the color dimmable light + void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); - void lightOn(); - void lightOn(uint16_t group_addr); - void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); - void lightOff(); - void lightOff(uint16_t group_addr); - void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); - void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); - void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); - void lightOnWithSceneRecall(); + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); - void setLightLevel(uint8_t level); - void setLightLevel(uint8_t level, uint16_t group_addr); - void setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr); + void setLightLevel(uint8_t level); + void setLightLevel(uint8_t level, uint16_t group_addr); + void setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr); - void setLightColor(uint8_t red, uint8_t green, uint8_t blue); - void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr); - void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); - void setLightColorSaturation(uint8_t value); - void setLightColorSaturation(uint8_t value, uint16_t group_addr); - void setLightColorSaturation(uint8_t value, uint8_t endpoint, uint16_t short_addr); + void setLightColorSaturation(uint8_t value); + void setLightColorSaturation(uint8_t value, uint16_t group_addr); + void setLightColorSaturation(uint8_t value, uint8_t endpoint, uint16_t short_addr); - void setLightColorHue(uint8_t value); - void setLightColorHue(uint8_t value, uint16_t group_addr); - void setLightColorHue(uint8_t value, uint8_t endpoint, uint16_t short_addr); + void setLightColorHue(uint8_t value); + void setLightColorHue(uint8_t value, uint16_t group_addr); + void setLightColorHue(uint8_t value, uint8_t endpoint, uint16_t short_addr); - private: - // save instance of the class in order to use it in static functions - static ZigbeeColorDimmerSwitch* _instance; +private: + // save instance of the class in order to use it in static functions + static ZigbeeColorDimmerSwitch *_instance; - void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); + void calculateXY(uint8_t red, uint8_t green, uint8_t blue, uint16_t &x, uint16_t &y); }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 75e72bbac35..108faee5dc3 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -2,41 +2,34 @@ #if SOC_IEEE802154_SUPPORTED ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; + _device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; - esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); - _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, - .app_device_version = 0 - }; + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + _cluster_list = esp_zb_on_off_light_clusters_create(&light_cfg); // use esp_zb_zcl_cluster_list_create() instead of esp_zb_on_off_light_clusters_create() + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, .app_device_version = 0}; } //set attribude method -> methon overriden in child class void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { - //check the data and call right method - if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - _current_state = *(bool *)message->attribute.data.value; - lightChanged(); - } - else { - log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); - } - } - else { - log_w("Recieved message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + //check the data and call right method + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + _current_state = *(bool *)message->attribute.data.value; + lightChanged(); + } else { + log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } + } else { + log_w("Recieved message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + } } void ZigbeeLight::lightChanged() { - if(_on_light_change) { - _on_light_change(_current_state); - } else { - log_w("No callback function set for light change"); - } + if (_on_light_change) { + _on_light_change(_current_state); + } else { + log_w("No callback function set for light change"); + } } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.h b/libraries/Zigbee/src/ep/ZigbeeLight.h index 20b1e71ea9b..32e4e8c9bdc 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.h +++ b/libraries/Zigbee/src/ep/ZigbeeLight.h @@ -9,21 +9,25 @@ #include "ha/esp_zigbee_ha_standard.h" class ZigbeeLight : public ZigbeeEP { - public: - ZigbeeLight(uint8_t endpoint); - ~ZigbeeLight(); - - // Use tp set a cb function to be called on light change - void onLightChange(void (*callback)(bool)) { _on_light_change = callback; } - void restoreLight() { lightChanged(); } - - private: - void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; - //callback function to be called on light change - void (*_on_light_change)(bool); - void lightChanged(); - - bool _current_state; +public: + ZigbeeLight(uint8_t endpoint); + ~ZigbeeLight(); + + // Use tp set a cb function to be called on light change + void onLightChange(void (*callback)(bool)) { + _on_light_change = callback; + } + void restoreLight() { + lightChanged(); + } + +private: + void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override; + //callback function to be called on light change + void (*_on_light_change)(bool); + void lightChanged(); + + bool _current_state; }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 15b1ce89de0..9152732e376 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -2,237 +2,232 @@ #if SOC_IEEE802154_SUPPORTED // Initialize the static instance pointer -ZigbeeSwitch* ZigbeeSwitch::_instance = nullptr; +ZigbeeSwitch *ZigbeeSwitch::_instance = nullptr; ZigbeeSwitch::ZigbeeSwitch(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; - _instance = this; // Set the static pointer to this instance + _device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID; + _instance = this; // Set the static pointer to this instance - esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); - _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); + esp_zb_on_off_switch_cfg_t switch_cfg = ESP_ZB_DEFAULT_ON_OFF_SWITCH_CONFIG(); + _cluster_list = esp_zb_on_off_switch_clusters_create(&switch_cfg); - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, - .app_device_version = 0 - }; + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_SWITCH_DEVICE_ID, .app_device_version = 0}; } void ZigbeeSwitch::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_i("Bound successfully!"); - if (user_ctx) { - zb_device_params_t *light = (zb_device_params_t *)user_ctx; - log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); - _instance->_bound_devices.push_back(light); - } - _is_bound = true; + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_i("Bound successfully!"); + if (user_ctx) { + zb_device_params_t *light = (zb_device_params_t *)user_ctx; + log_i("The light originating from address(0x%x) on endpoint(%d)", light->short_addr, light->endpoint); + _instance->_bound_devices.push_back(light); } + _is_bound = true; + } } void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) { - if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req; - zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); - light->endpoint = endpoint; - light->short_addr = addr; - esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); - esp_zb_get_long_address(bind_req.src_address); - bind_req.src_endp = _endpoint; //_dev_endpoint; - bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; - bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; - memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); - bind_req.dst_endp = endpoint; - bind_req.req_dst_addr = esp_zb_get_short_address(); - log_i("Try to bind On/Off"); - esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); - } else { - log_d("No light endpoint found"); - } + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + log_d("Found light endpoint"); + esp_zb_zdo_bind_req_param_t bind_req; + zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); + light->endpoint = endpoint; + light->short_addr = addr; + esp_zb_ieee_address_by_short(light->short_addr, light->ieee_addr); + esp_zb_get_long_address(bind_req.src_address); + bind_req.src_endp = _endpoint; //_dev_endpoint; + bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF; + bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED; + memcpy(bind_req.dst_address_u.addr_long, light->ieee_addr, sizeof(esp_zb_ieee_addr_t)); + bind_req.dst_endp = endpoint; + bind_req.req_dst_addr = esp_zb_get_short_address(); + log_i("Try to bind On/Off"); + esp_zb_zdo_device_bind_req(&bind_req, bindCb, (void *)light); + } else { + log_d("No light endpoint found"); + } } // find on_off light endpoint void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { - uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF}; - esp_zb_zdo_match_desc_req_param_t on_off_req = { - .dst_nwk_addr = cmd_req->dst_nwk_addr, - .addr_of_interest = cmd_req->addr_of_interest, - .profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .num_in_clusters = 1, - .num_out_clusters = 1, - .cluster_list = cluster_list, - }; + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF}; + esp_zb_zdo_match_desc_req_param_t on_off_req = { + .dst_nwk_addr = cmd_req->dst_nwk_addr, + .addr_of_interest = cmd_req->addr_of_interest, + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + .num_in_clusters = 1, + .num_out_clusters = 1, + .cluster_list = cluster_list, + }; - esp_zb_zdo_match_cluster(&on_off_req, findCb, NULL); + esp_zb_zdo_match_cluster(&on_off_req, findCb, NULL); } // Methods to control the light void ZigbeeSwitch::lightToggle() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light toggle' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light toggle' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightToggle(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to group address 0x%x", group_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOn() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light on' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light on' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOn(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to group address 0x%x", group_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOff() { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - log_i("Sending 'light off' command"); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + log_i("Sending 'light off' command"); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOff(uint16_t group_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to group address 0x%x", group_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { - if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; - 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; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; - cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); - esp_zb_zcl_on_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_cmd_t cmd_req; + 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; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } 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; - 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; - cmd_req.effect_variant = effect_variant; - log_i("Sending 'light off with effect' command"); - esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + 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; + cmd_req.effect_variant = effect_variant; + log_i("Sending 'light off with effect' command"); + esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } void ZigbeeSwitch::lightOnWithSceneRecall() { - if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; - cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; - cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - log_i("Sending 'light on with scene recall' command"); - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } + if (_is_bound) { + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; + cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; + log_i("Sending 'light on with scene recall' command"); + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } } 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; - 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 - cmd_req.on_time = time_on; - cmd_req.off_wait_time = time_off; - log_i("Sending 'light on with time off' command"); - esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); - } else { - log_e("Light not bound"); - } -} - -#endif //SOC_IEEE802154_SUPPORTED + if (_is_bound) { + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + 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 + cmd_req.on_time = time_on; + cmd_req.off_wait_time = time_off; + log_i("Sending 'light on with time off' command"); + esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + } else { + log_e("Light not bound"); + } +} + +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h index 322c7b7443b..bbc6c0a91dc 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -9,35 +9,34 @@ #include "ha/esp_zigbee_ha_standard.h" class ZigbeeSwitch : public ZigbeeEP { - public: - ZigbeeSwitch(uint8_t endpoint); - ~ZigbeeSwitch(); - - // methods to control the on/off light - void lightToggle(); - void lightToggle(uint16_t group_addr); - void lightToggle(uint8_t endpoint, uint16_t short_addr); - - void lightOn(); - void lightOn(uint16_t group_addr); - void lightOn(uint8_t endpoint, uint16_t short_addr); - - void lightOff(); - void lightOff(uint16_t group_addr); - void lightOff(uint8_t endpoint, uint16_t short_addr); - - void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); - void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); - void lightOnWithSceneRecall(); - - private: - // save instance of the class in order to use it in static functions - static ZigbeeSwitch* _instance; - - void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - +public: + ZigbeeSwitch(uint8_t endpoint); + ~ZigbeeSwitch(); + + // methods to control the on/off light + void lightToggle(); + void lightToggle(uint16_t group_addr); + void lightToggle(uint8_t endpoint, uint16_t short_addr); + + void lightOn(); + void lightOn(uint16_t group_addr); + void lightOn(uint8_t endpoint, uint16_t short_addr); + + void lightOff(); + void lightOff(uint16_t group_addr); + void lightOff(uint8_t endpoint, uint16_t short_addr); + + void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); + void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); + void lightOnWithSceneRecall(); + +private: + // save instance of the class in order to use it in static functions + static ZigbeeSwitch *_instance; + + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index e4bba80246d..e0dba03da5c 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -2,17 +2,14 @@ #if SOC_IEEE802154_SUPPORTED ZigbeeTempSensor::ZigbeeTempSensor(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; + _device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; - esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); - _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); - - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, - .app_device_version = 0 - }; + esp_zb_temperature_sensor_cfg_t temp_sensor_cfg = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); + _cluster_list = esp_zb_temperature_sensor_clusters_create(&temp_sensor_cfg); + + _ep_config = { + .endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID, .app_device_version = 0 + }; } static int16_t zb_temperature_to_s16(float temp) { @@ -20,73 +17,77 @@ static int16_t zb_temperature_to_s16(float temp) { } void ZigbeeTempSensor::setMinMaxValue(float min, float max) { - int16_t zb_min = zb_temperature_to_s16(min); - int16_t zb_max = zb_temperature_to_s16(max); - esp_zb_attribute_list_t *temp_measure_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); - esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); + int16_t zb_min = zb_temperature_to_s16(min); + int16_t zb_max = zb_temperature_to_s16(max); + esp_zb_attribute_list_t *temp_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, (void *)&zb_min); + esp_zb_cluster_update_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, (void *)&zb_max); } void ZigbeeTempSensor::setTolerance(float tolerance) { - // Convert tolerance to ZCL uint16_t - uint16_t zb_tolerance = (uint16_t)(tolerance * 100); - esp_zb_attribute_list_t *temp_measure_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); + // Convert tolerance to ZCL uint16_t + uint16_t zb_tolerance = (uint16_t)(tolerance * 100); + esp_zb_attribute_list_t *temp_measure_cluster = + esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_temperature_meas_cluster_add_attr(temp_measure_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID, (void *)&zb_tolerance); } void ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval, float delta) { - esp_zb_zcl_reporting_info_t reporting_info = { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .ep = _endpoint, - .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, - .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, - .attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, - .u = - { - .send_info = - { - .min_interval = min_interval, - .max_interval = max_interval, - .delta = - { - .u16 = (uint16_t)(delta * 100), // Convert delta to ZCL uint16_t - }, - .def_min_interval = min_interval, - .def_max_interval = max_interval, - }, - }, - .dst = - { - .profile_id = ESP_ZB_AF_HA_PROFILE_ID, - }, - .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, - }; + esp_zb_zcl_reporting_info_t reporting_info = { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .ep = _endpoint, + .cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, + .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, + .attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .u = + { + .send_info = + { + .min_interval = min_interval, + .max_interval = max_interval, + .delta = + { + .u16 = (uint16_t)(delta * 100), // Convert delta to ZCL uint16_t + }, + .def_min_interval = min_interval, + .def_max_interval = max_interval, + }, + }, + .dst = + { + .profile_id = ESP_ZB_AF_HA_PROFILE_ID, + }, + .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, + }; esp_zb_zcl_update_reporting_info(&reporting_info); } void ZigbeeTempSensor::setTemperature(float temperature) { - int16_t zb_temperature = zb_temperature_to_s16(temperature); - log_v("Updating temperature sensor value..."); - /* Update temperature sensor measured value */ - log_d("Setting temperature to %d", zb_temperature); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false); - esp_zb_lock_release(); + int16_t zb_temperature = zb_temperature_to_s16(temperature); + log_v("Updating temperature sensor value..."); + /* Update temperature sensor measured value */ + log_d("Setting temperature to %d", zb_temperature); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_set_attribute_val( + _endpoint, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &zb_temperature, false + ); + esp_zb_lock_release(); } void ZigbeeTempSensor::reportTemperature() { - /* 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_TEMP_MEASUREMENT_VALUE_ID; - report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; - report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; - report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + /* 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_TEMP_MEASUREMENT_VALUE_ID; + report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; + report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint; - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); - esp_zb_lock_release(); - log_v("Temperature report sent"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd); + esp_zb_lock_release(); + log_v("Temperature report sent"); } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h index 2f15e6029f6..22317721fc4 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.h +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.h @@ -9,22 +9,22 @@ #include "ha/esp_zigbee_ha_standard.h" class ZigbeeTempSensor : public ZigbeeEP { - public: - ZigbeeTempSensor(uint8_t endpoint); - ~ZigbeeTempSensor(); +public: + ZigbeeTempSensor(uint8_t endpoint); + ~ZigbeeTempSensor(); - // Set the temperature value in 0,01°C - void setTemperature(float value); + // Set the temperature value in 0,01°C + void setTemperature(float value); - // Set the min and max value for the temperature sensor in 0,01°C - void setMinMaxValue(float min, float max); + // Set the min and max value for the temperature sensor in 0,01°C + void setMinMaxValue(float min, float max); - // Set the tolerance value for the temperature sensor in 0,01°C - void setTolerance(float tolerance); + // Set the tolerance value for the temperature sensor in 0,01°C + void setTolerance(float tolerance); - // Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C) - void setReporting(uint16_t min_interval, uint16_t max_interval, float delta); - void reportTemperature(); + // Set the reporting interval for temperature measurement in seconds and delta (temp change in 0,01 °C) + void setReporting(uint16_t min_interval, uint16_t max_interval, float delta); + void reportTemperature(); }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index 86c1a8fc18c..28ed2a70cd2 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -6,46 +6,40 @@ static float zb_s16_to_temperature(int16_t value) { } // Initialize the static instance of the class -ZigbeeThermostat* ZigbeeThermostat::_instance = nullptr; +ZigbeeThermostat *ZigbeeThermostat::_instance = nullptr; ZigbeeThermostat::ZigbeeThermostat(uint8_t endpoint) : ZigbeeEP(endpoint) { - _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; - _instance = this; // Set the static pointer to this instance - - //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk - esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); - - //use custom cluster creating to accept reportings from temperature sensor - _cluster_list = esp_zb_zcl_cluster_list_create(); - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat_cfg.basic_cfg)); - esp_zb_cluster_list_add_basic_cluster(_cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(&(thermostat_cfg.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); - esp_zb_cluster_list_add_thermostat_cluster(_cluster_list, esp_zb_thermostat_cluster_create(&(thermostat_cfg.thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - /* Add temperature measurement cluster for attribute reporting */ - esp_zb_cluster_list_add_temperature_meas_cluster(_cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); - - _ep_config = { - .endpoint = _endpoint, - .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, - .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, - .app_device_version = 0 - }; + _device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID; + _instance = this; // Set the static pointer to this instance + + //use custom config to avoid narrowing error -> must be fixed in zigbee-sdk + esp_zb_thermostat_cfg_t thermostat_cfg = ZB_DEFAULT_THERMOSTAT_CONFIG(); + + //use custom cluster creating to accept reportings from temperature sensor + _cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(thermostat_cfg.basic_cfg)); + esp_zb_cluster_list_add_basic_cluster(_cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(&(thermostat_cfg.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + esp_zb_cluster_list_add_thermostat_cluster(_cluster_list, esp_zb_thermostat_cluster_create(&(thermostat_cfg.thermostat_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + /* Add temperature measurement cluster for attribute reporting */ + esp_zb_cluster_list_add_temperature_meas_cluster(_cluster_list, esp_zb_temperature_meas_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE); + + _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_THERMOSTAT_DEVICE_ID, .app_device_version = 0}; } void ZigbeeThermostat::bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx) { if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { - if (user_ctx) { - zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; - log_i("The temperature sensor originating from address(0x%x) on endpoint(%d)", sensor->short_addr, sensor->endpoint); - _instance->_bound_devices.push_back(sensor); - } - else { - log_v("Local binding success"); - } - _is_bound = true; + if (user_ctx) { + zb_device_params_t *sensor = (zb_device_params_t *)user_ctx; + log_i("The temperature sensor originating from address(0x%x) on endpoint(%d)", sensor->short_addr, sensor->endpoint); + _instance->_bound_devices.push_back(sensor); + } else { + log_v("Local binding success"); + } + _is_bound = true; } else { - log_e("Binding failed!"); + log_e("Binding failed!"); } } @@ -97,20 +91,20 @@ void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uin } void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) { - uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; - param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; - param->num_in_clusters = 1; - param->num_out_clusters = 0; - param->cluster_list = cluster_list; - esp_zb_zdo_match_cluster(param, findCb, NULL); + uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT}; + param->profile_id = ESP_ZB_AF_HA_PROFILE_ID; + param->num_in_clusters = 1; + param->num_out_clusters = 0; + param->cluster_list = cluster_list; + esp_zb_zdo_match_cluster(param, findCb, NULL); } void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { - static uint8_t read_config = 0; - if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) { + 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) { int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - if(_on_temp_recieve){ + if (_on_temp_recieve) { _on_temp_recieve(zb_s16_to_temperature(value)); } } @@ -129,88 +123,83 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att _tolerance = 1.0 * tolerance / 100; read_config++; } - if(read_config == 3){ + if (read_config == 3) { read_config = 0; xSemaphoreGive(lock); } } } -void ZigbeeThermostat::getTemperature(){ - /* 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_DST_ADDR_ENDP_NOT_PRESENT; - read_req.zcl_basic_cmd.src_endpoint = _endpoint; - 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"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_read_attr_cmd_req(&read_req); - esp_zb_lock_release(); +void ZigbeeThermostat::getTemperature() { + /* 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_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + 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"); + 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; - 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; - - 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 temperature' 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, portMAX_DELAY) != 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() { + /* 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_DST_ADDR_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + 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 temperature' 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, portMAX_DELAY) != 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::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta){ +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; - 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; - - int16_t report_change = (int16_t)delta * 100; - esp_zb_zcl_config_report_record_t records[] = { - { - .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, - .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"); - esp_zb_lock_acquire(portMAX_DELAY); - esp_zb_zcl_config_report_cmd_req(&report_cmd); - esp_zb_lock_release(); + esp_zb_zcl_config_report_cmd_t report_cmd; + 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; + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, + .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"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); } -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h index f0c1b5588e1..7d63cd9f726 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -9,53 +9,56 @@ #include "ha/esp_zigbee_ha_standard.h" //define the thermostat configuration to avoid narrowing conversion issue in zigbee-sdk -#define ZB_DEFAULT_THERMOSTAT_CONFIG() \ - { \ - .basic_cfg = \ - { \ - .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ - .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ - }, \ - .identify_cfg = \ - { \ - .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ - }, \ - .thermostat_cfg = \ - { \ - .local_temperature = (int16_t)ESP_ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_DEFAULT_VALUE, \ - .occupied_cooling_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE, \ - .occupied_heating_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE, \ - .control_sequence_of_operation = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_DEFAULT_VALUE, \ - .system_mode = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE, \ - }, \ - } +#define ZB_DEFAULT_THERMOSTAT_CONFIG() \ + { \ + .basic_cfg = \ + { \ + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, \ + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE, \ + }, \ + .identify_cfg = \ + { \ + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE, \ + }, \ + .thermostat_cfg = { \ + .local_temperature = (int16_t)ESP_ZB_ZCL_THERMOSTAT_LOCAL_TEMPERATURE_DEFAULT_VALUE, \ + .occupied_cooling_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_COOLING_SETPOINT_DEFAULT_VALUE, \ + .occupied_heating_setpoint = ESP_ZB_ZCL_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_DEFAULT_VALUE, \ + .control_sequence_of_operation = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_DEFAULT_VALUE, \ + .system_mode = ESP_ZB_ZCL_THERMOSTAT_CONTROL_SYSTEM_MODE_DEFAULT_VALUE, \ + }, \ + } class ZigbeeThermostat : public ZigbeeEP { - public: - ZigbeeThermostat(uint8_t endpoint); - ~ZigbeeThermostat(); +public: + ZigbeeThermostat(uint8_t endpoint); + ~ZigbeeThermostat(); - void onTempRecieve(void (*callback)(float)) { _on_temp_recieve = callback; } - void onConfigRecieve(void (*callback)(float, float, float)) { _on_config_recieve = callback; } + void onTempRecieve(void (*callback)(float)) { + _on_temp_recieve = callback; + } + void onConfigRecieve(void (*callback)(float, float, float)) { + _on_config_recieve = callback; + } - void getTemperature(); - void getSensorSettings(); - void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); + void getTemperature(); + void getSensorSettings(); + void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); - private: - // save instance of the class in order to use it in static functions - static ZigbeeThermostat* _instance; +private: + // save instance of the class in order to use it in static functions + static ZigbeeThermostat *_instance; - void (*_on_temp_recieve)(float); - void (*_on_config_recieve)(float, float, float); - float _min_temp; - float _max_temp; - float _tolerance; + void (*_on_temp_recieve)(float); + void (*_on_config_recieve)(float, float, float); + float _min_temp; + float _max_temp; + float _tolerance; - void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); - static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); - static void findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); + void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req); + static void bindCb(esp_zb_zdp_status_t zdo_status, void *user_ctx); + static void findCb(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) override; }; -#endif //SOC_IEEE802154_SUPPORTED +#endif //SOC_IEEE802154_SUPPORTED From 7d763df95cadc88ba44fbc962cd17cff64056297 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: Wed, 2 Oct 2024 12:57:14 +0200 Subject: [PATCH 34/34] fix(): Codespell issues --- .../Zigbee_Color_Dimmable_Light.ino | 4 ++-- .../Zigbee_Color_Dimmer_Switch.ino | 2 +- .../Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino | 4 ++-- .../Zigbee_Temperature_Sensor.ino | 6 +++--- .../examples/Zigbee_Thermostat/Zigbee_Thermostat.ino | 2 +- libraries/Zigbee/src/ZigbeeCore.cpp | 6 +++--- libraries/Zigbee/src/ZigbeeEP.h | 4 ++-- libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp | 10 +++++----- libraries/Zigbee/src/ep/ZigbeeLight.cpp | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino index c12ecadbd64..1ce9ff56816 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmable_Light/Zigbee_Color_Dimmable_Light.ino @@ -86,7 +86,7 @@ void setup() { } void loop() { - // Cheking button for factory reset + // Checking button for factory reset if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed // Key debounce handling delay(100); @@ -95,7 +95,7 @@ void loop() { delay(50); if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot - Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); } } diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index fac0a92316f..a494623e436 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -90,7 +90,7 @@ void loop() { // Toggle light zbSwitch.lightToggle(); } - // Handle serial input to controll color and level of the light + // Handle serial input to control color and level of the light if (Serial.available()) { String command = Serial.readString(); diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino index 576623e990a..2f13357a156 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Light/Zigbee_On_Off_Light.ino @@ -69,7 +69,7 @@ void setup() { } void loop() { - // Cheking button for factory reset + // Checking button for factory reset if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed // Key debounce handling delay(100); @@ -78,7 +78,7 @@ void loop() { delay(50); if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot - Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); } } diff --git a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino index bfb578663db..92249e980ab 100644 --- a/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino +++ b/libraries/Zigbee/examples/Zigbee_Temperature_Sensor/Zigbee_Temperature_Sensor.ino @@ -82,13 +82,13 @@ void setup() { // Set reporting interval for temperature measurement in seconds, must be called after Zigbee.begin() // min_interval and max_interval in seconds, delta (temp change in °C) // if min = 1 and max = 0, reporting is sent only when temperature changes by delta - // if min = 0 and max = 10, reporting is sent every 10 secods or temperature changes by delta + // if min = 0 and max = 10, reporting is sent every 10 seconds or temperature changes by delta // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of temperature change zbTempSensor.setReporting(1, 0, 1); } void loop() { - // Cheking button for factory reset + // Checking button for factory reset if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed // Key debounce handling delay(100); @@ -97,7 +97,7 @@ void loop() { delay(50); if ((millis() - startTime) > 3000) { // If key pressed for more than 3secs, factory reset Zigbee and reboot - Serial.printf("Reseting Zigbee to factory settings, reboot.\n"); + Serial.printf("Resetting Zigbee to factory settings, reboot.\n"); Zigbee.factoryReset(); } } diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 0fef83f0ad7..8f4ea0b543d 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -67,7 +67,7 @@ void setup() { // Init button switch pinMode(BUTTON_PIN, INPUT); - // Set callback functions for temperature and configuration recieve + // Set callback functions for temperature and configuration receive zbThermostat.onTempRecieve(recieveSensorTemp); zbThermostat.onConfigRecieve(recieveSensorConfig); diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index 2b089cf03ec..9edbe737cfe 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -156,7 +156,7 @@ void ZigbeeCore::setRebootOpenNetwork(uint8_t time) { void ZigbeeCore::openNetwork(uint8_t time) { if (_started) { - log_v("Openning network for joining for %d seconds", time); + log_v("Opening network for joining for %d seconds", time); esp_zb_bdb_open_network(time); } } @@ -198,7 +198,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { log_i("Device rebooted"); Zigbee._started = true; if ((zigbee_role_t)Zigbee.getRole() == ZIGBEE_COORDINATOR && Zigbee._open_network > 0) { - log_i("Openning network for joining for %d seconds", Zigbee._open_network); + log_i("Opening network for joining for %d seconds", Zigbee._open_network); esp_zb_bdb_open_network(Zigbee._open_network); } } @@ -289,7 +289,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } void ZigbeeCore::factoryReset() { - log_v("Factory reseting Zigbee stack, device will reboot"); + log_v("Factory resetting Zigbee stack, device will reboot"); esp_zb_factory_reset(); } diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index beb045559b3..e7deefdb32e 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -7,7 +7,7 @@ #include -/* Usefull defines */ +/* Useful defines */ #define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) #define print_ieee_addr(addr) \ log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) @@ -93,7 +93,7 @@ class ZigbeeEP { // findEndpoind may be implemented by EPs to find and bind devices virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {}; - //list of all handlers function calls, to be overide by EPs implementation + //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 zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp index b823d3879d1..841d9c7f122 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmableLight.cpp @@ -47,7 +47,7 @@ void ZigbeeColorDimmableLight::calculateRGB(uint16_t x, uint16_t y, uint8_t &red blue = (uint8_t)(b * (float)255); } -//set attribude method -> methon overriden in child class +//set attribute method -> method overridden in child class void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { @@ -58,7 +58,7 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me } return; } else { - log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL) { if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { @@ -68,7 +68,7 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me } return; } else { - log_w("Recieved message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); + log_w("Received message ignored. Attribute ID: %d not supported for Level Control", message->attribute.id); //TODO: implement more attributes -> includes/zcl/esp_zigbee_zcl_level.h } } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL) { @@ -96,10 +96,10 @@ void ZigbeeColorDimmableLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_me lightChanged(); return; } else { - log_w("Recieved message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); + log_w("Received message ignored. Attribute ID: %d not supported for Color Control", message->attribute.id); } } else { - log_w("Recieved message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); + log_w("Received message ignored. Cluster ID: %d not supported for Color dimmable Light", message->info.cluster); } } diff --git a/libraries/Zigbee/src/ep/ZigbeeLight.cpp b/libraries/Zigbee/src/ep/ZigbeeLight.cpp index 108faee5dc3..0577ede1788 100644 --- a/libraries/Zigbee/src/ep/ZigbeeLight.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeLight.cpp @@ -9,7 +9,7 @@ ZigbeeLight::ZigbeeLight(uint8_t endpoint) : ZigbeeEP(endpoint) { _ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID, .app_device_version = 0}; } -//set attribude method -> methon overriden in child class +//set attribute method -> method overridden in child class void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) { //check the data and call right method if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { @@ -17,10 +17,10 @@ void ZigbeeLight::zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *mess _current_state = *(bool *)message->attribute.data.value; lightChanged(); } else { - log_w("Recieved message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); + log_w("Received message ignored. Attribute ID: %d not supported for On/Off Light", message->attribute.id); } } else { - log_w("Recieved message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); + log_w("Received message ignored. Cluster ID: %d not supported for On/Off Light", message->info.cluster); } }