Skip to content

Commit cae66e6

Browse files
feat(zigbee): Add endpoint identification in read handlers + command structures fix (#11425)
* feat(zigbee): Add endpoint identification in read handlers * fix(zigbee): initialize Zigbee command structures with zeros * fix(zigbee): Spelling correction * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 375f2c0 commit cae66e6

File tree

9 files changed

+390
-89
lines changed

9 files changed

+390
-89
lines changed

libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
#include "Zigbee.h"
3535

3636
/* Zigbee thermostat configuration */
37-
#define THERMOSTAT_ENDPOINT_NUMBER 5
37+
#define THERMOSTAT_ENDPOINT_NUMBER 1
38+
#define USE_RECEIVE_TEMP_WITH_SOURCE 1
3839
uint8_t button = BOOT_PIN;
3940

4041
ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER);
@@ -48,13 +49,28 @@ float sensor_tolerance;
4849
struct tm timeinfo = {}; // Time structure for Time cluster
4950

5051
/****************** Temperature sensor handling *******************/
51-
void recieveSensorTemp(float temperature) {
52+
#if USE_RECEIVE_TEMP_WITH_SOURCE == 0
53+
void receiveSensorTemp(float temperature) {
5254
Serial.printf("Temperature sensor value: %.2f°C\n", temperature);
5355
sensor_temp = temperature;
5456
}
57+
#else
58+
void receiveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {
59+
if (src_address.addr_type == ESP_ZB_ZCL_ADDR_TYPE_SHORT) {
60+
Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address 0x%04x\n", temperature, src_endpoint, src_address.u.short_addr);
61+
} else {
62+
Serial.printf(
63+
"Temperature sensor value: %.2f°C from endpoint %d, address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", temperature, src_endpoint,
64+
src_address.u.ieee_addr[7], src_address.u.ieee_addr[6], src_address.u.ieee_addr[5], src_address.u.ieee_addr[4], src_address.u.ieee_addr[3],
65+
src_address.u.ieee_addr[2], src_address.u.ieee_addr[1], src_address.u.ieee_addr[0]
66+
);
67+
}
68+
sensor_temp = temperature;
69+
}
70+
#endif
5571

56-
void recieveSensorConfig(float min_temp, float max_temp, float tolerance) {
57-
Serial.printf("Temperature sensor settings: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
72+
void receiveSensorConfig(float min_temp, float max_temp, float tolerance) {
73+
Serial.printf("Temperature sensor config: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance);
5874
sensor_min_temp = min_temp;
5975
sensor_max_temp = max_temp;
6076
sensor_tolerance = tolerance;
@@ -66,9 +82,15 @@ void setup() {
6682
// Init button switch
6783
pinMode(button, INPUT_PULLUP);
6884

69-
// Set callback functions for temperature and configuration receive
70-
zbThermostat.onTempRecieve(recieveSensorTemp);
71-
zbThermostat.onConfigRecieve(recieveSensorConfig);
85+
// Set callback function for receiving temperature from sensor - Use only one option
86+
#if USE_RECEIVE_TEMP_WITH_SOURCE == 0
87+
zbThermostat.onTempReceive(receiveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature
88+
#else
89+
zbThermostat.onTempReceiveWithSource(receiveSensorTempWithSource);
90+
#endif
91+
92+
// Set callback function for receiving sensor configuration
93+
zbThermostat.onConfigReceive(receiveSensorConfig);
7294

7395
//Optional: set Zigbee device name and model
7496
zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat");
@@ -107,19 +129,30 @@ void setup() {
107129

108130
Serial.println();
109131

110-
// Get temperature sensor configuration
111-
zbThermostat.getSensorSettings();
132+
// Get temperature sensor configuration for all bound sensors by endpoint number and address
133+
std::list<zb_device_params_t *> boundSensors = zbThermostat.getBoundDevices();
134+
for (const auto &device : boundSensors) {
135+
Serial.println("--------------------------------");
136+
if (device->short_addr == 0x0000 || device->short_addr == 0xFFFF) { //End devices never have 0x0000 short address or 0xFFFF group address
137+
Serial.printf(
138+
"Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6],
139+
device->ieee_addr[5], device->ieee_addr[4], device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0]
140+
);
141+
zbThermostat.getSensorSettings(device->endpoint, device->ieee_addr);
142+
} else {
143+
Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr);
144+
zbThermostat.getSensorSettings(device->endpoint, device->short_addr);
145+
}
146+
}
112147
}
113148

114149
void loop() {
115150
// Handle button switch in loop()
116151
if (digitalRead(button) == LOW) { // Push button pressed
117-
118152
// Key debounce handling
119153
while (digitalRead(button) == LOW) {
120154
delay(50);
121155
}
122-
123156
// Set reporting interval for temperature sensor
124157
zbThermostat.setTemperatureReporting(0, 10, 2);
125158
}
@@ -130,5 +163,6 @@ void loop() {
130163
last_print = millis();
131164
int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100);
132165
Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent);
166+
zbThermostat.printBoundDevices(Serial);
133167
}
134168
}

libraries/Zigbee/keywords.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ setLightColor KEYWORD2
107107
# ZigbeeThermostat
108108
onTempRecieve KEYWORD2
109109
onConfigRecieve KEYWORD2
110+
onTempReceiveWithSource KEYWORD2
110111
getTemperature KEYWORD2
111112
getSensorSettings KEYWORD2
112113
setTemperatureReporting KEYWORD2
@@ -191,4 +192,4 @@ ZIGBEE_DEFAULT_COORDINATOR_CONFIG LITERAL1
191192
ZIGBEE_DEFAULT_RADIO_CONFIG LITERAL1
192193
ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG LITERAL1
193194
ZIGBEE_DEFAULT_HOST_CONFIG LITERAL1
194-
ZB_ARRAY_LENTH LITERAL1
195+
ZB_ARRAY_LENGHT LITERAL1

libraries/Zigbee/src/ZigbeeEP.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ bool ZigbeeEP::setBatteryVoltage(uint8_t voltage) {
145145

146146
bool ZigbeeEP::reportBatteryPercentage() {
147147
/* Send report attributes command */
148-
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
148+
esp_zb_zcl_report_attr_cmd_t report_attr_cmd = {0};
149149
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
150150
report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID;
151151
report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI;
@@ -166,7 +166,7 @@ bool ZigbeeEP::reportBatteryPercentage() {
166166

167167
char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
168168
/* Read peer Manufacture Name & Model Identifier */
169-
esp_zb_zcl_read_attr_cmd_t read_req;
169+
esp_zb_zcl_read_attr_cmd_t read_req = {0};
170170

171171
if (short_addr != 0) {
172172
read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -183,7 +183,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
183183
uint16_t attributes[] = {
184184
ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
185185
};
186-
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
186+
read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
187187
read_req.attr_field = attributes;
188188

189189
if (_read_manufacturer != NULL) {
@@ -204,7 +204,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
204204

205205
char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
206206
/* Read peer Manufacture Name & Model Identifier */
207-
esp_zb_zcl_read_attr_cmd_t read_req;
207+
esp_zb_zcl_read_attr_cmd_t read_req = {0};
208208

209209
if (short_addr != 0) {
210210
read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -221,7 +221,7 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_add
221221
uint16_t attributes[] = {
222222
ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
223223
};
224-
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
224+
read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
225225
read_req.attr_field = attributes;
226226

227227
if (_read_model != NULL) {
@@ -375,7 +375,7 @@ bool ZigbeeEP::setTimezone(int32_t gmt_offset) {
375375

376376
tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
377377
/* Read peer time */
378-
esp_zb_zcl_read_attr_cmd_t read_req;
378+
esp_zb_zcl_read_attr_cmd_t read_req = {0};
379379

380380
if (short_addr >= 0) {
381381
read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -386,7 +386,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie
386386
}
387387

388388
uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ID};
389-
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
389+
read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
390390
read_req.attr_field = attributes;
391391

392392
read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
@@ -427,7 +427,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie
427427

428428
int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
429429
/* Read peer timezone */
430-
esp_zb_zcl_read_attr_cmd_t read_req;
430+
esp_zb_zcl_read_attr_cmd_t read_req = {0};
431431

432432
if (short_addr >= 0) {
433433
read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
@@ -438,7 +438,7 @@ int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_
438438
}
439439

440440
uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID};
441-
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
441+
read_req.attr_number = ZB_ARRAY_LENGHT(attributes);
442442
read_req.attr_field = attributes;
443443

444444
read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME;
@@ -543,7 +543,7 @@ static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t
543543
}
544544

545545
void ZigbeeEP::requestOTAUpdate() {
546-
esp_zb_zdo_match_desc_req_param_t req;
546+
esp_zb_zdo_match_desc_req_param_t req = {0};
547547
uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_OTA_UPGRADE};
548548

549549
/* Match the OTA server of coordinator */

libraries/Zigbee/src/ZigbeeEP.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#define ZB_CMD_TIMEOUT 10000 // 10 seconds
1313
#define OTA_UPGRADE_QUERY_INTERVAL (1 * 60) // 1 hour = 60 minutes
1414

15-
#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0]))
15+
#define ZB_ARRAY_LENGHT(arr) (sizeof(arr) / sizeof(arr[0]))
1616

1717
#define RGB_TO_XYZ(r, g, b, X, Y, Z) \
1818
{ \
@@ -131,7 +131,7 @@ class ZigbeeEP {
131131

132132
// list of all handlers function calls, to be override by EPs implementation
133133
virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {};
134-
virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {};
134+
virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {};
135135
virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
136136
virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message);
137137
virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {};

libraries/Zigbee/src/ZigbeeHandlers.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes
108108
// List through all Zigbee EPs and call the callback function, with the message
109109
for (std::list<ZigbeeEP *>::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) {
110110
if (message->dst_endpoint == (*it)->getEndpoint()) {
111-
(*it)->zbAttributeRead(message->cluster, &message->attribute); //method zbAttributeRead must be implemented in specific EP class
111+
(*it)->zbAttributeRead(
112+
message->cluster, &message->attribute, message->src_endpoint, message->src_address
113+
); //method zbAttributeRead must be implemented in specific EP class
112114
}
113115
}
114116
return ESP_OK;
@@ -142,7 +144,9 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re
142144
} else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) {
143145
(*it)->zbReadTimeCluster(&variable->attribute); //method zbReadTimeCluster implemented in the common EP class
144146
} else {
145-
(*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class
147+
(*it)->zbAttributeRead(
148+
message->info.cluster, &variable->attribute, message->info.src_endpoint, message->info.src_address
149+
); //method zbAttributeRead must be implemented in specific EP class
146150
}
147151
}
148152
variable = variable->next;

0 commit comments

Comments
 (0)