Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libraries/Zigbee/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ scanComplete KEYWORD2
getScanResult KEYWORD2
scanDelete KEYWORD2
factoryReset KEYWORD2
allowMultiEndpointBinding KEYWORD2

# Common ZigbeeEP
setEpConfig KEYWORD2
Expand Down
11 changes: 8 additions & 3 deletions libraries/Zigbee/src/ZigbeeCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ ZigbeeCore::ZigbeeCore() {
_scan_duration = 3; // default scan duration
_rx_on_when_idle = true;
_debug = false;
_allow_multi_endpoint_binding = false;
_global_default_response_cb = nullptr; // Initialize global callback to nullptr
if (!lock) {
lock = xSemaphoreCreateBinary();
Expand Down Expand Up @@ -392,7 +393,9 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
log_d("Device not bound to endpoint %d and it is free to bound!", (*it)->getEndpoint());
(*it)->findEndpoint(&cmd_req);
log_d("Endpoint %d is searching for device", (*it)->getEndpoint());
break; // Only one endpoint per device
if(!Zigbee.allowMultiEndpointBinding()) { // If multi endpoint binding is not allowed, break the loop to keep backwards compatibility
break;
}
}
}
}
Expand Down Expand Up @@ -422,11 +425,13 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
break;
}
}
log_d("Device not bound to endpoint %d and it is free to bound!", (*it)->getEndpoint());
if (!found) {
log_d("Device not bound to endpoint %d and it is free to bound!", (*it)->getEndpoint());
(*it)->findEndpoint(&cmd_req);
log_d("Endpoint %d is searching for device", (*it)->getEndpoint());
break; // Only one endpoint per device
if(!Zigbee.allowMultiEndpointBinding()) { // If multi endpoint binding is not allowed, break the loop to keep backwards compatibility
break;
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions libraries/Zigbee/src/ZigbeeCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class ZigbeeCore {
zigbee_scan_result_t *_scan_result;
SemaphoreHandle_t lock;
bool _debug;
bool _allow_multi_endpoint_binding;

// Global default response callback
void (*_global_default_response_cb)(zb_cmd_type_t resp_to_cmd, esp_zb_zcl_status_t status, uint8_t endpoint, uint16_t cluster);
Expand Down Expand Up @@ -196,6 +197,13 @@ class ZigbeeCore {
return _debug;
}

void allowMultiEndpointBinding(bool allow) {
_allow_multi_endpoint_binding = allow;
}
bool allowMultiEndpointBinding() {
return _allow_multi_endpoint_binding;
}

// Set global default response callback
void onGlobalDefaultResponse(void (*callback)(zb_cmd_type_t resp_to_cmd, esp_zb_zcl_status_t status, uint8_t endpoint, uint16_t cluster)) {
_global_default_response_cb = callback;
Expand Down
1 change: 1 addition & 0 deletions libraries/Zigbee/src/ZigbeeEP.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class ZigbeeEP {
// list of all handlers function calls, to be override by EPs implementation
virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {};
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) {};
virtual void zbWriteAttributeResponse(uint16_t cluster_id, uint16_t attribute_id, esp_zb_zcl_status_t status, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {};
virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented
virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message);
virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {};
Expand Down
33 changes: 33 additions & 0 deletions libraries/Zigbee/src/ZigbeeHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static bool s_tagid_received = false;
static esp_err_t zb_attribute_set_handler(const esp_zb_zcl_set_attr_value_message_t *message);
static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_message_t *message);
static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message);
static esp_err_t zb_cmd_write_attr_resp_handler(const esp_zb_zcl_cmd_write_attr_resp_message_t *message);
static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message);
static esp_err_t zb_cmd_ias_zone_status_change_handler(const esp_zb_zcl_ias_zone_status_change_notification_message_t *message);
static esp_err_t zb_cmd_ias_zone_enroll_response_handler(const esp_zb_zcl_ias_zone_enroll_response_message_t *message);
Expand Down Expand Up @@ -73,6 +74,7 @@ static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id,
ret = zb_ota_upgrade_query_image_resp_handler((esp_zb_zcl_ota_upgrade_query_image_resp_message_t *)message);
break;
case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID: ret = zb_cmd_default_resp_handler((esp_zb_zcl_cmd_default_resp_message_t *)message); break;
case ESP_ZB_CORE_CMD_WRITE_ATTR_RESP_CB_ID: ret = zb_cmd_write_attr_resp_handler((esp_zb_zcl_cmd_write_attr_resp_message_t *)message); break;
default: log_w("Receive unhandled Zigbee action(0x%x) callback", callback_id); break;
}
return ret;
Expand Down Expand Up @@ -170,6 +172,37 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re
return ESP_OK;
}

static esp_err_t zb_cmd_write_attr_resp_handler(const esp_zb_zcl_cmd_write_attr_resp_message_t *message) {
if (!message) {
log_e("Empty message");
return ESP_FAIL;
}
if (message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS) {
log_e("Received message: error status(%d)", message->info.status);
return ESP_ERR_INVALID_ARG;
}
log_v(
"Write attribute response: from address(0x%x) src endpoint(%d) to dst endpoint(%d) cluster(0x%x)", message->info.src_address.u.short_addr,
message->info.src_endpoint, message->info.dst_endpoint, message->info.cluster
);
for (std::list<ZigbeeEP *>::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) {
if (message->info.dst_endpoint == (*it)->getEndpoint()) {
esp_zb_zcl_write_attr_resp_variable_t *variable = message->variables;
while (variable) {
log_v(
"Write attribute response: status(%d), cluster(0x%x), attribute(0x%x)", variable->status, message->info.cluster, variable->attribute_id
);
if (variable->status == ESP_ZB_ZCL_STATUS_SUCCESS) {
(*it)->zbWriteAttributeResponse(message->info.cluster, variable->attribute_id, variable->status, message->info.src_endpoint, message->info.src_address);
}
variable = variable->next;
}
}
}
return ESP_OK;
}


static esp_err_t zb_configure_report_resp_handler(const esp_zb_zcl_cmd_config_report_resp_message_t *message) {
if (!message) {
log_e("Empty message");
Expand Down
Loading