Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
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