├── docs └── esp32-h2-devkitm-1-v1.2_pinlayout.png ├── .gitignore ├── idf_component.yml ├── partitions_zb.csv ├── ZB_sensor.yaml ├── esphome_zb.h ├── esp_zb_light.h ├── README.md └── esp_zb_light.c /docs/esp32-h2-devkitm-1-v1.2_pinlayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luar123/esphome_zb_sensor/HEAD/docs/esp32-h2-devkitm-1-v1.2_pinlayout.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Gitignore settings for ESPHome 2 | # This is an example and may include too much for your use-case. 3 | # You can modify this file to suit your needs. 4 | /.esphome/ 5 | /secrets.yaml 6 | -------------------------------------------------------------------------------- /idf_component.yml: -------------------------------------------------------------------------------- 1 | ## IDF Component Manager Manifest File 2 | dependencies: 3 | espressif/esp-zigbee-lib: "~1.1.2" 4 | espressif/esp-zboss-lib: "~1.1.2" 5 | ## Required IDF version 6 | idf: 7 | version: ">=5.1.2" 8 | -------------------------------------------------------------------------------- /partitions_zb.csv: -------------------------------------------------------------------------------- 1 | otadata, data, ota, , 0x2000, 2 | phy_init, data, phy, , 0x1000, 3 | app0, app, ota_0, , 0x1B0000, 4 | app1, app, ota_1, , 0x1B0000, 5 | nvs, data, nvs, , 0x6D000, 6 | zb_storage, data, fat, , 16K, 7 | zb_fct, data, fat, , 1K, 8 | -------------------------------------------------------------------------------- /ZB_sensor.yaml: -------------------------------------------------------------------------------- 1 | esphome: 2 | name: zb-sensor 3 | platformio_options: 4 | platform: https://github.com/luar123/platform-espressif32H2/archive/refs/tags/v6.5.1.zip 5 | includes: 6 | - esphome_zb.h 7 | - esp_zb_light.c 8 | - esp_zb_light.h 9 | 10 | esp32: 11 | board: esp32-h2-devkitm-1 12 | flash_size: 4MB 13 | partitions: partitions_zb.csv 14 | framework: 15 | type: esp-idf 16 | version: 5.1.2 17 | sdkconfig_options: 18 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y 19 | CONFIG_ZB_ENABLED: y 20 | CONFIG_ZB_ZED: y 21 | CONFIG_ZB_RADIO_NATIVE: y 22 | ZB_ED_ROLE: y 23 | variant: esp32h2 24 | 25 | # Enable logging 26 | logger: 27 | hardware_uart: UART0 28 | 29 | i2c: 30 | sda: 12 31 | scl: 22 32 | 33 | sensor: 34 | # https://esphome.io/components/sensor/aht10.html 35 | - platform: aht10 36 | variant: AHT10 # AHT20 for AHT20/AHT30 sensors 37 | temperature: 38 | name: "Living Room Temperature" 39 | id: "temp" 40 | filters: 41 | - delta: 0.1 42 | on_value: 43 | then: 44 | - lambda: |- 45 | int16_t value = (int16_t)(x*100); 46 | reportAttribute(ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &value); 47 | humidity: 48 | name: "Living Room Humidity" 49 | id: "hum" 50 | filters: 51 | - delta: 1 52 | on_value: 53 | then: 54 | - lambda: |- 55 | int16_t value = (int16_t)(x*100); 56 | reportAttribute(ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &value); 57 | update_interval: 60s 58 | 59 | custom_component: 60 | - lambda: |- 61 | auto my_zb = new esphomeZB(); 62 | return {my_zb}; 63 | components: 64 | - id: zb 65 | -------------------------------------------------------------------------------- /esphome_zb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Included 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form, except as embedded into a Espressif Systems 13 | * integrated circuit in a product or a software update for such product, 14 | * must reproduce the above copyright notice, this list of conditions and 15 | * the following disclaimer in the documentation and/or other materials 16 | * provided with the distribution. 17 | * 18 | * 3. Neither the name of the copyright holder nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * 4. Any software provided in binary form under this license must not be reverse 23 | * engineered, decompiled, modified and/or disassembled. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #include "esphome.h" 39 | #include "esp_zb_light.h" 40 | 41 | class esphomeZB : public Component { 42 | public: 43 | void setup() override { 44 | // This will be called once to set up the component 45 | // think of it as the setup() call in Arduino 46 | setup_zb(); 47 | 48 | } 49 | void loop() override { 50 | // This will be called very often after setup time. 51 | // think of it as the loop() call in Arduino 52 | 53 | } 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /esp_zb_light.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Included 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form, except as embedded into a Espressif Systems 13 | * integrated circuit in a product or a software update for such product, 14 | * must reproduce the above copyright notice, this list of conditions and 15 | * the following disclaimer in the documentation and/or other materials 16 | * provided with the distribution. 17 | * 18 | * 3. Neither the name of the copyright holder nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * 4. Any software provided in binary form under this license must not be reverse 23 | * engineered, decompiled, modified and/or disassembled. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #include "esp_zigbee_core.h" 39 | #include "zboss_api.h" 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* Zigbee configuration */ 46 | #define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ 47 | #define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN 48 | #define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ 49 | #define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ 50 | #define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ 51 | #define ESP_ZB_ZED_CONFIG() \ 52 | { \ 53 | .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ 54 | .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ 55 | .nwk_cfg.zed_cfg = { \ 56 | .ed_timeout = ED_AGING_TIMEOUT, \ 57 | .keep_alive = ED_KEEP_ALIVE, \ 58 | }, \ 59 | } 60 | 61 | #define ESP_ZB_DEFAULT_RADIO_CONFIG() \ 62 | { \ 63 | .radio_mode = RADIO_MODE_NATIVE, \ 64 | } 65 | 66 | #define ESP_ZB_DEFAULT_HOST_CONFIG() \ 67 | { \ 68 | .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ 69 | } 70 | void setup_zb(void); 71 | void run_zb(void); 72 | void reportAttribute(uint16_t clusterID, uint16_t attributeID, void *value); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!IMPORTANT] 2 | > **This implementation is outdated: Use the [external zigbee component](https://github.com/luar123/zigbee_esphome) for easier setup and more functionality.** 3 | 4 | # ESPHome Zigbee sensor using ESP32-H2 5 | 6 | ESPHome example of a zigbee sensor. 7 | 8 | Note that the Zigbee part in this project is currently hardcoded and included as a custom component including a task. (Changing this to an external component with more configuration possibilities would be the next step). 9 | 10 | ## Zigbee based temperature and humidity sensor 11 | 12 | ESPHome Zigbee sensor connected to [AHT10 Temperature+Humidity Sensor](https://next.esphome.io/components/sensor/aht10). 13 | 14 | ### Hardware Required 15 | 16 | * One development board with ESP32-H2 SoC acting as Zigbee end-device (that you will load ESPHome with the zb-sensor config to). 17 | * For example the official [ESP32-H2-DevKitM-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32h2/esp32-h2-devkitm-1/user_guide.html) development kit board. 18 | * [AHT10/AHT20/AHT30 Temperature+Humidity Sensor](https://next.esphome.io/components/sensor/aht10) connected to I2C pins (SDA: 12, SCL: 22). 19 | * A USB cable for power supply and programming. 20 | * (Optional) A USB-C cable to get ESP32 logs from the UART USB port (UART0). 21 | 22 | ### Build ESPHome Zigbee sensor 23 | 24 | * We will build [ZB_sensor.yaml](ZB_sensor.yaml) file. 25 | * Check [Getting Started with the ESPHome Command Line](https://esphome.io/guides/getting_started_command_line.html) tutorial to setup your dev environment. 26 | 27 | **Steps** 28 | * Change the [AHTx0 variant](https://esphome.io/components/sensor/aht10.html) in [ZB_sensor.yaml](ZB_sensor.yaml) file according to the sensor you have 29 | * Build with `esphome run ZB_sensor.yaml` command will fail 30 | * Copy [idf_component.yml](idf_component.yml) to `.esphome/build/zb-sensor/src/` 31 | * Add the following 4 lines to the `.esphome/build/zb-sensor/sdkconfig.zb-sensor` file 32 | ```ini 33 | CONFIG_ZB_ENABLED=y 34 | CONFIG_ZB_RADIO_NATIVE=y 35 | CONFIG_ZB_ZED=y 36 | ZB_ED_ROLE=y 37 | ``` 38 | * Build with `esphome run ZB_sensor.yaml` command 39 | * Firmware will be uploaded automatically to the ESP32-H2 board 40 | 41 | ### Notes 42 | * There is a bug in [ESPHome 2024.3.0](https://esphome.io/changelog/2024.3.0.html). Deactivate the logger to make it build. 43 | * Check issue [2024.3.0 fails to compile in logger component #5612](https://github.com/esphome/issues/issues/5612). 44 | * This should be fixed by esphome/esphome#6323 which should be included in ESPHome 2024.3.1. 45 | * If library versions in [idf_component.yml](idf_component.yml) are changed, copy the file to `.esphome/build/zb-sensor/src/` again and delete `.esphome/build/zb-sensor/.pioenvs`. 46 | 47 | ## Variants: 48 | - [Variant for ESP32-C6](https://github.com/lboue/esphome_zb_sensor/blob/ZB_C6_sensor/ZB_C6_sensor.yaml) 49 | - [Variant with added TSL2561 Sensor and illuminance ZigBee cluster](https://github.com/dronix27/esphome_zb_sensor/tree/master) 50 | 51 | ## External documentation and reference 52 | 53 | Note! The official documentation and reference examples for the ESP Zigbee SDK can currently be obtained from Espressif: 54 | 55 | - [ESP32 Zigbee SDK Programming Guide](https://docs.espressif.com/projects/esp-zigbee-sdk/en/latest/esp32/) 56 | - [ESP32-H2 Application User Guide](https://docs.espressif.com/projects/esp-zigbee-sdk/en/latest/esp32h2/application.html) 57 | - [ESP32-C6 Application User Guide](https://docs.espressif.com/projects/esp-zigbee-sdk/en/latest/esp32c6/application.html) 58 | - [ESP-Zigbee-SDK Github repo](https://github.com/espressif/esp-zigbee-sdk) 59 | - [ESP-Zigbee-SDK examples](https://github.com/espressif/esp-zigbee-sdk/tree/main/examples/) 60 | - [Zigbee HA Example](https://github.com/espressif/esp-zigbee-sdk/tree/main/examples/esp_zigbee_HA_sample) 61 | - [Zigbee HA Light Bulb example](https://github.com/espressif/esp-zigbee-sdk/tree/main/examples/esp_zigbee_HA_sample/HA_on_off_light) 62 | - [Zigbee HA temperature sensor example](https://github.com/espressif/esp-zigbee-sdk/tree/main/examples/esp_zigbee_HA_sample/HA_temperature_sensor) 63 | - [Zigbee HA thermostat example](https://github.com/espressif/esp-zigbee-sdk/tree/main/examples/esp_zigbee_HA_sample/HA_thermostat) 64 | 65 | ## How to contribute 66 | 67 | If looking to contribute to this project then suggest follow steps in these guides + look at issues in Espressif's ESP Zigbee SDK repoository: 68 | 69 | - https://github.com/espressif/esp-zigbee-sdk/issues 70 | - https://github.com/firstcontributions/first-contributions/blob/master/README.md 71 | - https://github.com/firstcontributions/first-contributions/blob/master/github-desktop-tutorial.md 72 | -------------------------------------------------------------------------------- /esp_zb_light.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: LicenseRef-Included 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form, except as embedded into a Espressif Systems 13 | * integrated circuit in a product or a software update for such product, 14 | * must reproduce the above copyright notice, this list of conditions and 15 | * the following disclaimer in the documentation and/or other materials 16 | * provided with the distribution. 17 | * 18 | * 3. Neither the name of the copyright holder nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software without 20 | * specific prior written permission. 21 | * 22 | * 4. Any software provided in binary form under this license must not be reverse 23 | * engineered, decompiled, modified and/or disassembled. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #include "freertos/FreeRTOS.h" 39 | #include "freertos/task.h" 40 | #include "esp_check.h" 41 | #include "esp_log.h" 42 | #include "nvs_flash.h" 43 | #include "ha/esp_zigbee_ha_standard.h" 44 | #include "esp_zb_light.h" 45 | 46 | #if !defined ZB_ED_ROLE 47 | #error Define ZB_ED_ROLE in idf.py menuconfig to compile light (End Device) source code. 48 | #endif 49 | 50 | bool connected = false; 51 | 52 | static const char *TAG = "ESP_ZB_ON_OFF_LIGHT"; 53 | /********************* Define functions **************************/ 54 | static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) 55 | { 56 | ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); 57 | } 58 | 59 | void reportAttribute(uint16_t clusterID, uint16_t attributeID, void *value) 60 | { 61 | if(!connected) {return;} 62 | esp_zb_zcl_report_attr_cmd_t cmd = { 63 | .zcl_basic_cmd = { 64 | .dst_addr_u.addr_short = 0x0000, 65 | .dst_endpoint = 1, 66 | .src_endpoint = HA_ESP_LIGHT_ENDPOINT, 67 | }, 68 | .address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT, 69 | .clusterID = clusterID, 70 | .attributeID = attributeID, 71 | .cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, 72 | }; 73 | esp_zb_zcl_status_t state = esp_zb_zcl_set_attribute_val(HA_ESP_LIGHT_ENDPOINT, clusterID, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attributeID, value, false); 74 | 75 | /* Check for error */ 76 | if(state != ESP_ZB_ZCL_STATUS_SUCCESS) { 77 | ESP_LOGE(TAG, "Setting attribute failed!"); 78 | return; 79 | } 80 | ESP_LOGD(TAG, "Attribute set!"); 81 | esp_zb_zcl_report_attr_cmd_req(&cmd); 82 | } 83 | 84 | void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) 85 | { 86 | uint32_t *p_sg_p = signal_struct->p_app_signal; 87 | esp_err_t err_status = signal_struct->esp_err_status; 88 | esp_zb_app_signal_type_t sig_type = *p_sg_p; 89 | switch (sig_type) { 90 | case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: 91 | ESP_LOGI(TAG, "Zigbee stack initialized"); 92 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); 93 | break; 94 | case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: 95 | case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: 96 | if (err_status == ESP_OK) { 97 | ESP_LOGI(TAG, "Start network steering"); 98 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); 99 | } else { 100 | /* commissioning failed */ 101 | ESP_LOGW(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); 102 | esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_INITIALIZATION, 1000); 103 | } 104 | break; 105 | case ESP_ZB_BDB_SIGNAL_STEERING: 106 | if (err_status == ESP_OK) { 107 | esp_zb_ieee_addr_t extended_pan_id; 108 | esp_zb_get_extended_pan_id(extended_pan_id); 109 | ESP_LOGI(TAG, "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d)", 110 | extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], 111 | extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], 112 | esp_zb_get_pan_id(), esp_zb_get_current_channel()); 113 | connected = true; 114 | //get local time: 115 | static esp_zb_zcl_read_attr_cmd_t cmd_req; 116 | cmd_req.zcl_basic_cmd.src_endpoint = HA_ESP_LIGHT_ENDPOINT; 117 | //cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; 118 | cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; 119 | //cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; 120 | cmd_req.zcl_basic_cmd.dst_endpoint = 1; 121 | cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = 0x0000; 122 | cmd_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME; 123 | cmd_req.attr_number = 1; 124 | uint16_t attributeID = ESP_ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID; 125 | cmd_req.attr_field = &attributeID; 126 | esp_zb_zcl_read_attr_cmd_req( &cmd_req); 127 | 128 | } else { 129 | ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status)); 130 | esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); 131 | } 132 | break; 133 | //todo: implement leave 134 | default: 135 | ESP_LOGI(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, 136 | esp_err_to_name(err_status)); 137 | break; 138 | } 139 | } 140 | 141 | static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) 142 | { 143 | esp_err_t ret = ESP_OK; 144 | bool light_state = 0; 145 | 146 | ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); 147 | ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, 148 | "Received message: error status(%d)", message->info.status); 149 | ESP_LOGI(TAG, "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", 150 | message->info.dst_endpoint, message->info.cluster, message->attribute.id, message->attribute.data.size); 151 | if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { 152 | /** if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { 153 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && 154 | message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { 155 | light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; 156 | ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off"); 157 | light_driver_set_power(light_state); 158 | } 159 | }**/ 160 | } 161 | return ret; 162 | } 163 | 164 | static esp_err_t zb_response_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) 165 | { 166 | esp_err_t ret = ESP_OK; 167 | 168 | ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); 169 | ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, 170 | "Received message: error status(%d)", message->info.status); 171 | ESP_LOGI(TAG, "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", 172 | message->info.dst_endpoint, message->info.cluster, message->variables->attribute.id, message->variables->attribute.data.size); 173 | 174 | if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { 175 | if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) { 176 | esp_zb_zcl_read_attr_resp_variable_t *var = message->variables; 177 | while (var->next != NULL) 178 | { 179 | if (var->attribute.id == ESP_ZB_ZCL_ATTR_TIME_LOCAL_TIME_ID && 180 | var->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U32) { 181 | //todo set time 182 | ESP_LOGI(TAG, "Local Time received: %u", *(unsigned int *)(uint32_t *)var->attribute.data.value); 183 | //light_driver_set_power(light_state); 184 | } 185 | var = var->next; 186 | } 187 | } 188 | if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) { 189 | ESP_LOGI(TAG, "id 0x%x, type 0x%x, value x", message->variables->attribute.id, message->variables->attribute.data.type); 190 | } 191 | } 192 | return ret; 193 | } 194 | 195 | static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) 196 | { 197 | esp_err_t ret = ESP_OK; 198 | switch (callback_id) { 199 | case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: 200 | ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); 201 | break; 202 | case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID: 203 | ret = zb_response_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *)message); 204 | break; 205 | default: 206 | ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id); 207 | break; 208 | } 209 | return ret; 210 | } 211 | 212 | static void esp_zb_task(void *pvParameters) 213 | { 214 | /* initialize Zigbee stack */ 215 | esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); 216 | esp_zb_init(&zb_nwk_cfg); 217 | // ------------------------------ Cluster BASIC ------------------------------ 218 | esp_zb_basic_cluster_cfg_t basic_cluster_cfg = { 219 | .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, 220 | .power_source = 0x03, 221 | }; 222 | uint32_t ApplicationVersion = 0x0001; 223 | uint32_t StackVersion = 0x0001; 224 | uint32_t HWVersion = 0x0001; 225 | uint8_t ManufacturerName[] = {4, 'T', 'e', 's', 't'}; // warning: this is in format {length, 'string'} : 226 | uint8_t ModelIdentifier[] = {5, 'a','i','r','_','q'}; 227 | uint8_t DateCode[] = {8, '2', '0', '2', '4', '0', '3', '2', '3'}; 228 | esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(&basic_cluster_cfg); 229 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID, &ApplicationVersion); 230 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID, &StackVersion); 231 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_HW_VERSION_ID, &HWVersion); 232 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ManufacturerName); 233 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, ModelIdentifier); 234 | esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_DATE_CODE_ID, DateCode); 235 | 236 | // ------------------------------ Cluster IDENTIFY ------------------------------ 237 | esp_zb_identify_cluster_cfg_t identify_cluster_cfg = { 238 | .identify_time = 0, 239 | }; 240 | esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(&identify_cluster_cfg); 241 | 242 | //--------------------------time 243 | esp_zb_time_cluster_cfg_t time_cfg = { 244 | .time = 0, 245 | .time_status = 0, 246 | }; 247 | //int32_t my_val = 0; 248 | esp_zb_attribute_list_t *esp_zb_time_cluster = esp_zb_time_cluster_create(&time_cfg); 249 | //esp_zb_time_cluster_add_attr(esp_zb_time_cluster, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &my_val); 250 | 251 | // ------------------------------ Cluster Temperature ------------------------------ 252 | esp_zb_temperature_meas_cluster_cfg_t temperature_meas_cfg = { 253 | .measured_value = 0xFFFF, 254 | .min_value = -5000, 255 | .max_value = 10000, 256 | }; 257 | esp_zb_attribute_list_t *esp_zb_temperature_meas_cluster = esp_zb_temperature_meas_cluster_create(&temperature_meas_cfg); 258 | 259 | // ------------------------------ Cluster Humidity ------------------------------ 260 | esp_zb_humidity_meas_cluster_cfg_t humidity_meas_cfg = { 261 | .measured_value = 0xFFFF, 262 | .min_value = 0, 263 | .max_value = 10000, 264 | }; 265 | esp_zb_attribute_list_t *esp_zb_humidity_meas_cluster = esp_zb_humidity_meas_cluster_create(&humidity_meas_cfg); 266 | 267 | // ------------------------------ Create cluster list ------------------------------ 268 | esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); 269 | esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); 270 | esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); 271 | esp_zb_cluster_list_add_time_cluster(esp_zb_cluster_list, esp_zb_time_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); 272 | esp_zb_cluster_list_add_temperature_meas_cluster(esp_zb_cluster_list, esp_zb_temperature_meas_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); 273 | esp_zb_cluster_list_add_humidity_meas_cluster(esp_zb_cluster_list, esp_zb_humidity_meas_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); 274 | 275 | // ------------------------------ Create endpoint list ------------------------------ 276 | esp_zb_ep_list_t *esp_zb_ep_list = esp_zb_ep_list_create(); 277 | esp_zb_ep_list_add_ep(esp_zb_ep_list, esp_zb_cluster_list, HA_ESP_LIGHT_ENDPOINT, ESP_ZB_AF_HA_PROFILE_ID, ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID); 278 | 279 | // ------------------------------ Register Device ------------------------------ 280 | esp_zb_device_register(esp_zb_ep_list); 281 | esp_zb_core_action_handler_register(zb_action_handler); 282 | esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); 283 | 284 | ESP_ERROR_CHECK(esp_zb_start(false)); 285 | esp_zb_main_loop_iteration(); 286 | } 287 | 288 | void setup_zb(void) 289 | { 290 | esp_zb_platform_config_t config = { 291 | .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), 292 | .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), 293 | }; 294 | ESP_ERROR_CHECK(nvs_flash_init()); 295 | ESP_ERROR_CHECK(esp_zb_platform_config(&config)); 296 | //esp_zb_task(); 297 | xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 24, NULL); 298 | } 299 | 300 | void run_zb(void) 301 | { 302 | //esp_zb_lock_acquire(); 303 | //zboss_main_loop_iteration(); 304 | //esp_zb_lock_release(); 305 | } 306 | --------------------------------------------------------------------------------