Skip to content

Commit 160e286

Browse files
committed
fix(zigbee): Fix memory leak, print esp_zb_zcl_status_t error, remove analogValue from analog EP
1 parent 80eba94 commit 160e286

18 files changed

+160
-122
lines changed

libraries/Zigbee/src/ZigbeeCore.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,23 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
368368
case ESP_ZB_ZDO_SIGNAL_LEAVE: // End Device + Router
369369
// Device was removed from the network, factory reset the device
370370
if ((zigbee_role_t)Zigbee.getRole() != ZIGBEE_COORDINATOR) {
371-
Zigbee.factoryReset();
371+
Zigbee.factoryReset(true);
372372
}
373373
break;
374374
default: log_v("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break;
375375
}
376376
}
377377

378-
void ZigbeeCore::factoryReset() {
379-
log_v("Factory resetting Zigbee stack, device will reboot");
380-
esp_zb_factory_reset();
378+
void ZigbeeCore::factoryReset(bool restart) {
379+
if (restart) {
380+
log_v("Factory resetting Zigbee stack, device will reboot");
381+
esp_zb_factory_reset();
382+
}
383+
else {
384+
log_v("Factory resetting Zigbee NVRAM to factory default");
385+
log_w("The device will not reboot, to take effect please reboot the device manually");
386+
esp_zb_zcl_reset_nvram_to_factory_default();
387+
}
381388
}
382389

383390
void ZigbeeCore::scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor) {

libraries/Zigbee/src/ZigbeeCore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class ZigbeeCore {
164164
zigbee_scan_result_t *getScanResult();
165165
void scanDelete();
166166

167-
void factoryReset();
167+
void factoryReset(bool restart = true);
168168

169169
// Friend function declaration to allow access to private members
170170
friend void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct);

libraries/Zigbee/src/ZigbeeEP.cpp

Lines changed: 114 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,41 +34,36 @@ void ZigbeeEP::setVersion(uint8_t version) {
3434

3535
bool ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
3636
// Convert manufacturer to ZCL string
37-
size_t length = strlen(name);
38-
if (length > 32) {
39-
log_e("Manufacturer name is too long");
37+
size_t name_length = strlen(name);
38+
size_t model_length = strlen(model);
39+
if (name_length > 32 || model_length > 32) {
40+
log_e("Manufacturer or model name is too long");
4041
return false;
4142
}
4243
// Allocate a new array of size length + 2 (1 for the length, 1 for null terminator)
43-
char *zb_name = new char[length + 2];
44+
char *zb_name = new char[name_length + 2];
45+
char *zb_model = new char[model_length + 2];
4446
// Store the length as the first element
45-
zb_name[0] = static_cast<char>(length); // Cast size_t to char
47+
zb_name[0] = static_cast<char>(name_length); // Cast size_t to char
48+
zb_model[0] = static_cast<char>(model_length);
4649
// Use memcpy to copy the characters to the result array
47-
memcpy(zb_name + 1, name, length);
50+
memcpy(zb_name + 1, name, name_length);
51+
memcpy(zb_model + 1, model, model_length);
4852
// Null-terminate the array
49-
zb_name[length + 1] = '\0';
50-
51-
// Convert model to ZCL string
52-
length = strlen(model);
53-
if (length > 32) {
54-
log_e("Model name is too long");
55-
delete[] zb_name;
56-
return false;
57-
}
58-
char *zb_model = new char[length + 2];
59-
zb_model[0] = static_cast<char>(length);
60-
memcpy(zb_model + 1, model, length);
61-
zb_model[length + 1] = '\0';
53+
zb_name[name_length + 1] = '\0';
54+
zb_model[model_length + 1] = '\0';
6255

6356
// Get the basic cluster and update the manufacturer and model attributes
6457
esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster(_cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
6558
esp_err_t ret_manufacturer = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name);
6659
esp_err_t ret_model = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model);
6760
if(ret_manufacturer != ESP_OK || ret_model != ESP_OK) {
6861
log_e("Failed to set manufacturer (0x%x) or model (0x%x)", ret_manufacturer, ret_model);
69-
return false;
7062
}
71-
return true;
63+
64+
delete[] zb_name;
65+
delete[] zb_model;
66+
return ret_manufacturer == ESP_OK && ret_model == ESP_OK;
7267
}
7368

7469
void ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_percentage) {
@@ -103,7 +98,7 @@ bool ZigbeeEP::setBatteryPercentage(uint8_t percentage) {
10398
);
10499
esp_zb_lock_release();
105100
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
106-
log_e("Failed to set battery percentage: 0x%x", ret);
101+
log_e("Failed to set battery percentage: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
107102
return false;
108103
}
109104
log_v("Battery percentage updated");
@@ -153,7 +148,9 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i
153148
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
154149
read_req.attr_field = attributes;
155150

156-
// clear read manufacturer
151+
if (_read_manufacturer != nullptr) {
152+
free(_read_manufacturer);
153+
}
157154
_read_manufacturer = nullptr;
158155

159156
esp_zb_lock_acquire(portMAX_DELAY);
@@ -189,7 +186,9 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_add
189186
read_req.attr_number = ZB_ARRAY_LENTH(attributes);
190187
read_req.attr_field = attributes;
191188

192-
// clear read model
189+
if (_read_model != nullptr) {
190+
free(_read_model);
191+
}
193192
_read_model = nullptr;
194193

195194
esp_zb_lock_acquire(portMAX_DELAY);
@@ -287,7 +286,7 @@ bool ZigbeeEP::setTime(tm time) {
287286
ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ID, &utc_time, false);
288287
esp_zb_lock_release();
289288
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
290-
log_e("Failed to set time: 0x%x", ret);
289+
log_e("Failed to set time: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
291290
return false;
292291
}
293292
return true;
@@ -300,7 +299,7 @@ bool ZigbeeEP::setTimezone(int32_t gmt_offset) {
300299
ret = esp_zb_zcl_set_attribute_val(_endpoint, ESP_ZB_ZCL_CLUSTER_ID_TIME, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID, &gmt_offset, false);
301300
esp_zb_lock_release();
302301
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
303-
log_e("Failed to set timezone: 0x%x", ret);
302+
log_e("Failed to set timezone: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
304303
return false;
305304
}
306305
return true;
@@ -422,7 +421,7 @@ void ZigbeeEP::zbReadTimeCluster(const esp_zb_zcl_attribute_t *attribute) {
422421
// uint8_t max_data_size; /*!< The maximum size of OTA data */
423422
// } esp_zb_zcl_ota_upgrade_client_variable_t;
424423

425-
void ZigbeeEP::addOTAClient(
424+
bool ZigbeeEP::addOTAClient(
426425
uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer, uint16_t image_type, uint8_t max_data_size
427426
) {
428427

@@ -442,11 +441,23 @@ void ZigbeeEP::addOTAClient(
442441
uint16_t ota_upgrade_server_addr = 0xffff;
443442
uint8_t ota_upgrade_server_ep = 0xff;
444443

445-
esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config);
446-
esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr);
447-
esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep);
448-
444+
esp_err_t ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config);
445+
if (ret != ESP_OK) {
446+
log_e("Failed to add OTA client data: 0x%x: %s", ret, esp_err_to_name(ret));
447+
return false;
448+
}
449+
ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr);
450+
if (ret != ESP_OK) {
451+
log_e("Failed to add OTA server address: 0x%x: %s", ret, esp_err_to_name(ret));
452+
return false;
453+
}
454+
ret = esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep);
455+
if (ret != ESP_OK) {
456+
log_e("Failed to add OTA server endpoint: 0x%x: %s", ret, esp_err_to_name(ret));
457+
return false;
458+
}
449459
esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
460+
return true;
450461
}
451462

452463
static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) {
@@ -477,4 +488,76 @@ void ZigbeeEP::requestOTAUpdate() {
477488
esp_zb_lock_release();
478489
}
479490

491+
const char* ZigbeeEP::esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status) {
492+
switch (status) {
493+
case ESP_ZB_ZCL_STATUS_SUCCESS:
494+
return "Success";
495+
case ESP_ZB_ZCL_STATUS_FAIL:
496+
return "Fail";
497+
case ESP_ZB_ZCL_STATUS_NOT_AUTHORIZED:
498+
return "Not authorized";
499+
case ESP_ZB_ZCL_STATUS_MALFORMED_CMD:
500+
return "Malformed command";
501+
case ESP_ZB_ZCL_STATUS_UNSUP_CLUST_CMD:
502+
return "Unsupported cluster command";
503+
case ESP_ZB_ZCL_STATUS_UNSUP_GEN_CMD:
504+
return "Unsupported general command";
505+
case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_CLUST_CMD:
506+
return "Unsupported manufacturer cluster command";
507+
case ESP_ZB_ZCL_STATUS_UNSUP_MANUF_GEN_CMD:
508+
return "Unsupported manufacturer general command";
509+
case ESP_ZB_ZCL_STATUS_INVALID_FIELD:
510+
return "Invalid field";
511+
case ESP_ZB_ZCL_STATUS_UNSUP_ATTRIB:
512+
return "Unsupported attribute";
513+
case ESP_ZB_ZCL_STATUS_INVALID_VALUE:
514+
return "Invalid value";
515+
case ESP_ZB_ZCL_STATUS_READ_ONLY:
516+
return "Read only";
517+
case ESP_ZB_ZCL_STATUS_INSUFF_SPACE:
518+
return "Insufficient space";
519+
case ESP_ZB_ZCL_STATUS_DUPE_EXISTS:
520+
return "Duplicate exists";
521+
case ESP_ZB_ZCL_STATUS_NOT_FOUND:
522+
return "Not found";
523+
case ESP_ZB_ZCL_STATUS_UNREPORTABLE_ATTRIB:
524+
return "Unreportable attribute";
525+
case ESP_ZB_ZCL_STATUS_INVALID_TYPE:
526+
return "Invalid type";
527+
case ESP_ZB_ZCL_STATUS_WRITE_ONLY:
528+
return "Write only";
529+
case ESP_ZB_ZCL_STATUS_INCONSISTENT:
530+
return "Inconsistent";
531+
case ESP_ZB_ZCL_STATUS_ACTION_DENIED:
532+
return "Action denied";
533+
case ESP_ZB_ZCL_STATUS_TIMEOUT:
534+
return "Timeout";
535+
case ESP_ZB_ZCL_STATUS_ABORT:
536+
return "Abort";
537+
case ESP_ZB_ZCL_STATUS_INVALID_IMAGE:
538+
return "Invalid OTA upgrade image";
539+
case ESP_ZB_ZCL_STATUS_WAIT_FOR_DATA:
540+
return "Server does not have data block available yet";
541+
case ESP_ZB_ZCL_STATUS_NO_IMAGE_AVAILABLE:
542+
return "No image available";
543+
case ESP_ZB_ZCL_STATUS_REQUIRE_MORE_IMAGE:
544+
return "Require more image";
545+
case ESP_ZB_ZCL_STATUS_NOTIFICATION_PENDING:
546+
return "Notification pending";
547+
case ESP_ZB_ZCL_STATUS_HW_FAIL:
548+
return "Hardware failure";
549+
case ESP_ZB_ZCL_STATUS_SW_FAIL:
550+
return "Software failure";
551+
case ESP_ZB_ZCL_STATUS_CALIB_ERR:
552+
return "Calibration error";
553+
case ESP_ZB_ZCL_STATUS_UNSUP_CLUST:
554+
return "Cluster is not found on the target endpoint";
555+
case ESP_ZB_ZCL_STATUS_LIMIT_REACHED:
556+
return "Limit reached";
557+
default:
558+
return "Unknown status";
559+
}
560+
}
561+
562+
480563
#endif // CONFIG_ZB_ENABLED

libraries/Zigbee/src/ZigbeeEP.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ class ZigbeeEP {
104104
* @param manufacturer The manufacturer code (default: 0x1001).
105105
* @param image_type The image type code (default: 0x1011).
106106
* @param max_data_size The maximum data size for OTA transfer (default and recommended: 223).
107+
* @return true if the OTA client was added successfully, false otherwise.
107108
*/
108-
void addOTAClient(
109+
bool addOTAClient(
109110
uint32_t file_version, uint32_t downloaded_file_ver, uint16_t hw_version, uint16_t manufacturer = 0x1001, uint16_t image_type = 0x1011,
110111
uint8_t max_data_size = 223
111112
);
@@ -114,10 +115,10 @@ class ZigbeeEP {
114115
*/
115116
void requestOTAUpdate();
116117

117-
// findEndpoind may be implemented by EPs to find and bind devices
118+
// findEndpoint may be implemented by EPs to find and bind devices
118119
virtual void findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) {};
119120

120-
//list of all handlers function calls, to be override by EPs implementation
121+
// list of all handlers function calls, to be override by EPs implementation
121122
virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {};
122123
virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {};
123124
virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
@@ -144,6 +145,9 @@ class ZigbeeEP {
144145
int32_t _read_timezone;
145146

146147
protected:
148+
// Convert ZCL status to name
149+
const char *esp_zb_zcl_status_to_name(esp_zb_zcl_status_t status);
150+
147151
uint8_t _endpoint;
148152
esp_zb_ha_standard_devices_t _device_id;
149153
esp_zb_endpoint_config_t _ep_config;

libraries/Zigbee/src/ep/ZigbeeAnalog.cpp

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,17 @@
11
#include "ZigbeeAnalog.h"
22
#if CONFIG_ZB_ENABLED
33

4-
esp_zb_cluster_list_t *zigbee_analog_clusters_create(zigbee_analog_cfg_t *analog_sensor) {
5-
esp_zb_basic_cluster_cfg_t *basic_cfg = analog_sensor ? &(analog_sensor->basic_cfg) : NULL;
6-
esp_zb_identify_cluster_cfg_t *identify_cfg = analog_sensor ? &(analog_sensor->identify_cfg) : NULL;
7-
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
8-
esp_zb_cluster_list_add_basic_cluster(cluster_list, esp_zb_basic_cluster_create(basic_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
9-
esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(identify_cfg), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
10-
return cluster_list;
11-
}
12-
134
ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) {
145
_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID;
156

16-
//Create custom analog sensor configuration
17-
zigbee_analog_cfg_t analog_cfg = ZIGBEE_DEFAULT_ANALOG_CONFIG();
18-
_cluster_list = zigbee_analog_clusters_create(&analog_cfg);
7+
//Create basic analog sensor clusters without configuration
8+
_cluster_list = esp_zb_zcl_cluster_list_create();
9+
esp_zb_cluster_list_add_basic_cluster(_cluster_list, esp_zb_basic_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
10+
esp_zb_cluster_list_add_identify_cluster(_cluster_list, esp_zb_identify_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
1911

2012
_ep_config = {.endpoint = _endpoint, .app_profile_id = ESP_ZB_AF_HA_PROFILE_ID, .app_device_id = ESP_ZB_HA_SIMPLE_SENSOR_DEVICE_ID, .app_device_version = 0};
2113
}
2214

23-
bool ZigbeeAnalog::addAnalogValue() {
24-
esp_err_t ret = esp_zb_cluster_list_add_analog_value_cluster(_cluster_list, esp_zb_analog_value_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
25-
if (ret != ESP_OK) {
26-
log_e("Failed to add Analog Value cluster: 0x%x: %s", ret, esp_err_to_name(ret));
27-
return false;
28-
}
29-
_analog_clusters |= ANALOG_VALUE;
30-
return true;
31-
}
32-
3315
bool ZigbeeAnalog::addAnalogInput() {
3416
esp_err_t ret = esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
3517
if (ret != ESP_OK) {
@@ -72,25 +54,6 @@ void ZigbeeAnalog::analogOutputChanged(float analog_output) {
7254
}
7355
}
7456

75-
bool ZigbeeAnalog::setAnalogValue(float analog) {
76-
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
77-
if (!(_analog_clusters & ANALOG_VALUE)) {
78-
log_e("Analog Value cluster not added");
79-
return false;
80-
}
81-
log_d("Setting analog value to %.1f", analog);
82-
esp_zb_lock_acquire(portMAX_DELAY);
83-
ret = esp_zb_zcl_set_attribute_val(
84-
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_VALUE, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ANALOG_VALUE_PRESENT_VALUE_ID, &analog, false
85-
);
86-
esp_zb_lock_release();
87-
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
88-
log_e("Failed to set analog value: 0x%x", ret);
89-
return false;
90-
}
91-
return true;
92-
}
93-
9457
bool ZigbeeAnalog::setAnalogInput(float analog) {
9558
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
9659
if (!(_analog_clusters & ANALOG_INPUT)) {
@@ -104,7 +67,7 @@ bool ZigbeeAnalog::setAnalogInput(float analog) {
10467
);
10568
esp_zb_lock_release();
10669
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
107-
log_e("Failed to set analog input: 0x%x", ret);
70+
log_e("Failed to set analog input: 0x%x: %s", ret, esp_zb_zcl_status_to_name(ret));
10871
return false;
10972
}
11073
return true;

0 commit comments

Comments
 (0)