@@ -19,6 +19,9 @@ ZigbeeEP::ZigbeeEP(uint8_t endpoint) {
1919 _ep_config.endpoint = 0 ;
2020 _cluster_list = nullptr ;
2121 _on_identify = nullptr ;
22+ _read_model = nullptr ; // Explicitly initialize here
23+ _read_manufacturer = nullptr ; // Explicitly initialize here
24+
2225 _time_status = 0 ;
2326 if (!lock) {
2427 lock = xSemaphoreCreateBinary ();
@@ -33,43 +36,51 @@ void ZigbeeEP::setVersion(uint8_t version) {
3336}
3437
3538bool ZigbeeEP::setManufacturerAndModel (const char *name, const char *model) {
36- constexpr size_t ZB_MAX_NAME_LENGTH = 32 ;
39+ constexpr size_t ZB_MAX_NAME_LENGTH = 32 ;
40+
41+ // Validate input lengths
42+ size_t name_length = strlen (name);
43+ size_t model_length = strlen (model);
44+ if (name_length > ZB_MAX_NAME_LENGTH || model_length > ZB_MAX_NAME_LENGTH) {
45+ log_e (" Manufacturer or model name is too long" );
46+ return false ;
47+ }
3748
38- // Convert manufacturer to ZCL string
39- size_t name_length = strlen (name);
40- size_t model_length = strlen (model );
41- if (name_length > ZB_MAX_NAME_LENGTH || model_length > ZB_MAX_NAME_LENGTH) {
42- log_e ( " Manufacturer or model name is too long " );
43- return false ;
44- }
45- // Allocate an array of size length + 2 (1 for the length, 1 for null terminator)
46- char zb_name[ZB_MAX_NAME_LENGTH + 2 ];
47- char zb_model[ZB_MAX_NAME_LENGTH + 2 ];
48- // Store the length as the first element
49- zb_name[ 0 ] = static_cast < char >(name_length); // Cast size_t to char
50- zb_model[0 ] = static_cast < char >(model_length) ;
51- // Use memcpy to copy the characters to the result array
52- memcpy (zb_name + 1 , name, name_length);
53- memcpy (zb_model + 1 , model, model_length);
54- // Null-terminate the array
55- zb_name[name_length + 1 ] = ' \0 ' ;
56- zb_model[model_length + 1 ] = ' \0 ' ;
57-
58- // Get the basic cluster and update the manufacturer and model attributes
59- 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);
60- if (basic_cluster == nullptr ) {
61- log_e ( " Failed to get basic cluster " );
62- return false ;
63- }
64- esp_err_t ret_name = esp_zb_basic_cluster_add_attr (basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ( void *)zb_name);
65- if (ret_name != ESP_OK) {
66- log_e ( " Failed to set manufacturer: 0x%x: %s " , ret_name, esp_err_to_name (ret_name));
67- }
68- esp_err_t ret_model = esp_zb_basic_cluster_add_attr (basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, ( void *)zb_model);
69- if (ret_model != ESP_OK) {
70- log_e ( " Failed to set model: 0x%x: %s " , ret_model, esp_err_to_name (ret_model));
71- }
72- return ret_name == ESP_OK && ret_model == ESP_OK;
49+ // Use std::vector<char> for dynamic memory management - free() is for free when out of scope
50+ std::vector< char > zb_name (name_length + 2 ); // +2 for length byte and null terminator
51+ std::vector< char > zb_model (model_length + 2 );
52+
53+ // Convert manufacturer to ZCL string
54+ zb_name[ 0 ] = static_cast < char >(name_length); // Store the length as the first element
55+ memcpy (zb_name. data () + 1 , name, name_length);
56+ zb_name[name_length + 1 ] = ' \0 ' ; // Null-terminate the array
57+
58+ // Convert model to ZCL string
59+ zb_model[ 0 ] = static_cast < char >(model_length);
60+ memcpy (zb_model. data () + 1 , model, model_length);
61+ zb_model[model_length + 1 ] = ' \0 ' ;
62+
63+ // Get the basic cluster and update the manufacturer and model attributes
64+ esp_zb_attribute_list_t *basic_cluster = esp_zb_cluster_list_get_cluster (
65+ _cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
66+ if (!basic_cluster) {
67+ log_e ( " Failed to get basic cluster " ) ;
68+ return false ;
69+ }
70+
71+ esp_err_t ret_name = esp_zb_basic_cluster_add_attr (
72+ basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, zb_name. data () );
73+ if (ret_name != ESP_OK) {
74+ log_e ( " Failed to set manufacturer: 0x%x: %s " , ret_name, esp_err_to_name (ret_name));
75+ }
76+
77+ esp_err_t ret_model = esp_zb_basic_cluster_add_attr (
78+ basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, zb_model. data ());
79+ if (ret_model != ESP_OK) {
80+ log_e ( " Failed to set model: 0x%x: %s " , ret_model, esp_err_to_name (ret_model));
81+ }
82+
83+ return ret_name == ESP_OK && ret_model == ESP_OK;
7384}
7485
7586bool ZigbeeEP::setPowerSource (zb_power_source_t power_source, uint8_t battery_percentage) {
@@ -146,79 +157,77 @@ bool ZigbeeEP::reportBatteryPercentage() {
146157}
147158
148159char *ZigbeeEP::readManufacturer (uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
149- /* Read peer Manufacture Name & Model Identifier */
150- esp_zb_zcl_read_attr_cmd_t read_req;
151-
152- if (short_addr != 0 ) {
153- read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
154- read_req.zcl_basic_cmd .dst_addr_u .addr_short = short_addr;
155- } else {
156- read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
157- memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
158- }
160+ /* Read peer Manufacturer Name */
161+ esp_zb_zcl_read_attr_cmd_t read_req;
162+
163+ if (short_addr != 0 ) {
164+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
165+ read_req.zcl_basic_cmd .dst_addr_u .addr_short = short_addr;
166+ } else {
167+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
168+ memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
169+ }
159170
160- read_req.zcl_basic_cmd .src_endpoint = _endpoint;
161- read_req.zcl_basic_cmd .dst_endpoint = endpoint;
162- read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC;
171+ read_req.zcl_basic_cmd .src_endpoint = _endpoint;
172+ read_req.zcl_basic_cmd .dst_endpoint = endpoint;
173+ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC;
163174
164- uint16_t attributes[] = {
165- ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
166- };
167- read_req.attr_number = ZB_ARRAY_LENTH (attributes);
168- read_req.attr_field = attributes;
175+ uint16_t attributes[] = {
176+ ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
177+ };
178+ read_req.attr_number = ZB_ARRAY_LENTH (attributes);
179+ read_req.attr_field = attributes;
169180
170- if (_read_manufacturer != nullptr ) {
181+ // Free previously allocated memory for _read_manufacturer
171182 free (_read_manufacturer);
172- }
173- _read_manufacturer = nullptr ;
183+ _read_manufacturer = nullptr ;
174184
175- esp_zb_lock_acquire (portMAX_DELAY);
176- esp_zb_zcl_read_attr_cmd_req (&read_req);
177- esp_zb_lock_release ();
185+ esp_zb_lock_acquire (portMAX_DELAY);
186+ esp_zb_zcl_read_attr_cmd_req (&read_req);
187+ esp_zb_lock_release ();
178188
179- // Wait for response or timeout
180- if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
181- log_e (" Error while reading manufacturer" );
182- }
183- return _read_manufacturer;
189+ // Wait for response or timeout
190+ if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
191+ log_e (" Error while reading manufacturer" );
192+ }
193+ return _read_manufacturer;
184194}
185195
186196char *ZigbeeEP::readModel (uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
187- /* Read peer Manufacture Name & Model Identifier */
188- esp_zb_zcl_read_attr_cmd_t read_req;
197+ /* Read peer Model Identifier */
198+ esp_zb_zcl_read_attr_cmd_t read_req;
199+
200+ if (short_addr != 0 ) {
201+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
202+ read_req.zcl_basic_cmd .dst_addr_u .addr_short = short_addr;
203+ } else {
204+ read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
205+ memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
206+ }
189207
190- if (short_addr != 0 ) {
191- read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
192- read_req.zcl_basic_cmd .dst_addr_u .addr_short = short_addr;
193- } else {
194- read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
195- memcpy (read_req.zcl_basic_cmd .dst_addr_u .addr_long , ieee_addr, sizeof (esp_zb_ieee_addr_t ));
196- }
208+ read_req.zcl_basic_cmd .src_endpoint = _endpoint;
209+ read_req.zcl_basic_cmd .dst_endpoint = endpoint;
210+ read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC;
197211
198- read_req.zcl_basic_cmd .src_endpoint = _endpoint;
199- read_req.zcl_basic_cmd .dst_endpoint = endpoint;
200- read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_BASIC;
212+ uint16_t attributes[] = {
213+ ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
214+ };
215+ read_req.attr_number = ZB_ARRAY_LENTH (attributes);
216+ read_req.attr_field = attributes;
201217
202- uint16_t attributes[] = {
203- ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
204- };
205- read_req.attr_number = ZB_ARRAY_LENTH (attributes);
206- read_req.attr_field = attributes;
207-
208- if (_read_model != nullptr ) {
218+ // Free previously allocated memory for _read_model
209219 free (_read_model);
210- }
211- _read_model = nullptr ;
220+ _read_model = nullptr ;
212221
213- esp_zb_lock_acquire (portMAX_DELAY);
214- esp_zb_zcl_read_attr_cmd_req (&read_req);
215- esp_zb_lock_release ();
222+ esp_zb_lock_acquire (portMAX_DELAY);
223+ esp_zb_zcl_read_attr_cmd_req (&read_req);
224+ esp_zb_lock_release ();
216225
217- // Wait for response or timeout
218- if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
219- log_e (" Error while reading model" );
220- }
221- return _read_model;
226+ // Wait for response or timeout
227+ if (xSemaphoreTake (lock, ZB_CMD_TIMEOUT) != pdTRUE) {
228+ log_e (" Error while reading model" );
229+ }
230+ return _read_model;
222231}
223232
224233void ZigbeeEP::printBoundDevices () {
@@ -246,25 +255,44 @@ void ZigbeeEP::printBoundDevices(Print &print) {
246255}
247256
248257void ZigbeeEP::zbReadBasicCluster (const esp_zb_zcl_attribute_t *attribute) {
249- /* Basic cluster attributes */
250- if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID && attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data .value ) {
251- zbstring_t *zbstr = (zbstring_t *)attribute->data .value ;
252- char string[zbstr->len + 1 ];
253- memcpy (string, zbstr->data , zbstr->len );
254- string[zbstr->len ] = ' \0 ' ;
255- log_i (" Peer Manufacturer is \" %s\" " , string);
256- _read_manufacturer = string;
257- xSemaphoreGive (lock);
258- }
259- if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID && attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING && attribute->data .value ) {
260- zbstring_t *zbstr = (zbstring_t *)attribute->data .value ;
261- char string[zbstr->len + 1 ];
262- memcpy (string, zbstr->data , zbstr->len );
263- string[zbstr->len ] = ' \0 ' ;
264- log_i (" Peer Model is \" %s\" " , string);
265- _read_model = string;
266- xSemaphoreGive (lock);
267- }
258+ /* Basic cluster attributes */
259+ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID &&
260+ attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING &&
261+ attribute->data .value ) {
262+ zbstring_t *zbstr = (zbstring_t *)attribute->data .value ;
263+
264+ // Use std::vector<char> for automatic memory management
265+ std::vector<char > string (zbstr->len + 1 ); // Allocate space for the string and null terminator
266+ memcpy (string.data (), zbstr->data , zbstr->len );
267+ string[zbstr->len ] = ' \0 ' ; // Null-terminate the string
268+
269+ log_i (" Peer Manufacturer is \" %s\" " , string.data ());
270+
271+ // Update _read_manufacturer with a dynamically allocated copy
272+ free (_read_manufacturer); // Free any previously allocated memory
273+ _read_manufacturer = strdup (string.data ()); // Duplicate the string for persistent storage
274+
275+ xSemaphoreGive (lock);
276+ }
277+
278+ if (attribute->id == ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID &&
279+ attribute->data .type == ESP_ZB_ZCL_ATTR_TYPE_CHAR_STRING &&
280+ attribute->data .value ) {
281+ zbstring_t *zbstr = (zbstring_t *)attribute->data .value ;
282+
283+ // Use std::vector<char> for automatic memory management
284+ std::vector<char > string (zbstr->len + 1 ); // Allocate space for the string and null terminator
285+ memcpy (string.data (), zbstr->data , zbstr->len );
286+ string[zbstr->len ] = ' \0 ' ; // Null-terminate the string
287+
288+ log_i (" Peer Model is \" %s\" " , string.data ());
289+
290+ // Update _read_model with a dynamically allocated copy
291+ free (_read_model); // Free any previously allocated memory
292+ _read_model = strdup (string.data ()); // Duplicate the string for persistent storage
293+
294+ xSemaphoreGive (lock);
295+ }
268296}
269297
270298void ZigbeeEP::zbIdentify (const esp_zb_zcl_set_attr_value_message_t *message) {
0 commit comments