├── .gitignore ├── README.md ├── Zigbee_Arduino_CO2 ├── README.md ├── Zigbee_Arduino_CO2.ino └── ci.json ├── Zigbee_Light_Bulb_Router_V2.1 ├── README.md ├── Zigbee_Light_Bulb_Router_V2.1.ino ├── actionHandler.ino └── signalHandler.ino ├── Zigbee_Multiple_Endpoint_Router_V1 ├── README.md ├── SCD30.ino ├── Zigbee_Multiple_Endpoint_Router_V1.ino ├── actionHandler.ino ├── createEndpoints.ino ├── defines.h └── esp_zb_app_signal_handler.ino └── Zigbee_RGB_Light_Bulb_Router_V1 ├── Zigbee_RGB_Light_Bulb_Router_V1.ino ├── actionHandler.ino ├── lightDriver.ino └── signalHandler.ino /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | .theia 4 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp32c6_zigbee_router_examples 2 | Easy to use ESP32-C6 Zigbee Router Light Bulb example in Arduino! 3 | 4 | - Arduino-ESP32 Carbon dioxide (CO2) Sensor Example 5 | - SCD30 even simpler 6 | - Zigbee_Light_Bulb_Router 7 | - Simple on/off light in router mode 8 | - Zigbee_RGB_Light_Bulb_Router 9 | - RGB color dimmable light in router mode 10 | - Zigbee_Multiple_Endpoint_Router 11 | - SCD30 Sensor with CO2, Temperature and Humidity measurement 12 | -------------------------------------------------------------------------------- /Zigbee_Arduino_CO2/README.md: -------------------------------------------------------------------------------- 1 | # Arduino-ESP32 Carbon dioxide (CO2) Sensor Example 2 | 3 | This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) simple sensor device type with carbon dioxide measuring. 4 | 5 | # Supported Targets 6 | 7 | Currently, this example supports the following targets. 8 | 9 | | Supported Targets | ESP32-C6 | ESP32-H2 | 10 | | ----------------- | -------- | -------- | 11 | 12 | ## Pressure + Flow Sensor Functions 13 | 14 | * After this board first starts up, it would be configured locally to report the carbon dioxide on every 30 seconds. 15 | * By clicking the button (BOOT) on this board, this board will immediately send a report of the current measured carbon dioxide to the network. 16 | 17 | ## Hardware Required 18 | 19 | * A USB cable for power supply and programming 20 | 21 | ### Configure the Project 22 | 23 | In this example, the internal temperature sensor is used to demonstrate reading of the carbon dioxide sensors. 24 | Set the Button GPIO by changing the `button` variable. By default, it's the pin `BOOT_PIN` (BOOT button on ESP32-C6 and ESP32-H2). 25 | 26 | #### Using Arduino IDE 27 | 28 | To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). 29 | 30 | * Before Compile/Verify, select the correct board: `Tools -> Board`. 31 | * Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ED (end device)` 32 | * Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee 4MB with spiffs` 33 | * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. 34 | * Optional: Set debug level to verbose to see all logs from Zigbee stack: `Tools -> Core Debug Level: Verbose`. 35 | 36 | ## Troubleshooting 37 | 38 | 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. 39 | You can do the following: 40 | 41 | * In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled`. 42 | * Add to the sketch `Zigbee.factoryReset();` to reset the device and Zigbee stack. 43 | 44 | By default, the coordinator network is closed after rebooting or flashing new firmware. 45 | To open the network you have 2 options: 46 | 47 | * Open network after reboot by setting `Zigbee.setRebootOpenNetwork(time);` before calling `Zigbee.begin();`. 48 | * In application you can anytime call `Zigbee.openNetwork(time);` to open the network for devices to join. 49 | 50 | ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** 51 | 52 | * **LED not blinking:** Check the wiring connection and the IO selection. 53 | * **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. 54 | * **COM port not detected:** Check the USB cable and the USB to Serial driver installation. 55 | 56 | If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). 57 | 58 | ## Contribute 59 | 60 | To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) 61 | 62 | 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! 63 | 64 | Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. 65 | 66 | ## Resources 67 | 68 | * Official ESP32 Forum: [Link](https://esp32.com) 69 | * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) 70 | * ESP32-C6 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf) 71 | * ESP32-H2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-h2_datasheet_en.pdf) 72 | * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) 73 | -------------------------------------------------------------------------------- /Zigbee_Arduino_CO2/Zigbee_Arduino_CO2.ino: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ZIGBEE_MODE_ED 3 | #error "Zigbee end device mode is not selected in Tools->Zigbee mode" 4 | #endif 5 | 6 | #include "Zigbee.h" 7 | #include 8 | #include "SparkFun_SCD30_Arduino_Library.h" //Click here to get the library: http:// 9 | 10 | // SCD30 config 11 | #define SCD30_SDA_PIN 6 12 | #define SCD30_SCL_PIN 7 13 | 14 | /* Zigbee carbon dioxide sensor configuration */ 15 | #define CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER 10 16 | #define TEMPERATURE_SENSOR_ENDPOINT_NUMBER 11 17 | uint8_t button = BOOT_PIN; 18 | 19 | ZigbeeCarbonDioxideSensor zbCarbonDioxideSensor = ZigbeeCarbonDioxideSensor(CARBON_DIOXIDE_SENSOR_ENDPOINT_NUMBER); 20 | ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMPERATURE_SENSOR_ENDPOINT_NUMBER); 21 | SCD30 airSensor; 22 | 23 | 24 | void setup() { 25 | Serial.begin(115200); 26 | Wire.begin(SCD30_SDA_PIN, SCD30_SCL_PIN); // initialize I2C protocoll 27 | 28 | // Init button switch 29 | pinMode(button, INPUT_PULLUP); 30 | 31 | delay(2000); 32 | 33 | // Checking button for factory reset and reporting 34 | if (digitalRead(button) == LOW) { // Push button pressed 35 | // Key debounce handling 36 | delay(100); 37 | int startTime = millis(); 38 | while (digitalRead(button) == LOW) { 39 | delay(50); 40 | if ((millis() - startTime) > 3000) { 41 | // If key pressed for more than 3secs, factory reset Zigbee and reboot 42 | Serial.println("Resetting Zigbee to factory and rebooting in 1s."); 43 | delay(1000); 44 | Zigbee.factoryReset(); 45 | } 46 | } 47 | } 48 | 49 | 50 | if (airSensor.begin() == false) { 51 | Serial.println("Air sensor not detected. Please check wiring. Freezing..."); 52 | //while (1) 53 | // ; 54 | } 55 | 56 | airSensor.setAutoSelfCalibration(true); 57 | log_i("Auto calibration set to %d", airSensor.getAutoSelfCalibration()); 58 | 59 | // Optional: set Zigbee device name and model 60 | zbCarbonDioxideSensor.setManufacturerAndModel("MicroMasterMinds", "CarbonDioxideSensor"); 61 | zbTempSensor.setManufacturerAndModel("MicroMasterMinds", "TemperatureSensor"); 62 | 63 | // Set minimum and maximum carbon dioxide measurement value in ppm 64 | zbCarbonDioxideSensor.setMinMaxValue(400, 10000); 65 | zbTempSensor.setMinMaxValue(-40, 70); 66 | zbTempSensor.addHumiditySensor(0, 95, 3); 67 | 68 | // Add endpoints to Zigbee Core 69 | Zigbee.addEndpoint(&zbCarbonDioxideSensor); 70 | Zigbee.addEndpoint(&zbTempSensor); 71 | 72 | Serial.println("Starting Zigbee..."); 73 | // When all EPs are registered, start Zigbee in End Device mode 74 | if (!Zigbee.begin()) { 75 | Serial.println("Zigbee failed to start!"); 76 | Serial.println("Rebooting..."); 77 | ESP.restart(); 78 | } else { 79 | Serial.println("Zigbee started successfully!"); 80 | } 81 | Serial.println("Connecting to network"); 82 | while (!Zigbee.connected()) { 83 | Serial.print("."); 84 | delay(100); 85 | } 86 | Serial.println(); 87 | 88 | // Set reporting interval for carbon dioxide measurement to be done every 30 seconds, must be called after Zigbee.begin() 89 | // min_interval and max_interval in seconds, delta (carbon dioxide change in ppm) 90 | // if min = 1 and max = 0, reporting is sent only when carbon dioxide changes by delta 91 | // if min = 0 and max = 10, reporting is sent every 10 seconds or when carbon dioxide changes by delta 92 | // if min = 0, max = 10 and delta = 0, reporting is sent every 10 seconds regardless of delta change 93 | zbCarbonDioxideSensor.setReporting(0, 30, 0); 94 | zbTempSensor.setReporting(0, 30, 0); 95 | } 96 | 97 | void loop() { 98 | static uint32_t timeCounter = 0; 99 | // Read carbon dioxide sensor every 2s 100 | if (!(timeCounter++ % 20)) { // delaying for 100ms x 20 = 2s 101 | // Read sensor value - here is chip temperature used + 300 as a dummy value for demonstration 102 | if (airSensor.dataAvailable()){ 103 | uint16_t carbon_dioxide_value = airSensor.getCO2(); 104 | float temp_value = airSensor.getTemperature(); 105 | float humidity_value = airSensor.getHumidity(); 106 | //Serial.printf("Updating carbon dioxide sensor value to %d ppm\r\n", carbon_dioxide_value); 107 | zbCarbonDioxideSensor.setCarbonDioxide(carbon_dioxide_value); 108 | zbTempSensor.setTemperature(temp_value); 109 | zbTempSensor.setHumidity(humidity_value); 110 | } 111 | } 112 | 113 | // Checking button for factory reset and reporting 114 | if (digitalRead(button) == LOW) { // Push button pressed 115 | // Key debounce handling 116 | delay(100); 117 | int startTime = millis(); 118 | while (digitalRead(button) == LOW) { 119 | delay(50); 120 | if ((millis() - startTime) > 3000) { 121 | // If key pressed for more than 3secs, factory reset Zigbee and reboot 122 | Serial.println("Resetting Zigbee to factory and rebooting in 1s."); 123 | delay(1000); 124 | Zigbee.factoryReset(); 125 | } 126 | } 127 | zbCarbonDioxideSensor.report(); 128 | zbTempSensor.report(); 129 | } 130 | delay(100); 131 | } 132 | -------------------------------------------------------------------------------- /Zigbee_Arduino_CO2/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "fqbn_append": "PartitionScheme=zigbee,ZigbeeMode=ed", 3 | "requires": [ 4 | "CONFIG_SOC_IEEE802154_SUPPORTED=y", 5 | "CONFIG_ZB_ENABLED=y" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /Zigbee_Light_Bulb_Router_V2.1/README.md: -------------------------------------------------------------------------------- 1 | # Arduino-ESP32 Zigbee Light Bulb Example 2 | 3 | This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. 4 | 5 | **This example is based on Espressif ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** 6 | 7 | # Supported Targets 8 | 9 | Currently, this example supports the following targets. 10 | 11 | | Supported Targets | ESP32-C6 | ESP32-H2 | 12 | | ----------------- | -------- | -------- | 13 | 14 | ## Hardware Required 15 | 16 | * One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) 17 | * A USB cable for power supply and programming 18 | * Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) 19 | 20 | ### Configure the Project 21 | 22 | Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. 23 | By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. 24 | 25 | #### Using Arduino IDE 26 | 27 | To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). 28 | 29 | * Before Compile/Verify, select the correct board: `Tools -> Board`. 30 | * Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (Coordinator or Router)` 31 | * Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee ZCZR 4MB with spiffs` 32 | * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. 33 | 34 | ## Troubleshooting 35 | 36 | 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. 37 | You can do the following: 38 | 39 | * In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled` 40 | * In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. 41 | 42 | 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. 43 | You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. 44 | 45 | ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** 46 | 47 | * **LED not blinking:** Check the wiring connection and the IO selection. 48 | * **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. 49 | * **COM port not detected:** Check the USB cable and the USB to Serial driver installation. 50 | 51 | If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). 52 | 53 | ## Contribute 54 | 55 | To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) 56 | 57 | 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! 58 | 59 | Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. 60 | 61 | ## Resources 62 | 63 | The ESP Zigbee SDK provides more examples: 64 | * ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) 65 | * ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) 66 | 67 | * Official ESP32 Forum: [Link](https://esp32.com) 68 | * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) 69 | * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) 70 | * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) 71 | * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) 72 | * ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) 73 | * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) 74 | -------------------------------------------------------------------------------- /Zigbee_Light_Bulb_Router_V2.1/Zigbee_Light_Bulb_Router_V2.1.ino: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Based on Espressif Light Bulb Example 16 | // 17 | // Modified by MicroMasterMinds 🤯 18 | // 19 | // Hoffe es funzt auch 😂 20 | 21 | #ifndef ZIGBEE_MODE_ZCZR // Coordinator Device or Router Device 22 | #error "Zigbee router mode is not selected in Tools->Zigbee mode" 23 | #endif 24 | 25 | #include "esp_zigbee_core.h" 26 | #include "freertos/FreeRTOS.h" 27 | #include "freertos/task.h" 28 | #include "ha/esp_zigbee_ha_standard.h" 29 | 30 | #define LED_PIN RGB_BUILTIN 31 | 32 | /* Zigbee configuration */ 33 | #define MAX_CHILDREN 10 /* the max amount of connected devices */ 34 | #define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ 35 | #define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ 36 | 37 | /* Attribute values in ZCL string format 38 | * The string should be started with the length of its own. */ 39 | #define MANUFACTURER_NAME "\x12" \ 40 | "MicroMasterMinds" 41 | #define MODEL_IDENTIFIER "\x07" \ 42 | "Light" 43 | 44 | /********************* Zigbee functions **************************/ 45 | static void createZigbeeLightDevice() { 46 | /* Create customized Light endpoint */ 47 | esp_zb_on_off_light_cfg_t lightConfig = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); 48 | 49 | esp_zb_ep_list_t *endpointList = esp_zb_ep_list_create(); 50 | esp_zb_endpoint_config_t endpointConfig = {}; 51 | endpointConfig.endpoint = HA_ESP_LIGHT_ENDPOINT; 52 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 53 | endpointConfig.app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; 54 | endpointConfig.app_device_version = 0; 55 | 56 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 57 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&lightConfig.basic_cfg); 58 | 59 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 60 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 61 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 62 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(lightConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 63 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 64 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_on_off_cluster(clusterList, esp_zb_on_off_cluster_create(&lightConfig.on_off_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 65 | 66 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 67 | 68 | /* Register the device */ 69 | esp_zb_device_register(endpointList); 70 | } 71 | 72 | static void esp_zb_task(void *pvParameters) { 73 | /* Initialize Zigbee platform */ 74 | esp_zb_platform_config_t platformConfig = {}; 75 | platformConfig.radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; 76 | platformConfig.host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; 77 | ESP_ERROR_CHECK(esp_zb_platform_config(&platformConfig)); 78 | 79 | /* Initialize Zigbee stack */ 80 | esp_zb_cfg_t stackConfig = {}; 81 | stackConfig.esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER; 82 | stackConfig.install_code_policy = INSTALLCODE_POLICY_ENABLE; 83 | stackConfig.nwk_cfg.zczr_cfg.max_children = MAX_CHILDREN; 84 | esp_zb_init(&stackConfig); 85 | 86 | createZigbeeLightDevice(); 87 | 88 | esp_zb_core_action_handler_register(zb_action_handler); 89 | 90 | esp_zb_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK); 91 | 92 | ESP_ERROR_CHECK(esp_zb_start(false)); 93 | 94 | esp_zb_main_loop_iteration(); 95 | } 96 | /********************* Arduino functions **************************/ 97 | void setup() { 98 | Serial.begin(115200); 99 | Serial.println("Starting"); // will be shown in the terminal 100 | Serial.setDebugOutput(true); // show debug messages in Serial 101 | 102 | // Init RMT and leave light OFF 103 | neopixelWrite(LED_PIN, 0, 0, 0); 104 | 105 | // Start Zigbee task 106 | xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); 107 | } 108 | 109 | void loop() { 110 | // nothing here, runs in task 111 | ; 112 | } 113 | -------------------------------------------------------------------------------- /Zigbee_Light_Bulb_Router_V2.1/actionHandler.ino: -------------------------------------------------------------------------------- 1 | esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { 2 | esp_err_t ret = ESP_OK; 3 | switch (callback_id) { 4 | case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; 5 | default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; 6 | } 7 | return ret; 8 | } 9 | 10 | /* Handle the light attribute */ 11 | esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { 12 | esp_err_t ret = ESP_OK; 13 | bool light_state = 0; 14 | 15 | if (!message) { 16 | log_e("Empty message"); 17 | } 18 | if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { 19 | log_e("Received message: error status(%d)", message->info.status); 20 | } 21 | 22 | log_i( 23 | "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, 24 | message->attribute.data.size); 25 | if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { 26 | if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { 27 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { 28 | light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; 29 | log_i("Light sets to %s", light_state ? "On" : "Off"); 30 | neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light 31 | } 32 | } 33 | } 34 | return ret; 35 | } 36 | -------------------------------------------------------------------------------- /Zigbee_Light_Bulb_Router_V2.1/signalHandler.ino: -------------------------------------------------------------------------------- 1 | // 2 | // After esp_zb_start, user shall based on the corresponding signal type refer to 3 | // esp_zdo_app_signal_type from struct pointer signal_s to do certain actions. User could also 4 | // use refer to esp_zb_bdb_start_top_level_commissioning to change BDB mode. 5 | // 6 | 7 | static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { 8 | ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); 9 | } 10 | 11 | void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { 12 | 13 | esp_err_t err_status = signal_struct->esp_err_status; 14 | esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*signal_struct->p_app_signal; 15 | 16 | log_i("Zigbee signal: %s", esp_zb_zdo_signal_to_string(sig_type)); 17 | 18 | switch (sig_type) { 19 | 20 | case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: 21 | log_i("Zigbee stack initialized"); 22 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); 23 | break; 24 | 25 | case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: 26 | [[fallthrough]]; 27 | 28 | case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: 29 | log_i("Device started up, joining network..."); 30 | 31 | if (err_status == ESP_OK) { 32 | log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); 33 | 34 | if (esp_zb_bdb_is_factory_new()) { 35 | log_i("Start network steering"); 36 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); 37 | return; 38 | } else { 39 | log_i("Device rebooted"); 40 | } 41 | } else { 42 | /* commissioning failed */ 43 | log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); 44 | return; 45 | } 46 | break; 47 | 48 | case ESP_ZB_BDB_SIGNAL_STEERING: 49 | if (err_status == ESP_OK) { 50 | esp_zb_ieee_addr_t extended_pan_id; 51 | esp_zb_get_extended_pan_id(extended_pan_id); 52 | log_i( 53 | "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", 54 | 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], 55 | extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); 56 | return; 57 | } else { 58 | log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); 59 | esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); 60 | } 61 | break; 62 | 63 | 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; 64 | } 65 | } -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/README.md: -------------------------------------------------------------------------------- 1 | # Arduino-ESP32 Zigbee Light Bulb Example 2 | 3 | This example shows how to configure the Zigbee end device and use it as a Home Automation (HA) on/off light bulb. 4 | 5 | **This example is based on Espressif ESP-Zigbee-SDK example esp_zigbee_HA_sample/HA_on_off_light.** 6 | 7 | # Supported Targets 8 | 9 | Currently, this example supports the following targets. 10 | 11 | | Supported Targets | ESP32-C6 | ESP32-H2 | 12 | | ----------------- | -------- | -------- | 13 | 14 | ## Hardware Required 15 | 16 | * One development board (ESP32-H2 or ESP32-C6) acting as Zigbee coordinator (loaded with Zigbee_Light_switch example) 17 | * A USB cable for power supply and programming 18 | * Choose another board (ESP32-H2 or ESP32-C6) as Zigbee end device (loaded with Zigbee_Light_bulb example) 19 | 20 | ### Configure the Project 21 | 22 | Set the LED GPIO by changing the `LED_PIN` definition. By default, the LED_PIN is `RGB_BUILTIN`. 23 | By default, the `neoPixelWrite` function is used to control the LED. You can change it to digitalWrite to control a simple LED. 24 | 25 | #### Using Arduino IDE 26 | 27 | To get more information about the Espressif boards see [Espressif Development Kits](https://www.espressif.com/en/products/devkits). 28 | 29 | * Before Compile/Verify, select the correct board: `Tools -> Board`. 30 | * Select the End device Zigbee mode: `Tools -> Zigbee mode: Zigbee ZCZR (Coordinator or Router)` 31 | * Select Partition Scheme for Zigbee: `Tools -> Partition Scheme: Zigbee ZCZR 4MB with spiffs` 32 | * Select the COM port: `Tools -> Port: xxx` where the `xxx` is the detected COM port. 33 | 34 | ## Troubleshooting 35 | 36 | 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. 37 | You can do the following: 38 | 39 | * In the Arduino IDE go to the Tools menu and set `Erase All Flash Before Sketch Upload` to `Enabled` 40 | * In the sketch uncomment function `esp_zb_nvram_erase_at_start(true);` located in `esp_zb_task` function. 41 | 42 | 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. 43 | You can change it by editing `esp_zb_bdb_open_network(180);` in `esp_zb_app_signal_handler` function. 44 | 45 | ***Important: Make sure you are using a good quality USB cable and that you have a reliable power source*** 46 | 47 | * **LED not blinking:** Check the wiring connection and the IO selection. 48 | * **Programming Fail:** If the programming/flash procedure fails, try reducing the serial connection speed. 49 | * **COM port not detected:** Check the USB cable and the USB to Serial driver installation. 50 | 51 | If the error persists, you can ask for help at the official [ESP32 forum](https://esp32.com) or see [Contribute](#contribute). 52 | 53 | ## Contribute 54 | 55 | To know how to contribute to this project, see [How to contribute.](https://github.com/espressif/arduino-esp32/blob/master/CONTRIBUTING.rst) 56 | 57 | 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! 58 | 59 | Before creating a new issue, be sure to try Troubleshooting and check if the same issue was already created by someone else. 60 | 61 | ## Resources 62 | 63 | The ESP Zigbee SDK provides more examples: 64 | * ESP Zigbee SDK Docs: [Link](https://docs.espressif.com/projects/esp-zigbee-sdk) 65 | * ESP Zigbee SDK Repo: [Link](https://github.com/espressif/esp-zigbee-sdk) 66 | 67 | * Official ESP32 Forum: [Link](https://esp32.com) 68 | * Arduino-ESP32 Official Repository: [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) 69 | * ESP32 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf) 70 | * ESP32-S2 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) 71 | * ESP32-C3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf) 72 | * ESP32-S3 Datasheet: [Link to datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf) 73 | * Official ESP-IDF documentation: [ESP-IDF](https://idf.espressif.com) 74 | -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/SCD30.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SCD30_SDA_PIN 6 5 | #define SCD30_SCL_PIN 7 6 | 7 | SCD30 airSensor; 8 | 9 | static void SCD30_sensor_handler(void *pvParameters) { 10 | 11 | Wire.begin(SCD30_SDA_PIN, SCD30_SCL_PIN); // initialize I2C protocoll 12 | vTaskDelay(10 / portTICK_PERIOD_MS); // delay alternative for Tasks. Dont use delay()! 13 | 14 | while (airSensor.begin(Wire, true) == false) { 15 | log_e("Air sensor not detected. Please check wiring...."); 16 | } 17 | 18 | airSensor.setAutoSelfCalibration(true); 19 | log_i("Auto calibration set to %d", airSensor.getAutoSelfCalibration()); 20 | 21 | while (true) { 22 | if (airSensor.dataAvailable()) { 23 | SCD30_CO2 = airSensor.getCO2(); 24 | SCD30_temp = airSensor.getTemperature(); 25 | SCD30_humid = airSensor.getHumidity(); 26 | Serial.print("SCD30 "); 27 | Serial.print("Temperature: "); 28 | Serial.print(SCD30_temp); 29 | Serial.print(" C "); 30 | Serial.print("Humidity: "); 31 | Serial.print(SCD30_humid); 32 | Serial.print(" % "); 33 | Serial.print("CO2: "); 34 | Serial.print(SCD30_CO2); 35 | Serial.println(" ppm "); 36 | } 37 | 38 | vTaskDelay(500 / portTICK_PERIOD_MS); // delay alternative for Tasks. Dont use delay()! 39 | } 40 | } -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/Zigbee_Multiple_Endpoint_Router_V1.ino: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Based on Espressif Examples 16 | // 17 | // Modified by MicroMasterMinds 🤯 18 | // 19 | // Hoffe es funzt auch 😂 20 | 21 | #ifndef ZIGBEE_MODE_ZCZR // Coordinator Device or Router Device 22 | #error "Zigbee router mode is not selected in Tools->Zigbee mode" 23 | #endif 24 | 25 | #include "esp_zigbee_core.h" 26 | #include "freertos/FreeRTOS.h" 27 | #include "freertos/task.h" 28 | #include "ha/esp_zigbee_ha_standard.h" 29 | #include "defines.h" 30 | 31 | // Global variables with standard values 32 | int SCD30_CO2 = 400; 33 | float SCD30_temp = 25, SCD30_humid = 50; 34 | 35 | /********************* Zigbee functions **************************/ 36 | static void esp_zb_task(void *pvParameters) { 37 | /* Initialize Zigbee platform */ 38 | esp_zb_platform_config_t platformConfig = {}; 39 | platformConfig.radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; 40 | platformConfig.host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; 41 | ESP_ERROR_CHECK(esp_zb_platform_config(&platformConfig)); 42 | 43 | /* Initialize Zigbee stack */ 44 | esp_zb_cfg_t stackConfig = {}; 45 | stackConfig.esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER; 46 | stackConfig.install_code_policy = INSTALLCODE_POLICY_ENABLE; 47 | stackConfig.nwk_cfg.zczr_cfg.max_children = MAX_CHILDREN; 48 | esp_zb_init(&stackConfig); 49 | 50 | /* Register the device */ 51 | esp_zb_ep_list_t *endpointList = esp_zb_ep_list_create(); 52 | createZigbeeTempSensorDevice(endpointList); /* create temperature endpoint and add it to endpoint list */ 53 | createZigbeeCo2SensorDevice(endpointList); /* create co2 endpoint and add it to endpoint list */ 54 | createZigbeeLightDevice(endpointList); /* create light endpoint and add it to endpoint list */ 55 | createZigbeeHumiditySensorDevice(endpointList); /* create humidity endpoint and add it to endpoint list */ 56 | esp_zb_device_register(endpointList); /* take endpoint list and register the whole list */ 57 | 58 | /* Config the reporting info */ 59 | esp_zb_zcl_reporting_info_t temp_reporting_info = {}; 60 | temp_reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; 61 | temp_reporting_info.ep = HA_ESP_TEMPERATURE_ENDPOINT; // Temperature sensor endpoint 62 | temp_reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; 63 | temp_reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; 64 | temp_reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; 65 | temp_reporting_info.u.send_info.min_interval = 0; 66 | temp_reporting_info.u.send_info.max_interval = 1; 67 | temp_reporting_info.u.send_info.delta.u16 = 0; 68 | temp_reporting_info.u.send_info.def_min_interval = 0; 69 | temp_reporting_info.u.send_info.def_max_interval = 1; 70 | temp_reporting_info.attr_id = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID; 71 | temp_reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; 72 | ESP_ERROR_CHECK(esp_zb_zcl_update_reporting_info(&temp_reporting_info)); 73 | log_i("UPDATE REPORTING INFO TEMP"); 74 | 75 | /* Config the reporting info */ 76 | esp_zb_zcl_reporting_info_t co2_reporting_info = {}; 77 | co2_reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; 78 | co2_reporting_info.ep = HA_ESP_CO2_ENDPOINT; 79 | co2_reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT; 80 | co2_reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; 81 | co2_reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; 82 | co2_reporting_info.u.send_info.min_interval = 0; 83 | co2_reporting_info.u.send_info.max_interval = 1; 84 | co2_reporting_info.u.send_info.delta.u16 = 0; 85 | co2_reporting_info.u.send_info.def_min_interval = 0; 86 | co2_reporting_info.u.send_info.def_max_interval = 1; 87 | co2_reporting_info.attr_id = ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID; 88 | co2_reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; 89 | ESP_ERROR_CHECK(esp_zb_zcl_update_reporting_info(&co2_reporting_info)); 90 | log_i("UPDATE REPORTING INFO CO2"); 91 | 92 | /* Config the reporting info */ 93 | esp_zb_zcl_reporting_info_t humidity_reporting_info = {}; 94 | humidity_reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV; 95 | humidity_reporting_info.ep = HA_ESP_HUMIDITY_ENDPOINT; 96 | humidity_reporting_info.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT; 97 | humidity_reporting_info.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE; 98 | humidity_reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID; 99 | humidity_reporting_info.u.send_info.min_interval = 0; 100 | humidity_reporting_info.u.send_info.max_interval = 1; 101 | humidity_reporting_info.u.send_info.delta.u16 = 0; 102 | humidity_reporting_info.u.send_info.def_min_interval = 0; 103 | humidity_reporting_info.u.send_info.def_max_interval = 1; 104 | humidity_reporting_info.attr_id = ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID; 105 | humidity_reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC; 106 | ESP_ERROR_CHECK(esp_zb_zcl_update_reporting_info(&humidity_reporting_info)); 107 | log_i("UPDATE REPORTING INFO HUMIDITY"); 108 | 109 | esp_zb_core_action_handler_register(zb_action_handler); 110 | 111 | esp_zb_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK); 112 | 113 | ESP_ERROR_CHECK(esp_zb_start(false)); 114 | 115 | esp_zb_main_loop_iteration(); // internal main loop!!!!! 116 | } 117 | /************************ Temp sensor *****************************/ 118 | static void esp_app_temp_sensor_handler(void *pvParameters) { 119 | while (1) { // loop forever in task 120 | 121 | int16_t temp_measured_value = SCD30_temp * 100; // value can't be float, *100 for 2 decimals 122 | float co2_measured_value = SCD30_CO2 / 1000000.0; // value between 0...1 123 | uint16_t humidity_measured_value = SCD30_humid * 100; // value can't be float, *100 for 2 decimals 124 | 125 | //int16_t measured_value = 500 * sin(0.005 * millis() / 1000) + 2000; 126 | 127 | /* Update temperature sensor measured value */ 128 | esp_zb_lock_acquire(portMAX_DELAY); 129 | esp_zb_zcl_set_attribute_val(HA_ESP_TEMPERATURE_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_measured_value, false); 130 | esp_zb_lock_release(); 131 | 132 | esp_zb_lock_acquire(portMAX_DELAY); 133 | esp_zb_zcl_set_attribute_val(HA_ESP_CO2_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_CARBON_DIOXIDE_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_ID, &co2_measured_value, false); 134 | esp_zb_lock_release(); 135 | 136 | esp_zb_lock_acquire(portMAX_DELAY); 137 | esp_zb_zcl_set_attribute_val(HA_ESP_HUMIDITY_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_ID, &humidity_measured_value, false); 138 | esp_zb_lock_release(); 139 | 140 | log_i("Updating sensor value: %d C and %fPPM and %f", temp_measured_value, co2_measured_value, humidity_measured_value); 141 | vTaskDelay(SENSOR_UPDATE_INTERVAL * 1000 / portTICK_PERIOD_MS); // delay alternative for Tasks. Dont use delay()! 142 | } 143 | } 144 | 145 | /********************* Arduino functions **************************/ 146 | void setup() { 147 | Serial.begin(115200); 148 | Serial.println("Starting"); // will be shown in the terminal 149 | Serial.setDebugOutput(true); // show debug messages in Serial 150 | 151 | // Init RMT and leave light OFF 152 | neopixelWrite(LED_PIN, 0, 0, 0); 153 | 154 | // Start Temperature sensor reading task 155 | xTaskCreate(SCD30_sensor_handler, "SCD30_sensor_read", 4096, NULL, 10, NULL); 156 | 157 | // Wait for SCD30... 158 | vTaskDelay(100 / portTICK_PERIOD_MS); // delay alternative for Tasks. Dont use delay()! 159 | 160 | // Start Zigbee task 161 | xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); 162 | 163 | // Start Temperature sensor writing task 164 | xTaskCreate(esp_app_temp_sensor_handler, "temp_sensor_write", 2048, NULL, 10, NULL); 165 | } 166 | 167 | void loop() { 168 | // nothing here, runs in task 169 | ; 170 | } 171 | -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/actionHandler.ino: -------------------------------------------------------------------------------- 1 | // 2 | // Action Handler for Light Bulb 3 | // 4 | 5 | static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { 6 | esp_err_t ret = ESP_OK; 7 | switch (callback_id) { 8 | case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); break; 9 | default: log_w("Receive Zigbee action(0x%x) callback", callback_id); break; 10 | } 11 | return ret; 12 | } 13 | 14 | /* Handle the light attribute */ 15 | static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { 16 | esp_err_t ret = ESP_OK; 17 | bool light_state = 0; 18 | 19 | if (!message) { 20 | log_e("Empty message"); 21 | } 22 | if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) { 23 | log_e("Received message: error status(%d)", message->info.status); 24 | } 25 | 26 | log_i( 27 | "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, 28 | message->attribute.data.size); 29 | if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { 30 | if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { 31 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { 32 | light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; 33 | log_i("Light sets to %s", light_state ? "On" : "Off"); 34 | neopixelWrite(LED_PIN, 255 * light_state, 255 * light_state, 255 * light_state); // Toggle light 35 | } 36 | } 37 | } 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/createEndpoints.ino: -------------------------------------------------------------------------------- 1 | // 2 | // creating multiple endpoints 3 | // 4 | // Endpoint 1: createZigbeeTempSensorDevice 5 | // Endpoint 2: createZigbeeCo2SensorDevice 6 | // Endpoint 3: createZigbeeHumiditySensorDevice 7 | // Endpoint 4: createZigbeeLightDevice 8 | // 9 | 10 | static void createZigbeeTempSensorDevice(esp_zb_ep_list_t *endpointList) { 11 | /* Create customized temperature sensor endpoint */ 12 | esp_zb_temperature_sensor_cfg_t sensorConfig = ESP_ZB_DEFAULT_TEMPERATURE_SENSOR_CONFIG(); 13 | sensorConfig.temp_meas_cfg.min_value = ESP_TEMP_SENSOR_MIN_VALUE * 100; 14 | sensorConfig.temp_meas_cfg.max_value = ESP_TEMP_SENSOR_MAX_VALUE * 100; 15 | 16 | esp_zb_endpoint_config_t endpointConfig = {}; 17 | endpointConfig.endpoint = HA_ESP_TEMPERATURE_ENDPOINT; // Temperature sensor endpoint 18 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 19 | endpointConfig.app_device_id = ESP_ZB_HA_TEMPERATURE_SENSOR_DEVICE_ID; 20 | endpointConfig.app_device_version = 0; 21 | 22 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 23 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&(sensorConfig.basic_cfg)); 24 | 25 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 26 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 27 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 28 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(sensorConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 29 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 30 | 31 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_temperature_meas_cluster(clusterList, esp_zb_temperature_meas_cluster_create(&(sensorConfig.temp_meas_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 32 | 33 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 34 | } 35 | 36 | static void createZigbeeCo2SensorDevice(esp_zb_ep_list_t *endpointList) { 37 | /* Create customized co2 sensor endpoint */ 38 | esp_zb_carbon_dioxide_sensor_cfg_t sensorConfig = {}; 39 | sensorConfig.basic_cfg.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE; 40 | sensorConfig.basic_cfg.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE; 41 | sensorConfig.identify_cfg.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; 42 | sensorConfig.carbon_dioxide_meas_cfg.measured_value = ESP_ZB_ZCL_CARBON_DIOXIDE_MEASUREMENT_MEASURED_VALUE_DEFAULT_VALUE; 43 | sensorConfig.carbon_dioxide_meas_cfg.min_measured_value = CARBON_DIOXIDE_MIN_VALUE / 1000000.0; // PPM 44 | sensorConfig.carbon_dioxide_meas_cfg.max_measured_value = CARBON_DIOXIDE_MAX_VALUE / 1000000.0; // PPM 45 | 46 | esp_zb_endpoint_config_t endpointConfig = {}; 47 | endpointConfig.endpoint = HA_ESP_CO2_ENDPOINT; 48 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 49 | endpointConfig.app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; 50 | endpointConfig.app_device_version = 0; 51 | 52 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 53 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&(sensorConfig.basic_cfg)); 54 | 55 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 56 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 57 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 58 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(sensorConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 59 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 60 | 61 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_carbon_dioxide_measurement_cluster(clusterList, esp_zb_carbon_dioxide_measurement_cluster_create(&(sensorConfig.carbon_dioxide_meas_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 62 | 63 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 64 | } 65 | 66 | static void createZigbeeHumiditySensorDevice(esp_zb_ep_list_t *endpointList) { 67 | esp_zb_humidity_sensor_cfg_t sensorConfig = {}; 68 | sensorConfig.basic_cfg.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE; 69 | sensorConfig.basic_cfg.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE; 70 | sensorConfig.identify_cfg.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; 71 | sensorConfig.humidity_meas_cfg.measured_value = ESP_ZB_ZCL_ATTR_REL_HUMIDITY_MEASUREMENT_VALUE_DEFAULT; 72 | sensorConfig.humidity_meas_cfg.min_value = HUMIDITY_MIN_VALUE; // 0...95 % 73 | sensorConfig.humidity_meas_cfg.max_value = HUMIDITY_MAX_VALUE; // 0...95 % 74 | 75 | esp_zb_endpoint_config_t endpointConfig = {}; 76 | endpointConfig.endpoint = HA_ESP_HUMIDITY_ENDPOINT; 77 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 78 | endpointConfig.app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID; 79 | endpointConfig.app_device_version = 0; 80 | 81 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 82 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&(sensorConfig.basic_cfg)); 83 | 84 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 85 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 86 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 87 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(sensorConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 88 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 89 | 90 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_humidity_meas_cluster(clusterList, esp_zb_humidity_meas_cluster_create(&(sensorConfig.humidity_meas_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 91 | 92 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 93 | } 94 | 95 | static void createZigbeeLightDevice(esp_zb_ep_list_t *endpointList) { 96 | /* Create customized Light endpoint */ 97 | esp_zb_on_off_light_cfg_t lightConfig = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); 98 | 99 | esp_zb_endpoint_config_t endpointConfig = {}; 100 | endpointConfig.endpoint = HA_ESP_LIGHT_ENDPOINT; 101 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 102 | endpointConfig.app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; 103 | endpointConfig.app_device_version = 0; 104 | 105 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 106 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&lightConfig.basic_cfg); 107 | 108 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 109 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 110 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 111 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(lightConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 112 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 113 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_on_off_cluster(clusterList, esp_zb_on_off_cluster_create(&lightConfig.on_off_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 114 | 115 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 116 | } -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/defines.h: -------------------------------------------------------------------------------- 1 | #define LED_PIN RGB_BUILTIN 2 | 3 | /* Zigbee configuration */ 4 | #define MAX_CHILDREN 10 /* the max amount of connected devices */ 5 | #define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ 6 | #define HA_ESP_TEMPERATURE_ENDPOINT 15 /* esp temperature sensor device endpoint, used for temperature measurement */ 7 | #define HA_ESP_CO2_ENDPOINT 16 /* esp co2 sensor device endpoint, used for co2 measurement */ 8 | #define HA_ESP_HUMIDITY_ENDPOINT 17 /* esp humidity sensor device endpoint, used for humidity measurement */ 9 | #define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ 10 | 11 | /* Sensor update interval */ 12 | #define SENSOR_UPDATE_INTERVAL (5) /* Seconds */ 13 | 14 | /* Temperature Sensor configuration */ 15 | #define ESP_TEMP_SENSOR_MIN_VALUE (-40) /* Temperature sensor min measured value (degree Celsius) */ 16 | #define ESP_TEMP_SENSOR_MAX_VALUE (70) /* Temperature sensor max measured value (degree Celsius) */ 17 | 18 | /* Carbon Dioxide Sensor configuration */ 19 | #define CARBON_DIOXIDE_MIN_VALUE (400) 20 | #define CARBON_DIOXIDE_MAX_VALUE (10000) 21 | 22 | /* Humidity Sensor configuration */ 23 | #define HUMIDITY_MIN_VALUE (0) 24 | #define HUMIDITY_MAX_VALUE (95) 25 | 26 | /* Attribute values in ZCL string format 27 | * The string should be started with the length of its own. */ 28 | #define MANUFACTURER_NAME "\x12" \ 29 | "MicroMasterMinds" 30 | #define MODEL_IDENTIFIER "\x0A" \ 31 | "Gas-Sensor" 32 | 33 | /** 34 | * @brief Zigbee carbon dioxide measurement cluster. 35 | * 36 | */ 37 | typedef struct esp_zb_carbon_dioxide_measurement_sensor_cfg_s { 38 | esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */ 39 | esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */ 40 | esp_zb_carbon_dioxide_measurement_cluster_cfg_t carbon_dioxide_meas_cfg; /*!< Carbon Dioxide measurement cluster configuration, @ref esp_zb_carbon_dioxide_meas_cluster_cfg_s */ 41 | } esp_zb_carbon_dioxide_sensor_cfg_t; 42 | 43 | /** 44 | * @brief Zigbee standard mandatory attribute for humidity measurement cluster. 45 | * 46 | */ 47 | typedef struct esp_zb_humidity_measurement_sensor_cfg_s { 48 | esp_zb_basic_cluster_cfg_t basic_cfg; /*!< Basic cluster configuration, @ref esp_zb_basic_cluster_cfg_s */ 49 | esp_zb_identify_cluster_cfg_t identify_cfg; /*!< Identify cluster configuration, @ref esp_zb_identify_cluster_cfg_s */ 50 | esp_zb_humidity_meas_cluster_cfg_t humidity_meas_cfg; /*!< Carbon Dioxide measurement cluster configuration, @ref esp_zb_carbon_dioxide_meas_cluster_cfg_s */ 51 | } esp_zb_humidity_sensor_cfg_t; -------------------------------------------------------------------------------- /Zigbee_Multiple_Endpoint_Router_V1/esp_zb_app_signal_handler.ino: -------------------------------------------------------------------------------- 1 | // 2 | // After esp_zb_start, user shall based on the corresponding signal type refer to 3 | // esp_zdo_app_signal_type from struct pointer signal_s to do certain actions. User could also 4 | // use refer to esp_zb_bdb_start_top_level_commissioning to change BDB mode. 5 | // 6 | 7 | static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { 8 | ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); 9 | } 10 | 11 | void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { 12 | 13 | esp_err_t err_status = signal_struct->esp_err_status; 14 | esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*signal_struct->p_app_signal; 15 | 16 | log_i("Zigbee signal: %s", esp_zb_zdo_signal_to_string(sig_type)); 17 | 18 | switch (sig_type) { 19 | 20 | case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: 21 | log_i("Zigbee stack initialized"); 22 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); 23 | break; 24 | 25 | case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: 26 | [[fallthrough]]; 27 | 28 | case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: 29 | log_i("Device started up, joining network..."); 30 | 31 | if (err_status == ESP_OK) { 32 | log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); 33 | 34 | if (esp_zb_bdb_is_factory_new()) { 35 | log_i("Start network steering"); 36 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); 37 | return; 38 | } else { 39 | log_i("Device rebooted"); 40 | } 41 | } else { 42 | /* commissioning failed */ 43 | log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); 44 | return; 45 | } 46 | break; 47 | 48 | case ESP_ZB_BDB_SIGNAL_STEERING: 49 | if (err_status == ESP_OK) { 50 | esp_zb_ieee_addr_t extended_pan_id; 51 | esp_zb_get_extended_pan_id(extended_pan_id); 52 | log_i( 53 | "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", 54 | 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], 55 | extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); 56 | return; 57 | } else { 58 | log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); 59 | esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); 60 | } 61 | break; 62 | 63 | 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; 64 | } 65 | } -------------------------------------------------------------------------------- /Zigbee_RGB_Light_Bulb_Router_V1/Zigbee_RGB_Light_Bulb_Router_V1.ino: -------------------------------------------------------------------------------- 1 | // Based on Espressif Light Bulb Example 2 | // 3 | // Modified by MicroMasterMinds 🤯 4 | // 5 | // Hoffe es funzt auch 😂 6 | 7 | #ifndef ZIGBEE_MODE_ZCZR // Coordinator Device or Router Device 8 | #error "Zigbee router mode is not selected in Tools->Zigbee mode" 9 | #endif 10 | 11 | #include "esp_zigbee_core.h" 12 | #include "freertos/FreeRTOS.h" 13 | #include "freertos/task.h" 14 | #include "ha/esp_zigbee_ha_standard.h" 15 | 16 | #define LED_PIN RGB_BUILTIN 17 | 18 | /* Zigbee configuration */ 19 | #define MAX_CHILDREN 10 /* the max amount of connected devices */ 20 | #define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ 21 | #define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ 22 | 23 | /* Attribute values in ZCL string format 24 | * The string should be started with the length of its own. */ 25 | #define MANUFACTURER_NAME "\x12" \ 26 | "MicroMasterMinds" 27 | #define MODEL_IDENTIFIER "\x07" \ 28 | "Light" 29 | 30 | /********************* Zigbee functions **************************/ 31 | static void createZigbeeLightDevice() { 32 | /* Create customized Light endpoint */ 33 | esp_zb_color_dimmable_light_cfg_t lightConfig = ESP_ZB_DEFAULT_COLOR_DIMMABLE_LIGHT_CONFIG(); 34 | 35 | esp_zb_ep_list_t *endpointList = esp_zb_ep_list_create(); 36 | esp_zb_endpoint_config_t endpointConfig = {}; 37 | endpointConfig.endpoint = HA_ESP_LIGHT_ENDPOINT; 38 | endpointConfig.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID; 39 | endpointConfig.app_device_id = ESP_ZB_HA_ON_OFF_LIGHT_DEVICE_ID; 40 | endpointConfig.app_device_version = 0; 41 | 42 | esp_zb_cluster_list_t *clusterList = esp_zb_zcl_cluster_list_create(); 43 | esp_zb_attribute_list_t *basicCluster = esp_zb_basic_cluster_create(&lightConfig.basic_cfg); 44 | 45 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)MANUFACTURER_NAME)); 46 | ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basicCluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)MODEL_IDENTIFIER)); 47 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(clusterList, basicCluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 48 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_identify_cluster_create(&(lightConfig.identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 49 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(clusterList, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE)); 50 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_on_off_cluster(clusterList, esp_zb_on_off_cluster_create(&lightConfig.on_off_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 51 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_level_cluster(clusterList, esp_zb_level_cluster_create(&lightConfig.level_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 52 | ESP_ERROR_CHECK(esp_zb_cluster_list_add_color_control_cluster(clusterList, esp_zb_color_control_cluster_create(&lightConfig.color_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE)); 53 | 54 | esp_zb_ep_list_add_ep(endpointList, clusterList, endpointConfig); 55 | 56 | /* Register the device */ 57 | esp_zb_device_register(endpointList); 58 | } 59 | 60 | static void esp_zb_task(void *pvParameters) { 61 | /* Initialize Zigbee platform */ 62 | esp_zb_platform_config_t platformConfig = {}; 63 | platformConfig.radio_config.radio_mode = ZB_RADIO_MODE_NATIVE; 64 | platformConfig.host_config.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE; 65 | ESP_ERROR_CHECK(esp_zb_platform_config(&platformConfig)); 66 | 67 | /* Initialize Zigbee stack */ 68 | esp_zb_cfg_t stackConfig = {}; 69 | stackConfig.esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER; 70 | stackConfig.install_code_policy = INSTALLCODE_POLICY_ENABLE; 71 | stackConfig.nwk_cfg.zczr_cfg.max_children = MAX_CHILDREN; 72 | esp_zb_init(&stackConfig); 73 | 74 | createZigbeeLightDevice(); 75 | 76 | esp_zb_core_action_handler_register(zb_action_handler); 77 | 78 | esp_zb_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK); 79 | 80 | //esp_zb_zcl_reset_nvram_to_factory_default(); 81 | 82 | //esp_zb_nvram_erase_at_start(true); 83 | 84 | ESP_ERROR_CHECK(esp_zb_start(false)); 85 | 86 | esp_zb_main_loop_iteration(); 87 | } 88 | /********************* Arduino functions **************************/ 89 | void setup() { 90 | Serial.begin(115200); 91 | Serial.println("Starting"); // will be shown in the terminal 92 | Serial.setDebugOutput(true); // show debug messages in Serial 93 | 94 | // Init RMT and leave light OFF 95 | neopixelWrite(LED_PIN, 0, 0, 0); 96 | 97 | // Start Zigbee task 98 | xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); 99 | } 100 | 101 | void loop() { 102 | // nothing here, runs in task 103 | ; 104 | } 105 | -------------------------------------------------------------------------------- /Zigbee_RGB_Light_Bulb_Router_V1/actionHandler.ino: -------------------------------------------------------------------------------- 1 | // 2 | // action handler 3 | // 4 | 5 | esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) { 6 | esp_err_t ret = ESP_OK; 7 | switch (callback_id) { 8 | case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: 9 | ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); 10 | break; 11 | default: 12 | log_w("Receive Zigbee action(0x%x) callback", callback_id); 13 | break; 14 | } 15 | return ret; 16 | } 17 | 18 | esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) { 19 | esp_err_t ret = ESP_OK; 20 | bool light_state = 0; 21 | uint8_t light_level = 0; 22 | uint16_t light_color_x = 0; 23 | uint16_t light_color_y = 0; 24 | if (message == NULL) 25 | log_e("Empty message!"); 26 | if (message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS) 27 | log_e("Received message: error status(%d)", message->info.status); 28 | 29 | log_i("Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, 30 | message->attribute.id, message->attribute.data.size); 31 | 32 | 33 | if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { 34 | switch (message->info.cluster) { 35 | 36 | case ESP_ZB_ZCL_CLUSTER_ID_ON_OFF: 37 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { 38 | light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; 39 | log_i("Light sets to %s", light_state ? "On" : "Off"); 40 | light_driver_set_power(light_state); 41 | } else { 42 | log_w("On/Off cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); 43 | } 44 | break; 45 | 46 | case ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL: 47 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { 48 | light_color_x = message->attribute.data.value ? *(uint16_t *)message->attribute.data.value : light_color_x; 49 | light_color_y = *(uint16_t *)esp_zb_zcl_get_attribute(message->info.dst_endpoint, message->info.cluster, 50 | ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID) 51 | ->data_p; 52 | log_i("Light color x changes to 0x%x", light_color_x); 53 | } else if (message->attribute.id == ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_Y_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { 54 | light_color_y = message->attribute.data.value ? *(uint16_t *)message->attribute.data.value : light_color_y; 55 | light_color_x = *(uint16_t *)esp_zb_zcl_get_attribute(message->info.dst_endpoint, message->info.cluster, 56 | ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_COLOR_CONTROL_CURRENT_X_ID) 57 | ->data_p; 58 | log_i("Light color y changes to 0x%x", light_color_y); 59 | } else { 60 | log_w("Color control cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); 61 | } 62 | light_driver_set_color_xy(light_color_x, light_color_y); 63 | break; 64 | 65 | case ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL: 66 | if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { 67 | light_level = message->attribute.data.value ? *(uint8_t *)message->attribute.data.value : light_level; 68 | light_driver_set_level((uint8_t)light_level); 69 | log_i("Light level changes to %d", light_level); 70 | } else { 71 | log_w("Level Control cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); 72 | } 73 | break; 74 | 75 | default: 76 | log_i("Message data: cluster(0x%x), attribute(0x%x) ", message->info.cluster, message->attribute.id); 77 | } 78 | } 79 | return ret; 80 | } -------------------------------------------------------------------------------- /Zigbee_RGB_Light_Bulb_Router_V1/lightDriver.ino: -------------------------------------------------------------------------------- 1 | /** Convert Hue,Saturation,V to RGB 2 | * RGB - [0..0xffff] 3 | * hue - [0..0xff] 4 | * Sat - [0..0xff] 5 | * V always = (ZB_UINT16_MAX-1) 6 | */ 7 | #define HSV_to_RGB(h, s, v, r, g, b) \ 8 | { \ 9 | uint8_t i; \ 10 | uint8_t sector = UINT8_MAX / 6; \ 11 | float f, p, q, t; \ 12 | if (s == 0) { /* achromatic (grey)*/ \ 13 | r = g = b = (v); \ 14 | } else { \ 15 | i = h / sector; /* sector 0 to 5 */ \ 16 | f = h % sector; /* factorial part of h*/ \ 17 | p = (float)(v * (1.0 - (float)s / UINT8_MAX)); \ 18 | q = (float)(v * (1.0 - (float)s / UINT8_MAX * f / (float)sector)); \ 19 | t = (float)(v * (1.0 - (float)s / UINT8_MAX * (1 - f / (float)sector))); \ 20 | switch (i) { \ 21 | case 0: \ 22 | r = (v); \ 23 | g = t; \ 24 | b = p; \ 25 | break; \ 26 | case 1: \ 27 | r = q; \ 28 | g = (v); \ 29 | b = p; \ 30 | break; \ 31 | case 2: \ 32 | r = p; \ 33 | g = (v); \ 34 | b = t; \ 35 | break; \ 36 | case 3: \ 37 | r = p; \ 38 | g = q; \ 39 | b = (v); \ 40 | break; \ 41 | case 4: \ 42 | r = t; \ 43 | g = p; \ 44 | b = (v); \ 45 | break; \ 46 | case 5: \ 47 | default: \ 48 | r = (v); \ 49 | g = p; \ 50 | b = q; \ 51 | break; \ 52 | } \ 53 | } \ 54 | } 55 | 56 | #define XYZ_to_RGB(X, Y, Z, r, g, b) \ 57 | { \ 58 | r = (float)(3.240479 * (X)-1.537150 * (Y)-0.498535 * (Z)); \ 59 | g = (float)(-0.969256 * (X) + 1.875992 * (Y) + 0.041556 * (Z)); \ 60 | b = (float)(0.055648 * (X)-0.204043 * (Y) + 1.057311 * (Z)); \ 61 | if (r > 1) { r = 1; } \ 62 | if (g > 1) { g = 1; } \ 63 | if (b > 1) { b = 1; } \ 64 | } 65 | 66 | // static led_strip_handle_t s_led_strip; 67 | static uint8_t s_red = 255, s_green = 255, s_blue = 255, s_level = 255; 68 | 69 | void light_driver_set_color_xy(uint16_t color_current_x, uint16_t color_current_y) { 70 | float red_f = 0, green_f = 0, blue_f = 0, color_x, color_y; 71 | color_x = (float)color_current_x / 65535; 72 | color_y = (float)color_current_y / 65535; 73 | /* assume color_Y is full light level value 1 (0-1.0) */ 74 | float color_X = color_x / color_y; 75 | float color_Z = (1 - color_x - color_y) / color_y; 76 | /* change from xy to linear RGB NOT sRGB */ 77 | XYZ_to_RGB(color_X, 1, color_Z, red_f, green_f, blue_f); 78 | float ratio = (float)s_level / 255; 79 | s_red = (uint8_t)(red_f * (float)255); 80 | s_green = (uint8_t)(green_f * (float)255); 81 | s_blue = (uint8_t)(blue_f * (float)255); 82 | neopixelWrite(RGB_BUILTIN, s_red * ratio, s_green * ratio, s_blue * ratio); 83 | // ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio)); 84 | // ESP_ERROR_CHECK(led_strip_refresh(s_led_strip)); 85 | } 86 | 87 | void light_driver_set_color_hue_sat(uint8_t hue, uint8_t sat) { 88 | float red_f, green_f, blue_f; 89 | HSV_to_RGB(hue, sat, UINT8_MAX, red_f, green_f, blue_f); 90 | float ratio = (float)s_level / 255; 91 | s_red = (uint8_t)red_f; 92 | s_green = (uint8_t)green_f; 93 | s_blue = (uint8_t)blue_f; 94 | neopixelWrite(RGB_BUILTIN, s_red * ratio, s_green * ratio, s_blue * ratio); 95 | // ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio)); 96 | // ESP_ERROR_CHECK(led_strip_refresh(s_led_strip)); 97 | } 98 | 99 | void light_driver_set_color_RGB(uint8_t red, uint8_t green, uint8_t blue) { 100 | float ratio = (float)s_level / 255; 101 | s_red = red; 102 | s_green = green; 103 | s_blue = blue; 104 | neopixelWrite(RGB_BUILTIN, s_red * ratio, s_green * ratio, s_blue * ratio); 105 | // ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, red * ratio, green * ratio, blue * ratio)); 106 | // ESP_ERROR_CHECK(led_strip_refresh(s_led_strip)); 107 | } 108 | 109 | void light_driver_set_power(bool power) { 110 | neopixelWrite(RGB_BUILTIN, s_red * power, s_green * power, s_blue * power); 111 | // ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * power, s_green * power, s_blue * power)); 112 | // ESP_ERROR_CHECK(led_strip_refresh(s_led_strip)); 113 | } 114 | 115 | void light_driver_set_level(uint8_t level) { 116 | s_level = level; 117 | float ratio = (float)s_level / 255; 118 | neopixelWrite(RGB_BUILTIN, s_red * ratio, s_green * ratio, s_blue * ratio); 119 | // ESP_ERROR_CHECK(led_strip_set_pixel(s_led_strip, 0, s_red * ratio, s_green * ratio, s_blue * ratio)); 120 | // ESP_ERROR_CHECK(led_strip_refresh(s_led_strip)); 121 | } 122 | -------------------------------------------------------------------------------- /Zigbee_RGB_Light_Bulb_Router_V1/signalHandler.ino: -------------------------------------------------------------------------------- 1 | // 2 | // After esp_zb_start, user shall based on the corresponding signal type refer to 3 | // esp_zdo_app_signal_type from struct pointer signal_s to do certain actions. User could also 4 | // use refer to esp_zb_bdb_start_top_level_commissioning to change BDB mode. 5 | // 6 | 7 | static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { 8 | ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); 9 | } 10 | 11 | void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { 12 | 13 | esp_err_t err_status = signal_struct->esp_err_status; 14 | esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*signal_struct->p_app_signal; 15 | 16 | log_i("Zigbee signal: %s", esp_zb_zdo_signal_to_string(sig_type)); 17 | 18 | switch (sig_type) { 19 | 20 | case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: 21 | log_i("Zigbee stack initialized"); 22 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); 23 | break; 24 | 25 | case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: 26 | [[fallthrough]]; 27 | 28 | case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: 29 | log_i("Device started up, joining network..."); 30 | 31 | if (err_status == ESP_OK) { 32 | log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non"); 33 | 34 | if (esp_zb_bdb_is_factory_new()) { 35 | log_i("Start network steering"); 36 | esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); 37 | return; 38 | } else { 39 | log_i("Device rebooted"); 40 | } 41 | } else { 42 | /* commissioning failed */ 43 | log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); 44 | return; 45 | } 46 | break; 47 | 48 | case ESP_ZB_BDB_SIGNAL_STEERING: 49 | if (err_status == ESP_OK) { 50 | esp_zb_ieee_addr_t extended_pan_id; 51 | esp_zb_get_extended_pan_id(extended_pan_id); 52 | log_i( 53 | "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", 54 | 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], 55 | extended_pan_id[0], esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); 56 | return; 57 | } else { 58 | log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); 59 | esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); 60 | } 61 | break; 62 | 63 | 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; 64 | } 65 | } --------------------------------------------------------------------------------