Skip to content

Commit 508b6fa

Browse files
committed
feat(zigbee): Add checks on setting attrs and commands
1 parent e2915c4 commit 508b6fa

30 files changed

+614
-257
lines changed

libraries/Zigbee/src/ZigbeeEP.cpp

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ void ZigbeeEP::setVersion(uint8_t version) {
3232
_ep_config.app_device_version = version;
3333
}
3434

35-
void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
35+
bool ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
3636
// Convert manufacturer to ZCL string
3737
size_t length = strlen(name);
3838
if (length > 32) {
3939
log_e("Manufacturer name is too long");
40-
return;
40+
return false;
4141
}
4242
// Allocate a new array of size length + 2 (1 for the length, 1 for null terminator)
4343
char *zb_name = new char[length + 2];
@@ -53,7 +53,7 @@ void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
5353
if (length > 32) {
5454
log_e("Model name is too long");
5555
delete[] zb_name;
56-
return;
56+
return false;
5757
}
5858
char *zb_model = new char[length + 2];
5959
zb_model[0] = static_cast<char>(length);
@@ -62,8 +62,13 @@ void ZigbeeEP::setManufacturerAndModel(const char *name, const char *model) {
6262

6363
// Get the basic cluster and update the manufacturer and model attributes
6464
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);
65-
esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name);
66-
esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model);
65+
esp_err_t ret_manufacturer = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, (void *)zb_name);
66+
esp_err_t ret_model = esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, (void *)zb_model);
67+
if(ret_manufacturer != ESP_OK || ret_model != ESP_OK) {
68+
log_e("Failed to set manufacturer and model");
69+
return false;
70+
}
71+
return true;
6772
}
6873

6974
void ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_percentage) {
@@ -72,6 +77,9 @@ void ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_pe
7277

7378
if (power_source == ZB_POWER_SOURCE_BATTERY) {
7479
// Add power config cluster and battery percentage attribute
80+
if (battery_percentage > 100) {
81+
battery_percentage = 100;
82+
}
7583
battery_percentage = battery_percentage * 2;
7684
esp_zb_attribute_list_t *power_config_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG);
7785
esp_zb_power_config_cluster_add_attr(power_config_cluster, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, (void *)&battery_percentage);
@@ -80,20 +88,26 @@ void ZigbeeEP::setPowerSource(zb_power_source_t power_source, uint8_t battery_pe
8088
_power_source = power_source;
8189
}
8290

83-
void ZigbeeEP::setBatteryPercentage(uint8_t percentage) {
91+
bool ZigbeeEP::setBatteryPercentage(uint8_t percentage) {
8492
// 100% = 200 in decimal, 0% = 0
8593
// Convert percentage to 0-200 range
94+
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
8695
if (percentage > 100) {
8796
percentage = 100;
8897
}
8998
percentage = percentage * 2;
9099
esp_zb_lock_acquire(portMAX_DELAY);
91-
esp_zb_zcl_set_attribute_val(
100+
ret = esp_zb_zcl_set_attribute_val(
92101
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID, &percentage,
93102
false
94103
);
95104
esp_zb_lock_release();
105+
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
106+
log_e("Failed to set battery percentage");
107+
return false;
108+
}
96109
log_v("Battery percentage updated");
110+
return true;
97111
}
98112

99113
void ZigbeeEP::reportBatteryPercentage() {
@@ -107,9 +121,14 @@ void ZigbeeEP::reportBatteryPercentage() {
107121
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
108122

109123
esp_zb_lock_acquire(portMAX_DELAY);
110-
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
124+
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
111125
esp_zb_lock_release();
126+
if(ret != ESP_OK) {
127+
log_e("Failed to report battery percentage");
128+
return false;
129+
}
112130
log_v("Battery percentage reported");
131+
return true;
113132
}
114133

115134
char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
@@ -260,18 +279,31 @@ void ZigbeeEP::addTimeCluster(tm time, int32_t gmt_offset) {
260279
esp_zb_cluster_list_add_time_cluster(_cluster_list, time_cluster_client, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
261280
}
262281

263-
void ZigbeeEP::setTime(tm time) {
282+
bool ZigbeeEP::setTime(tm time) {
283+
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
264284
time_t utc_time = mktime(&time);
265285
log_d("Setting time to %lld", utc_time);
266286
esp_zb_lock_acquire(portMAX_DELAY);
267-
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);
287+
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);
268288
esp_zb_lock_release();
289+
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
290+
log_e("Failed to set time");
291+
return false;
292+
}
293+
return true;
269294
}
270295

271-
void ZigbeeEP::setTimezone(int32_t gmt_offset) {
296+
bool ZigbeeEP::setTimezone(int32_t gmt_offset) {
297+
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
298+
log_d("Setting timezone to %d", gmt_offset);
272299
esp_zb_lock_acquire(portMAX_DELAY);
273-
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);
300+
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);
274301
esp_zb_lock_release();
302+
if(ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
303+
log_e("Failed to set timezone");
304+
return false;
305+
}
306+
return true;
275307
}
276308

277309
tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) {
@@ -410,11 +442,11 @@ void ZigbeeEP::addOTAClient(
410442
uint16_t ota_upgrade_server_addr = 0xffff;
411443
uint8_t ota_upgrade_server_ep = 0xff;
412444

413-
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_CLIENT_DATA_ID, (void *)&variable_config));
414-
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ADDR_ID, (void *)&ota_upgrade_server_addr));
415-
ESP_ERROR_CHECK(esp_zb_ota_cluster_add_attr(ota_cluster, ESP_ZB_ZCL_ATTR_OTA_UPGRADE_SERVER_ENDPOINT_ID, (void *)&ota_upgrade_server_ep));
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);
416448

417-
ESP_ERROR_CHECK(esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE));
449+
esp_zb_cluster_list_add_ota_cluster(_cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
418450
}
419451

420452
static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx) {

libraries/Zigbee/src/ZigbeeEP.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,21 @@ class ZigbeeEP {
7070
}
7171

7272
// Set Manufacturer name and model
73-
void setManufacturerAndModel(const char *name, const char *model);
73+
bool setManufacturerAndModel(const char *name, const char *model);
7474

7575
// Methods to read manufacturer and model name from selected endpoint and short address
7676
char *readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr);
7777
char *readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr);
7878

7979
// Set Power source and battery percentage for battery powered devices
8080
void setPowerSource(zb_power_source_t power_source, uint8_t percentage = 255);
81-
void setBatteryPercentage(uint8_t percentage);
82-
void reportBatteryPercentage();
81+
bool setBatteryPercentage(uint8_t percentage);
82+
bool reportBatteryPercentage();
8383

8484
// Set time
8585
void addTimeCluster(tm time = {}, int32_t gmt_offset = 0); // gmt offset in seconds
86-
void setTime(tm time);
87-
void setTimezone(int32_t gmt_offset);
86+
bool setTime(tm time);
87+
bool setTimezone(int32_t gmt_offset);
8888

8989
// Get time from Coordinator or specific endpoint (blocking until response)
9090
struct tm getTime(uint8_t endpoint = 1, int32_t short_addr = 0x0000, esp_zb_ieee_addr_t ieee_addr = {0});

libraries/Zigbee/src/ep/ZigbeeAnalog.cpp

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,34 @@ ZigbeeAnalog::ZigbeeAnalog(uint8_t endpoint) : ZigbeeEP(endpoint) {
2020
_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};
2121
}
2222

23-
void ZigbeeAnalog::addAnalogValue() {
24-
esp_zb_cluster_list_add_analog_value_cluster(_cluster_list, esp_zb_analog_value_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
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");
27+
return false;
28+
}
2529
_analog_clusters |= ANALOG_VALUE;
30+
return true;
2631
}
2732

28-
void ZigbeeAnalog::addAnalogInput() {
29-
esp_zb_cluster_list_add_analog_input_cluster(_cluster_list, esp_zb_analog_input_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
33+
bool ZigbeeAnalog::addAnalogInput() {
34+
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);
35+
if (ret != ESP_OK) {
36+
log_e("Failed to add Analog Input cluster");
37+
return false;
38+
}
3039
_analog_clusters |= ANALOG_INPUT;
40+
return true;
3141
}
3242

33-
void ZigbeeAnalog::addAnalogOutput() {
34-
esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
43+
bool ZigbeeAnalog::addAnalogOutput() {
44+
esp_err_t ret = esp_zb_cluster_list_add_analog_output_cluster(_cluster_list, esp_zb_analog_output_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
45+
if (ret != ESP_OK) {
46+
log_e("Failed to add Analog Output cluster");
47+
return false;
48+
}
3549
_analog_clusters |= ANALOG_OUTPUT;
50+
return true;
3651
}
3752

3853
//set attribute method -> method overridden in child class
@@ -57,35 +72,45 @@ void ZigbeeAnalog::analogOutputChanged(float analog_output) {
5772
}
5873
}
5974

60-
void ZigbeeAnalog::setAnalogValue(float analog) {
75+
bool ZigbeeAnalog::setAnalogValue(float analog) {
76+
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
6177
if (!(_analog_clusters & ANALOG_VALUE)) {
6278
log_e("Analog Value cluster not added");
63-
return;
79+
return false;
6480
}
65-
// float zb_analog = analog;
6681
log_d("Setting analog value to %.1f", analog);
6782
esp_zb_lock_acquire(portMAX_DELAY);
68-
esp_zb_zcl_set_attribute_val(
83+
ret = esp_zb_zcl_set_attribute_val(
6984
_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
7085
);
7186
esp_zb_lock_release();
87+
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
88+
log_e("Failed to set analog value");
89+
return false;
90+
}
91+
return true;
7292
}
7393

74-
void ZigbeeAnalog::setAnalogInput(float analog) {
94+
bool ZigbeeAnalog::setAnalogInput(float analog) {
95+
esp_zb_zcl_status_t ret = ESP_ZB_ZCL_STATUS_SUCCESS;
7596
if (!(_analog_clusters & ANALOG_INPUT)) {
7697
log_e("Analog Input cluster not added");
77-
return;
98+
return false;
7899
}
79-
// float zb_analog = analog;
80100
log_d("Setting analog input to %.1f", analog);
81101
esp_zb_lock_acquire(portMAX_DELAY);
82-
esp_zb_zcl_set_attribute_val(
102+
ret = esp_zb_zcl_set_attribute_val(
83103
_endpoint, ESP_ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID, &analog, false
84104
);
85105
esp_zb_lock_release();
106+
if (ret != ESP_ZB_ZCL_STATUS_SUCCESS) {
107+
log_e("Failed to set analog input");
108+
return false;
109+
}
110+
return true;
86111
}
87112

88-
void ZigbeeAnalog::reportAnalogInput() {
113+
bool ZigbeeAnalog::reportAnalogInput() {
89114
/* Send report attributes command */
90115
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
91116
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
@@ -96,12 +121,17 @@ void ZigbeeAnalog::reportAnalogInput() {
96121
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
97122

98123
esp_zb_lock_acquire(portMAX_DELAY);
99-
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
124+
esp_err_t ret = esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
100125
esp_zb_lock_release();
126+
if (ret != ESP_OK) {
127+
log_e("Failed to send Analog Input report");
128+
return false;
129+
}
101130
log_v("Analog Input report sent");
131+
return true;
102132
}
103133

104-
void ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
134+
bool ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta) {
105135
esp_zb_zcl_reporting_info_t reporting_info;
106136
memset(&reporting_info, 0, sizeof(esp_zb_zcl_reporting_info_t));
107137
reporting_info.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
@@ -118,8 +148,13 @@ void ZigbeeAnalog::setAnalogInputReporting(uint16_t min_interval, uint16_t max_i
118148
reporting_info.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
119149

120150
esp_zb_lock_acquire(portMAX_DELAY);
121-
esp_zb_zcl_update_reporting_info(&reporting_info);
151+
esp_err_t ret = esp_zb_zcl_update_reporting_info(&reporting_info);
122152
esp_zb_lock_release();
153+
if (ret != ESP_OK) {
154+
log_e("Failed to set Analog Input reporting");
155+
return false;
156+
}
157+
return true;
123158
}
124159

125160
#endif // CONFIG_ZB_ENABLED

libraries/Zigbee/src/ep/ZigbeeAnalog.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,24 @@ class ZigbeeAnalog : public ZigbeeEP {
4545
~ZigbeeAnalog() {}
4646

4747
// Add analog clusters
48-
void addAnalogValue();
49-
void addAnalogInput();
50-
void addAnalogOutput();
48+
bool addAnalogValue();
49+
bool addAnalogInput();
50+
bool addAnalogOutput();
5151

5252
// Use to set a cb function to be called on analog output change
5353
void onAnalogOutputChange(void (*callback)(float analog)) {
5454
_on_analog_output_change = callback;
5555
}
5656

5757
// Set the analog value / input
58-
void setAnalogValue(float analog);
59-
void setAnalogInput(float analog);
58+
bool setAnalogValue(float analog);
59+
bool setAnalogInput(float analog);
6060

6161
// Report Analog Input
62-
void reportAnalogInput();
62+
bool reportAnalogInput();
6363

6464
// Set reporting for Analog Input
65-
void setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta);
65+
bool setAnalogInputReporting(uint16_t min_interval, uint16_t max_interval, float delta);
6666

6767
private:
6868
void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) override;

0 commit comments

Comments
 (0)