From 1ecb566b5d24437965fb8a586ff65f913f45694c Mon Sep 17 00:00:00 2001 From: rippanda12 Date: Mon, 15 Sep 2025 15:03:44 +0300 Subject: [PATCH 1/3] feat(zigbee): OTA inhibit sleep --- .../Zigbee_Temp_Hum_Sensor_Sleepy.ino | 35 +++++++++++++++++-- libraries/Zigbee/src/ZigbeeEP.cpp | 7 ++++ libraries/Zigbee/src/ZigbeeEP.h | 6 ++++ libraries/Zigbee/src/ZigbeeHandlers.cpp | 15 ++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino index 54c085fbfea..f20d2acbdf5 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -32,6 +32,12 @@ #include "Zigbee.h" +/* Zigbee OTA configuration */ + +#define OTA_UPGRADE_RUNNING_FILE_VERSION 0x01010100 // Increment this value when the running image is updated +#define OTA_UPGRADE_DOWNLOADED_FILE_VERSION 0x01010101 // Increment this value when the downloaded image is updated +#define OTA_UPGRADE_HW_VERSION 0x0101 // The hardware version, this can be used to differentiate between different hardware versions + #define USE_GLOBAL_ON_RESPONSE_CALLBACK 1 // Set to 0 to use local callback specified directly for the endpoint. /* Zigbee temperature + humidity sensor configuration */ @@ -45,6 +51,7 @@ uint8_t button = BOOT_PIN; ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); +volatile bool otaInhibitSleep = false; uint8_t dataToSend = 2; // Temperature and humidity values are reported in same endpoint, so 2 values are reported bool resend = false; @@ -73,6 +80,15 @@ void onResponse(zb_cmd_type_t command, esp_zb_zcl_status_t status) { } #endif +void otaSleepInhibitCallback(bool otaActive) { + otaInhibitSleep = otaActive; + if (otaActive) { + Serial.println("OTA started: inhibiting sleep"); + } else { + Serial.println("OTA finished: sleep allowed"); + } +} + /************************ Temp sensor *****************************/ static void meausureAndSleep(void *arg) { // Measure temperature sensor value @@ -115,8 +131,10 @@ static void meausureAndSleep(void *arg) { } // Put device to deep sleep after data was sent successfully or timeout - Serial.println("Going to sleep now"); - esp_deep_sleep_start(); + if (!otaInhibitSleep) { + Serial.println("Going to sleep now"); + esp_deep_sleep_start(); + } } /********************* Arduino functions **************************/ @@ -132,6 +150,12 @@ void setup() { // Optional: set Zigbee device name and model zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensor"); + // Optional: set ota + zbTempSensor.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION); + + // Optional: Register callback for OTA state change (inhibit sleep during OTA) + zbTempSensor.onOTAStateChange(otaSleepInhibitCallback); + // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement) zbTempSensor.setMinMaxValue(10, 50); @@ -180,6 +204,9 @@ void setup() { Serial.println(); Serial.println("Successfully connected to Zigbee network"); + // Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically + zbLight.requestOTAUpdate(); + // Start Temperature sensor reading task xTaskCreate(meausureAndSleep, "temp_sensor_update", 2048, NULL, 10, NULL); } @@ -193,6 +220,10 @@ void loop() { while (digitalRead(button) == LOW) { delay(50); if ((millis() - startTime) > 10000) { + if (otaInhibitSleep) { + Serial.println("OTA in progress, cannot reset now"); + break; + } // If key pressed for more than 10secs, factory reset Zigbee and reboot Serial.println("Resetting Zigbee to factory and rebooting in 1s."); delay(1000); diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 5e4d9a38545..b857eb5e7a5 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -28,6 +28,7 @@ ZigbeeEP::ZigbeeEP(uint8_t endpoint) { _ep_config.endpoint = 0; _cluster_list = nullptr; _on_identify = nullptr; + _on_ota_state_change = nullptr; _read_model = NULL; _read_manufacturer = NULL; _time_status = 0; @@ -318,6 +319,12 @@ void ZigbeeEP::zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message) { } } +void ZigbeeEP::zbOTAState(bool otaActive) { + if (_on_ota_state_change != NULL) { + _on_ota_state_change(otaActive); + } +} + bool ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) { time_t utc_time = 0; // Check if time is set diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index a873205808f..3a7dea19a41 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -153,6 +153,7 @@ class ZigbeeEP { zbWriteAttributeResponse(uint16_t cluster_id, uint16_t attribute_id, esp_zb_zcl_status_t status, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {}; virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message); + virtual void zbOTAState(bool otaActive); virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {}; virtual void zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented virtual void zbIASZoneStatusChangeNotification(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message) {}; @@ -176,6 +177,10 @@ class ZigbeeEP { _on_identify = callback; } + void onOTAStateChange(void (*callback)(bool state)) { + _on_ota_state_change = callback; + } + void onDefaultResponse(void (*callback)(zb_cmd_type_t resp_to_cmd, esp_zb_zcl_status_t status)) { _on_default_response = callback; } @@ -186,6 +191,7 @@ class ZigbeeEP { char *_read_manufacturer; char *_read_model; void (*_on_identify)(uint16_t time); + void (*_on_ota_state_change)(bool state); void (*_on_default_response)(zb_cmd_type_t resp_to_cmd, esp_zb_zcl_status_t status); time_t _read_time; int32_t _read_timezone; diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index 29c4e670f66..9b574ea7422 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -338,6 +338,9 @@ static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_valu switch (message->upgrade_status) { case ESP_ZB_ZCL_OTA_UPGRADE_STATUS_START: log_i("Zigbee - OTA upgrade start"); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + (*it)->zbOTAState(true); // Notify that OTA is active + } start_time = esp_timer_get_time(); s_ota_partition = esp_ota_get_next_update_partition(NULL); assert(s_ota_partition); @@ -348,6 +351,9 @@ static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_valu #endif if (ret != ESP_OK) { log_e("Zigbee - Failed to begin OTA partition, status: %s", esp_err_to_name(ret)); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + (*it)->zbOTAState(false); // Notify that OTA is no longer active + } return ret; } break; @@ -361,6 +367,9 @@ static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_valu ret = esp_element_ota_data(total_size, message->payload, message->payload_size, &payload, &payload_size); if (ret != ESP_OK) { log_e("Zigbee - Failed to element OTA data, status: %s", esp_err_to_name(ret)); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + (*it)->zbOTAState(false); // Notify that OTA is no longer active + } return ret; } #if CONFIG_ZB_DELTA_OTA @@ -370,6 +379,9 @@ static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_valu #endif if (ret != ESP_OK) { log_e("Zigbee - Failed to write OTA data to partition, status: %s", esp_err_to_name(ret)); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + (*it)->zbOTAState(false); // Notify that OTA is no longer active + } return ret; } } @@ -389,6 +401,9 @@ static esp_err_t zb_ota_upgrade_status_handler(const esp_zb_zcl_ota_upgrade_valu message->ota_header.file_version, message->ota_header.manufacturer_code, message->ota_header.image_type, message->ota_header.image_size, (esp_timer_get_time() - start_time) / 1000 ); + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + (*it)->zbOTAState(false); // Notify that OTA is no longer active + } #if CONFIG_ZB_DELTA_OTA ret = esp_delta_ota_end(s_ota_handle); #else From a8164308cc621e746390308c63d59e0bdd400d47 Mon Sep 17 00:00:00 2001 From: Rippanda12 Date: Mon, 15 Sep 2025 16:46:09 +0300 Subject: [PATCH 2/3] fix(zigbee example): copy paste error --- .../Zigbee_Temp_Hum_Sensor_Sleepy.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino index f20d2acbdf5..f321fd6dac2 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -205,7 +205,7 @@ void setup() { Serial.println("Successfully connected to Zigbee network"); // Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically - zbLight.requestOTAUpdate(); + zbTempSensor.requestOTAUpdate(); // Start Temperature sensor reading task xTaskCreate(meausureAndSleep, "temp_sensor_update", 2048, NULL, 10, NULL); From 69e7d9c486a37a67556256cfdd6a28586e3356d6 Mon Sep 17 00:00:00 2001 From: rippanda12 Date: Tue, 16 Sep 2025 17:25:10 +0300 Subject: [PATCH 3/3] feat(zigbee examples): revert sleepy temp hum sensor instead add example to ota client --- .../Zigbee_OTA_Client/Zigbee_OTA_Client.ino | 19 ++++++++++ .../Zigbee_Temp_Hum_Sensor_Sleepy.ino | 35 ++----------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino b/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino index 29d114014b4..6ea2329a459 100644 --- a/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino +++ b/libraries/Zigbee/examples/Zigbee_OTA_Client/Zigbee_OTA_Client.ino @@ -44,6 +44,18 @@ uint8_t button = BOOT_PIN; ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT); +volatile bool otaRunning = false; + +/********************* Callbacks *************************/ +void otaActiveCallback(bool otaActive) { + otaRunning = otaActive; + if (otaActive) { + Serial.println("OTA started"); + } else { + Serial.println("OTA finished"); + } +} + /********************* RGB LED functions **************************/ void setLED(bool value) { digitalWrite(led, value); @@ -69,6 +81,9 @@ void setup() { // Add OTA client to the light bulb zbLight.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION); + // Optional: Register callback for OTA state change + zbLight.onOTAStateChange(otaActiveCallback); + // Add endpoint to Zigbee Core Serial.println("Adding ZigbeeLight endpoint to Zigbee Core"); Zigbee.addEndpoint(&zbLight); @@ -99,6 +114,10 @@ void loop() { while (digitalRead(button) == LOW) { delay(50); if ((millis() - startTime) > 3000) { + if (otaRunning) { + Serial.println("OTA in progress, cannot reset now"); + break; + } // If key pressed for more than 3secs, factory reset Zigbee and reboot Serial.println("Resetting Zigbee to factory and rebooting in 1s."); delay(1000); diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino index f321fd6dac2..54c085fbfea 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -32,12 +32,6 @@ #include "Zigbee.h" -/* Zigbee OTA configuration */ - -#define OTA_UPGRADE_RUNNING_FILE_VERSION 0x01010100 // Increment this value when the running image is updated -#define OTA_UPGRADE_DOWNLOADED_FILE_VERSION 0x01010101 // Increment this value when the downloaded image is updated -#define OTA_UPGRADE_HW_VERSION 0x0101 // The hardware version, this can be used to differentiate between different hardware versions - #define USE_GLOBAL_ON_RESPONSE_CALLBACK 1 // Set to 0 to use local callback specified directly for the endpoint. /* Zigbee temperature + humidity sensor configuration */ @@ -51,7 +45,6 @@ uint8_t button = BOOT_PIN; ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER); -volatile bool otaInhibitSleep = false; uint8_t dataToSend = 2; // Temperature and humidity values are reported in same endpoint, so 2 values are reported bool resend = false; @@ -80,15 +73,6 @@ void onResponse(zb_cmd_type_t command, esp_zb_zcl_status_t status) { } #endif -void otaSleepInhibitCallback(bool otaActive) { - otaInhibitSleep = otaActive; - if (otaActive) { - Serial.println("OTA started: inhibiting sleep"); - } else { - Serial.println("OTA finished: sleep allowed"); - } -} - /************************ Temp sensor *****************************/ static void meausureAndSleep(void *arg) { // Measure temperature sensor value @@ -131,10 +115,8 @@ static void meausureAndSleep(void *arg) { } // Put device to deep sleep after data was sent successfully or timeout - if (!otaInhibitSleep) { - Serial.println("Going to sleep now"); - esp_deep_sleep_start(); - } + Serial.println("Going to sleep now"); + esp_deep_sleep_start(); } /********************* Arduino functions **************************/ @@ -150,12 +132,6 @@ void setup() { // Optional: set Zigbee device name and model zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensor"); - // Optional: set ota - zbTempSensor.addOTAClient(OTA_UPGRADE_RUNNING_FILE_VERSION, OTA_UPGRADE_DOWNLOADED_FILE_VERSION, OTA_UPGRADE_HW_VERSION); - - // Optional: Register callback for OTA state change (inhibit sleep during OTA) - zbTempSensor.onOTAStateChange(otaSleepInhibitCallback); - // Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement) zbTempSensor.setMinMaxValue(10, 50); @@ -204,9 +180,6 @@ void setup() { Serial.println(); Serial.println("Successfully connected to Zigbee network"); - // Start Zigbee OTA client query, first request is within a minute and the next requests are sent every hour automatically - zbTempSensor.requestOTAUpdate(); - // Start Temperature sensor reading task xTaskCreate(meausureAndSleep, "temp_sensor_update", 2048, NULL, 10, NULL); } @@ -220,10 +193,6 @@ void loop() { while (digitalRead(button) == LOW) { delay(50); if ((millis() - startTime) > 10000) { - if (otaInhibitSleep) { - Serial.println("OTA in progress, cannot reset now"); - break; - } // If key pressed for more than 10secs, factory reset Zigbee and reboot Serial.println("Resetting Zigbee to factory and rebooting in 1s."); delay(1000);