3232
3333#include " Zigbee.h"
3434
35+ #define USE_GLOBAL_ON_RESPONSE_CALLBACK 1 // Set to 0 to use local callback specified directly for the endpoint.
36+
3537/* Zigbee temperature + humidity sensor configuration */
3638#define TEMP_SENSOR_ENDPOINT_NUMBER 10
3739
3840#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
3941#define TIME_TO_SLEEP 55 /* Sleep for 55s will + 5s delay for establishing connection => data reported every 1 minute */
42+ #define REPORT_TIMEOUT 1000 /* Timeout for response from coordinator in ms */
4043
4144uint8_t button = BOOT_PIN;
4245
4346ZigbeeTempSensor zbTempSensor = ZigbeeTempSensor(TEMP_SENSOR_ENDPOINT_NUMBER);
4447
48+ uint8_t dataToSend = 2 ; // Temperature and humidity values are reported in same endpoint, so 2 values are reported
49+ bool resend = false ;
50+
51+ /* *********************** Callbacks *****************************/
52+ #if USE_GLOBAL_ON_RESPONSE_CALLBACK
53+ void onGlobalResponse (zb_cmd_type_t command, esp_zb_zcl_status_t status, uint8_t endpoint, uint16_t cluster) {
54+ Serial.printf (" Global response command: %d, status: %s, endpoint: %d, cluster: 0x%04x\r\n " , command, esp_zb_zcl_status_to_name (status), endpoint, cluster);
55+ if ((command == ZB_CMD_REPORT_ATTRIBUTE) && (endpoint == TEMP_SENSOR_ENDPOINT_NUMBER)) {
56+ switch (status) {
57+ case ESP_ZB_ZCL_STATUS_SUCCESS: dataToSend--; break ;
58+ case ESP_ZB_ZCL_STATUS_FAIL: resend = true ; break ;
59+ default : break ; // add more statuses like ESP_ZB_ZCL_STATUS_INVALID_VALUE, ESP_ZB_ZCL_STATUS_TIMEOUT etc.
60+ }
61+ }
62+ }
63+ #else
64+ void onResponse (zb_cmd_type_t command, esp_zb_zcl_status_t status) {
65+ Serial.printf (" Response command: %d, status: %s\r\n " , command, esp_zb_zcl_status_to_name (status));
66+ if (command == ZB_CMD_REPORT_ATTRIBUTE) {
67+ switch (status) {
68+ case ESP_ZB_ZCL_STATUS_SUCCESS: dataToSend--; break ;
69+ case ESP_ZB_ZCL_STATUS_FAIL: resend = true ; break ;
70+ default : break ; // add more statuses like ESP_ZB_ZCL_STATUS_INVALID_VALUE, ESP_ZB_ZCL_STATUS_TIMEOUT etc.
71+ }
72+ }
73+ }
74+ #endif
75+
4576/* *********************** Temp sensor *****************************/
46- void meausureAndSleep () {
77+ static void meausureAndSleep (void *arg ) {
4778 // Measure temperature sensor value
4879 float temperature = temperatureRead ();
4980
@@ -55,13 +86,35 @@ void meausureAndSleep() {
5586 zbTempSensor.setHumidity (humidity);
5687
5788 // Report temperature and humidity values
58- zbTempSensor.report ();
89+ zbTempSensor.report (); // reports temperature and humidity values (if humidity sensor is not added, only temperature is reported)
5990 Serial.printf (" Reported temperature: %.2f°C, Humidity: %.2f%%\r\n " , temperature, humidity);
6091
61- // Add small delay to allow the data to be sent before going to sleep
62- delay (100 );
92+ unsigned long startTime = millis ();
93+ const unsigned long timeout = REPORT_TIMEOUT;
94+
95+ Serial.printf (" Waiting for data report to be confirmed \r\n " );
96+ // Wait until data was successfully sent
97+ int tries = 0 ;
98+ const int maxTries = 3 ;
99+ while (dataToSend != 0 && tries < maxTries) {
100+ if (resend) {
101+ Serial.println (" Resending data on failure!" );
102+ resend = false ;
103+ dataToSend = 2 ;
104+ zbTempSensor.report (); // report again
105+ }
106+ if (millis () - startTime >= timeout) {
107+ Serial.println (" \n Report timeout! Report Again" );
108+ dataToSend = 2 ;
109+ zbTempSensor.report (); // report again
110+ startTime = millis ();
111+ tries++;
112+ }
113+ Serial.printf (" ." );
114+ delay (50 ); // 50ms delay to avoid busy-waiting
115+ }
63116
64- // Put device to deep sleep
117+ // Put device to deep sleep after data was sent successfully or timeout
65118 Serial.println (" Going to sleep now" );
66119 esp_deep_sleep_start ();
67120}
@@ -92,6 +145,16 @@ void setup() {
92145 // Add humidity cluster to the temperature sensor device with min, max and tolerance values
93146 zbTempSensor.addHumiditySensor (0 , 100 , 1 );
94147
148+ // Set callback for default response to handle status of reported data, there are 2 options.
149+
150+ #if USE_GLOBAL_ON_RESPONSE_CALLBACK
151+ // Global callback for all endpoints with more params to determine the endpoint and cluster in the callback function.
152+ Zigbee.onGlobalDefaultResponse (onGlobalResponse);
153+ #else
154+ // Callback specified for endpoint
155+ zbTempSensor.onDefaultResponse (onResponse);
156+ #endif
157+
95158 // Add endpoint to Zigbee Core
96159 Zigbee.addEndpoint (&zbTempSensor);
97160
@@ -117,8 +180,8 @@ void setup() {
117180 Serial.println ();
118181 Serial.println (" Successfully connected to Zigbee network" );
119182
120- // Delay approx 1s (may be adjusted) to allow establishing proper connection with coordinator, needed for sleepy devices
121- delay ( 1000 );
183+ // Start Temperature sensor reading task
184+ xTaskCreate (meausureAndSleep, " temp_sensor_update " , 2048 , NULL , 10 , NULL );
122185}
123186
124187void loop () {
@@ -141,7 +204,5 @@ void loop() {
141204 }
142205 }
143206 }
144-
145- // Call the function to measure temperature and put the device to sleep
146- meausureAndSleep ();
207+ delay (100 );
147208}
0 commit comments