-
-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathzigbee.cpp
More file actions
513 lines (460 loc) · 20.9 KB
/
zigbee.cpp
File metadata and controls
513 lines (460 loc) · 20.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_check.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "zigbee_attribute.h"
#include "zigbee.h"
#include "esphome/core/log.h"
#include "zigbee_helpers.h"
#ifdef CONFIG_WIFI_COEX
#include "esp_coexist.h"
#endif
#if !defined ZB_ED_ROLE
#error Define ZB_ED_ROLE in idf.py menuconfig to compile light (End Device) source code.
#endif
namespace esphome {
namespace zigbee {
ZigBeeComponent *zigbeeC;
device_params_t coord;
/********************* Define functions **************************/
uint8_t *get_character_string(std::string str) {
uint8_t *cstr = new uint8_t[(str.size() + 2)];
std::snprintf((char *) (cstr + 1), str.size() + 1, "%s", str.c_str());
cstr[0] = str.size();
return cstr;
}
static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) {
if (esp_zb_bdb_start_top_level_commissioning(mode_mask) != ESP_OK) {
ESP_LOGE(TAG, "Start network steering failed!");
}
}
void ZigBeeComponent::set_report(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id) {
/* Config the reporting info */
esp_zb_zcl_reporting_info_t reporting_info = {
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.ep = endpoint_id,
.cluster_id = cluster_id,
.cluster_role = role,
.attr_id = attr_id,
.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC,
};
// reporting_info.dst.short_addr = 0;
// reporting_info.dst.endpoint = 1;
reporting_info.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
reporting_info.u.send_info.min_interval = 10; /*!< Actual minimum reporting interval */
reporting_info.u.send_info.max_interval = 0; /*!< Actual maximum reporting interval */
reporting_info.u.send_info.def_min_interval = 10; /*!< Default minimum reporting interval */
reporting_info.u.send_info.def_max_interval = 0; /*!< Default maximum reporting interval */
reporting_info.u.send_info.delta.s16 = 0; /*!< Actual reportable change */
this->reporting_list.push_back(reporting_info);
}
void ZigBeeComponent::report() { this->report_ = true; }
void ZigBeeComponent::send_report_() {
if (esp_zb_lock_acquire(20 / portTICK_PERIOD_MS)) {
esp_zb_zcl_report_attr_cmd_t cmd = {
.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI,
};
cmd.zcl_basic_cmd.dst_addr_u.addr_short = 0x0000;
cmd.zcl_basic_cmd.dst_endpoint = 1;
for (auto reporting_info : zigbeeC->reporting_list) {
cmd.zcl_basic_cmd.src_endpoint = reporting_info.ep;
cmd.clusterID = reporting_info.cluster_id;
cmd.attributeID = reporting_info.attr_id;
// cmd.cluster_role = reporting_info.cluster_role;
esp_zb_zcl_report_attr_cmd_req(&cmd);
}
this->report_ = false;
esp_zb_lock_release();
}
}
void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
static uint8_t steering_retry_count = 0;
uint32_t *p_sg_p = signal_struct->p_app_signal;
esp_err_t err_status = signal_struct->esp_err_status;
esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t) *p_sg_p;
esp_zb_zdo_signal_leave_params_t *leave_params = NULL;
switch (sig_type) {
case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP:
// Notifies the application that ZBOSS framework (scheduler, buffer pool, etc.) has started, but no
// join/rejoin/formation/BDB initialization has been done yet.
ESP_LOGD(TAG, "Zigbee stack initialized");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION);
break;
case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START:
// Device started for the first time after the NVRAM erase
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT:
// Device started using the NVRAM contents.
if (err_status == ESP_OK) {
ESP_LOGD(TAG, "Device started up in %sfactory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non ");
zigbeeC->started = true;
if (esp_zb_bdb_is_factory_new()) {
ESP_LOGD(TAG, "Start network steering");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
} else {
ESP_LOGD(TAG, "Device rebooted");
zigbeeC->connected = true;
zigbeeC->searchBindings();
}
} else {
ESP_LOGE(TAG, "FIRST_START. Device started up in %sfactory-reset mode with an error %d (%s)",
esp_zb_bdb_is_factory_new() ? "" : "non ", err_status, esp_err_to_name(err_status));
ESP_LOGW(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
esp_zb_scheduler_alarm((esp_zb_callback_t) bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_INITIALIZATION,
1000);
}
break;
case ESP_ZB_BDB_SIGNAL_STEERING:
// BDB network steering completed (Network steering only)
if (err_status == ESP_OK) {
steering_retry_count = 0;
esp_zb_ieee_addr_t extended_pan_id;
esp_zb_get_extended_pan_id(extended_pan_id);
ESP_LOGI(TAG,
"Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: "
"0x%04hx, Channel:%d)",
extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], extended_pan_id[3],
extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], esp_zb_get_pan_id(),
esp_zb_get_current_channel());
zigbeeC->on_join_callback_.call();
zigbeeC->connected = true;
} else {
ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status));
if (steering_retry_count < 10) {
steering_retry_count++;
esp_zb_scheduler_alarm((esp_zb_callback_t) bdb_start_top_level_commissioning_cb,
ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000);
} else {
esp_zb_scheduler_alarm((esp_zb_callback_t) bdb_start_top_level_commissioning_cb,
ESP_ZB_BDB_MODE_NETWORK_STEERING, 600 * 1000);
}
}
break;
case ESP_ZB_ZDO_SIGNAL_LEAVE:
leave_params = (esp_zb_zdo_signal_leave_params_t *) esp_zb_app_signal_get_params(p_sg_p);
if (leave_params->leave_type == ESP_ZB_NWK_LEAVE_TYPE_RESET) {
ESP_LOGD(TAG, "Reset device");
esp_zb_factory_reset();
} else {
ESP_LOGD(TAG, "Leave_type: %u", leave_params->leave_type);
}
break;
default:
ESP_LOGD(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type,
esp_err_to_name(err_status));
break;
}
}
// Recall bounded devices from the binding table after reboot
void ZigBeeComponent::bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx) {
bool done = true;
esp_zb_zdo_mgmt_bind_param_t *req = (esp_zb_zdo_mgmt_bind_param_t *) user_ctx;
esp_zb_zdp_status_t zdo_status = (esp_zb_zdp_status_t) table_info->status;
ESP_LOGD(TAG, "Binding table callback for address 0x%04x with status %d", req->dst_addr, zdo_status);
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
// Print binding table log simple
ESP_LOGD(TAG, "Binding table info: total %d, index %d, count %d", table_info->total, table_info->index,
table_info->count);
if (table_info->total == 0) {
ESP_LOGD(TAG, "No binding table entries found");
free(req);
return;
}
esp_zb_zdo_binding_table_record_t *record = table_info->record;
for (int i = 0; i < table_info->count; i++) {
ESP_LOGD(TAG, "Binding table record: src_endp %d, dst_endp %d, cluster_id 0x%04x, dst_addr_mode %d",
record->src_endp, record->dst_endp, record->cluster_id, record->dst_addr_mode);
zb_device_params_t *device = (zb_device_params_t *) calloc(1, sizeof(zb_device_params_t));
device->endpoint = record->dst_endp;
if (record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT ||
record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) {
device->short_addr = record->dst_address.addr_short;
} else { // ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT
memcpy(device->ieee_addr, record->dst_address.addr_long, sizeof(esp_zb_ieee_addr_t));
}
ESP_LOGD(TAG,
"Device bound to EP %d -> device endpoint: %d, short addr: 0x%04x, ieee addr: "
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
record->src_endp, device->endpoint, device->short_addr, device->ieee_addr[7], device->ieee_addr[6],
device->ieee_addr[5], device->ieee_addr[4], device->ieee_addr[3], device->ieee_addr[2],
device->ieee_addr[1], device->ieee_addr[0]);
record = record->next;
}
// Continue reading the binding table
if (table_info->index + table_info->count < table_info->total) {
/* There are unreported binding table entries, request for them. */
req->start_index = table_info->index + table_info->count;
esp_zb_zdo_binding_table_req(req, bindingTableCb, req);
done = false;
}
}
if (done) {
// Print bound devices
ESP_LOGD(TAG, "Filling bounded devices finished");
free(req);
}
}
void ZigBeeComponent::searchBindings() {
esp_zb_zdo_mgmt_bind_param_t *mb_req = (esp_zb_zdo_mgmt_bind_param_t *) malloc(sizeof(esp_zb_zdo_mgmt_bind_param_t));
mb_req->dst_addr = esp_zb_get_short_address();
mb_req->start_index = 0;
ESP_LOGD(TAG, "Requesting binding table for address 0x%04x", mb_req->dst_addr);
esp_zb_zdo_binding_table_req(mb_req, bindingTableCb, (void *) mb_req);
}
static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) {
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message");
ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG,
"Received message: error status(%d)", message->info.status);
ESP_LOGD(TAG, "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)",
message->info.dst_endpoint, message->info.cluster, message->attribute.id, message->attribute.data.size);
zigbeeC->handle_attribute(message->info, message->attribute);
return ret;
}
static esp_err_t zb_cmd_attribute_handler(const esp_zb_zcl_cmd_read_attr_resp_message_t *message) {
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message");
ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG,
"Received message: error status(%d)", message->info.status);
esp_zb_zcl_read_attr_resp_variable_t *variable = message->variables;
switch (message->info.cluster) {
case ESP_ZB_ZCL_CLUSTER_ID_TIME:
ESP_LOGD(TAG, "Recieved time information");
#ifdef USE_ZIGBEE_TIME
if (zigbeeC->zt_ == nullptr) {
ESP_LOGD(TAG, "No time component linked to update time!");
} else {
zigbeeC->zt_->recieve_timesync_response(message->variables);
}
#else
ESP_LOGD(TAG, "No zigbee time component included at build time!");
#endif
break;
default:
ESP_LOGD(TAG, "Attribute data recieved (but not yet handled):");
while (variable) {
ESP_LOGD(TAG, "Read attribute response: status(%d), cluster(0x%x), attribute(0x%x), type(0x%x), value(%d)",
variable->status, message->info.cluster, variable->attribute.id, variable->attribute.data.type,
variable->attribute.data.value ? *(uint8_t *) variable->attribute.data.value : 0);
variable = variable->next;
}
}
return ret;
}
static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) {
esp_err_t ret = ESP_OK;
switch (callback_id) {
case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID:
ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *) message);
break;
case ESP_ZB_CORE_CMD_READ_ATTR_RESP_CB_ID:
ret = zb_cmd_attribute_handler((esp_zb_zcl_cmd_read_attr_resp_message_t *) message);
break;
case ESP_ZB_CORE_CMD_DEFAULT_RESP_CB_ID:
ESP_LOGD(TAG, "Receive Zigbee default response callback");
break;
default:
ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id);
break;
}
return ret;
}
void ZigBeeComponent::handle_attribute(esp_zb_device_cb_common_info_t info, esp_zb_zcl_attribute_t attribute) {
if (this->attributes_.find({info.dst_endpoint, info.cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attribute.id}) !=
this->attributes_.end()) {
this->attributes_[{info.dst_endpoint, info.cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, attribute.id}]->on_value(
attribute);
}
}
void ZigBeeComponent::create_default_cluster(uint8_t endpoint_id, esp_zb_ha_standard_devices_t device_id) {
this->cluster_list_[endpoint_id] = esphome_zb_default_clusters_create(device_id);
this->endpoint_list_[endpoint_id] = device_id;
}
void ZigBeeComponent::add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role) {
esp_zb_attribute_list_t *attr_list;
switch (cluster_id) {
case 0:
attr_list = create_basic_cluster_();
break;
case 3:
attr_list = create_ident_cluster_();
break;
default:
attr_list = esphome_zb_default_attr_list_create(cluster_id);
}
this->attribute_list_[{endpoint_id, cluster_id, role}] = attr_list;
}
void ZigBeeComponent::set_basic_cluster(std::string model, std::string manufacturer, std::string date, uint8_t power,
uint8_t app_version, uint8_t stack_version, uint8_t hw_version,
std::string area, uint8_t physical_env) {
this->basic_cluster_data_ = {
.model = model,
.manufacturer = manufacturer,
.date = date,
.power = power,
.app_version = app_version,
.stack_version = stack_version,
.hw_version = hw_version,
.area = area,
.physical_env = physical_env,
};
}
esp_zb_attribute_list_t *ZigBeeComponent::create_basic_cluster_() {
// ------------------------------ Cluster BASIC ------------------------------
esp_zb_basic_cluster_cfg_t basic_cluster_cfg = {
.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE,
.power_source = this->basic_cluster_data_.power,
};
ESP_LOGD(TAG, "Model: %s", this->basic_cluster_data_.model.c_str());
ESP_LOGD(TAG, "Manufacturer: %s", this->basic_cluster_data_.manufacturer.c_str());
ESP_LOGD(TAG, "Date: %s", this->basic_cluster_data_.date.c_str());
ESP_LOGD(TAG, "Area: %s", this->basic_cluster_data_.area.c_str());
uint8_t *ManufacturerName =
get_character_string(this->basic_cluster_data_.manufacturer); // warning: this is in format {length, 'string'} :
uint8_t *ModelIdentifier = get_character_string(this->basic_cluster_data_.model);
uint8_t *DateCode = get_character_string(this->basic_cluster_data_.date);
uint8_t *Location = get_character_string(this->basic_cluster_data_.area);
esp_zb_attribute_list_t *attr_list = esp_zb_basic_cluster_create(&basic_cluster_cfg);
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID,
&(this->basic_cluster_data_.app_version));
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_STACK_VERSION_ID,
&(this->basic_cluster_data_.stack_version));
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_HW_VERSION_ID,
&(this->basic_cluster_data_.hw_version));
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, ManufacturerName);
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, ModelIdentifier);
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_DATE_CODE_ID, DateCode);
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID, Location);
esp_zb_basic_cluster_add_attr(attr_list, ESP_ZB_ZCL_ATTR_BASIC_PHYSICAL_ENVIRONMENT_ID,
&(this->basic_cluster_data_.physical_env));
return attr_list;
}
void ZigBeeComponent::set_ident_time(uint8_t ident_time) {
// ------------------------------ Cluster IDENTIFY ------------------------------
this->ident_time_ = ident_time;
}
esp_zb_attribute_list_t *ZigBeeComponent::create_ident_cluster_() {
// ------------------------------ Cluster IDENTIFY ------------------------------
esp_zb_identify_cluster_cfg_t identify_cluster_cfg = {
.identify_time = this->ident_time_,
};
return esp_zb_identify_cluster_create(&identify_cluster_cfg);
}
esp_err_t ZigBeeComponent::create_endpoint(uint8_t endpoint_id, esp_zb_ha_standard_devices_t device_id) {
esp_zb_cluster_list_t *esp_zb_cluster_list = this->cluster_list_[endpoint_id];
// ------------------------------ Create endpoint list ------------------------------
esp_zb_endpoint_config_t endpoint_config = {.endpoint = endpoint_id,
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.app_device_id = device_id,
.app_device_version = CONF_DEVICE_VERSION};
return esp_zb_ep_list_add_ep(this->esp_zb_ep_list_, esp_zb_cluster_list, endpoint_config);
}
static void esp_zb_task_(void *pvParameters) {
if (esp_zb_start(false) != ESP_OK) {
ESP_LOGE(TAG, "Could not setup Zigbee");
// this->mark_failed();
vTaskDelete(NULL);
}
esp_zb_stack_main_loop();
}
void ZigBeeComponent::setup() {
zigbeeC = this;
esp_zb_platform_config_t config = {
.radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_ZB_DEFAULT_HOST_CONFIG(),
};
#ifdef CONFIG_WIFI_COEX
if (esp_coex_wifi_i154_enable() != ESP_OK) {
this->mark_failed();
return;
}
#endif
// ESP_ERROR_CHECK(nvs_flash_init()); not needed, called by esp32 component
if (esp_zb_platform_config(&config) != ESP_OK) {
this->mark_failed();
return;
}
/* initialize Zigbee stack */
esp_zb_zed_cfg_t zb_zed_cfg = {
.ed_timeout = ED_AGING_TIMEOUT,
.keep_alive = ED_KEEP_ALIVE,
};
esp_zb_cfg_t zb_nwk_cfg = {
.esp_zb_role = this->device_role_,
.install_code_policy = INSTALLCODE_POLICY_ENABLE,
};
zb_nwk_cfg.nwk_cfg.zed_cfg = zb_zed_cfg;
esp_zb_init(&zb_nwk_cfg);
#ifdef CONF_TRUST_CENTER_KEY
uint8_t trustkey_[16];
memset(trustkey_, 0, 16);
char temp[3] = {0};
for (int i = 0; i < 16; i++) {
strncpy(temp, &(CONF_TRUST_CENTER_KEY[i * 2]), 2);
trustkey_[i] = std::strtoul(temp, nullptr, 16);
}
ESP_LOGE(TAG, "Zigbee trust center key: %s", format_hex_pretty(trustkey_, 16).c_str());
esp_zb_enable_joining_to_distributed(true);
esp_zb_secur_TC_standard_distributed_key_set(trustkey_);
#endif
esp_err_t ret;
// clusters
for (auto const &[key, val] : this->attribute_list_) {
esp_zb_cluster_list_t *esp_zb_cluster_list = this->cluster_list_[std::get<0>(key)];
ret = esphome_zb_cluster_list_add_or_update_cluster(std::get<1>(key), esp_zb_cluster_list, val, std::get<2>(key));
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Could not create cluster 0x%04X with role %u: %s", std::get<1>(key), std::get<2>(key),
esp_err_to_name(ret));
}
}
// endpoints
for (auto const &[ep_id, dev_id] : this->endpoint_list_) {
// create_default_cluster(key, val);
if (create_endpoint(ep_id, dev_id) != ESP_OK) {
ESP_LOGE(TAG, "Could not create endpoint %u", ep_id);
}
}
// ------------------------------ Register Device ------------------------------
if (esp_zb_device_register(this->esp_zb_ep_list_) != ESP_OK) {
ESP_LOGE(TAG, "Could not register the endpoint list");
this->mark_failed();
return;
}
esp_zb_core_action_handler_register(zb_action_handler);
if (esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK) != ESP_OK) {
ESP_LOGE(TAG, "Could not setup Zigbee");
this->mark_failed();
return;
}
// reporting
for (auto reporting_info : this->reporting_list) {
ESP_LOGD(TAG, "set reporting for cluster: %u", reporting_info.cluster_id);
esp_zb_zcl_attr_location_info_t attr_info = {
.endpoint_id = reporting_info.ep,
.cluster_id = reporting_info.cluster_id,
.cluster_role = reporting_info.cluster_role,
.manuf_code = reporting_info.manuf_code,
.attr_id = reporting_info.attr_id,
};
if (esp_zb_zcl_update_reporting_info(&reporting_info) != ESP_OK) {
ESP_LOGE(TAG, "Could not configure reporting for attribute 0x%04X in cluster 0x%04X in endpoint %u",
reporting_info.attr_id, reporting_info.cluster_id, reporting_info.ep);
}
// ESP_ERROR_CHECK(esp_zb_zcl_start_attr_reporting(attr_info)); // is this needed?
}
xTaskCreate(esp_zb_task_, "Zigbee_main", 4096, NULL, 24, NULL);
}
void ZigBeeComponent::loop() {
if (this->report_) {
this->send_report_();
}
}
void ZigBeeComponent::dump_config() {
ESP_LOGCONFIG(TAG, "ZigBee:");
for (auto const &[key, val] : this->endpoint_list_) {
ESP_LOGCONFIG(TAG, "Endpoint: %u, %d", key, val);
}
}
} // namespace zigbee
} // namespace esphome