ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
zigbee_esp32.cpp
Go to the documentation of this file.
2#ifdef USE_ESP32
3#ifdef USE_ZIGBEE
4
5#include "freertos/FreeRTOS.h"
6#include "freertos/task.h"
7#include "esp_check.h"
9#include "zigbee_esp32.h"
11#include "esphome/core/log.h"
13#ifdef USE_WIFI
14#include "esp_coexist.h"
15#endif
16
17namespace esphome::zigbee {
18
19ESPHOME_LOG_TAG(TAG, "zigbee");
20
21static constexpr uint32_t COMMISSIONING_RETRY_TIMEOUT_ID = 0;
22
23static ZigbeeComponent *global_zigbee = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
24
25uint8_t *get_zcl_string(const char *str, uint8_t max_size, bool use_max_size) {
26 uint8_t str_len = static_cast<uint8_t>(strlen(str));
27 uint8_t zcl_str_size = use_max_size ? max_size : std::min(max_size, str_len);
28 uint8_t *zcl_str = new uint8_t[zcl_str_size + 1]; // string + length octet
29 zcl_str[0] = zcl_str_size;
30
31 // Initialize payload to avoid leaking uninitialized heap contents and clamp copy length
32 memset(zcl_str + 1, 0, zcl_str_size);
33 uint8_t copy_len = std::min(zcl_str_size, str_len);
34 if (copy_len > 0) {
35 memcpy(zcl_str + 1, str, copy_len);
36 }
37 return zcl_str;
38}
39
41 esp_zigbee_lock_acquire(portMAX_DELAY);
42 if (this->joined_) {
43 // send leave request and trigger EZB_ZDO_SIGNAL_LEAVE
44 ezb_bdb_reset_via_local_action();
45 } else {
46 esp_zigbee_factory_reset(); // triggers a reboot
47 }
48 esp_zigbee_lock_release();
49}
50
52 for (const auto &[_, attribute] : this->attributes_) {
53 attribute->report();
54 }
55}
56
58 if (!esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
59 global_zigbee->set_timeout(COMMISSIONING_RETRY_TIMEOUT_ID, 100,
61 return;
62 }
63 if (ezb_bdb_start_top_level_commissioning(mode) != EZB_ERR_NONE) {
64 ESP_LOGE(TAG, "Start top level commissioning failed!");
65 }
66 esp_zigbee_lock_release();
67}
68
69bool ZigbeeComponent::app_signal_handler(const ezb_app_signal_t *app_signal) {
70 static uint8_t steering_retry_count = 0;
71 ezb_app_signal_type_t signal_type = ezb_app_signal_get_type(app_signal);
72 switch (signal_type) {
73 case EZB_ZDO_SIGNAL_SKIP_STARTUP:
74 ESP_LOGD(TAG, "Zigbee stack initialized");
75 global_zigbee->started_ = true;
76 global_zigbee->enable_loop_soon_any_context();
77 ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_INITIALIZATION);
78 break;
79 case EZB_BDB_SIGNAL_DEVICE_FIRST_START:
80 case EZB_BDB_SIGNAL_DEVICE_REBOOT: {
81 ezb_bdb_comm_status_t status = *((ezb_bdb_comm_status_t *) ezb_app_signal_get_params(app_signal));
82 if (status == EZB_BDB_STATUS_SUCCESS) {
83 ESP_LOGD(TAG, "Device started up in %sfactory-reset mode", ezb_bdb_is_factory_new() ? "" : "non ");
84 if (ezb_bdb_is_factory_new()) {
85 global_zigbee->factory_new_ = true;
86 ESP_LOGD(TAG, "Start network steering");
87 ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
88 } else {
89 ESP_LOGD(TAG, "Device rebooted");
90 global_zigbee->joined_ = true;
91 global_zigbee->join_pending_ = true;
92 global_zigbee->enable_loop_soon_any_context();
93 }
94 } else {
95 ESP_LOGW(TAG, "The %s failed with status(0x%02x), please retry", ezb_app_signal_to_string(signal_type), status);
96 global_zigbee->set_timeout(COMMISSIONING_RETRY_TIMEOUT_ID, 1000, []() {
97 ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(EZB_BDB_MODE_INITIALIZATION);
98 });
99 }
100 } break;
101 case EZB_BDB_SIGNAL_STEERING: {
102 ezb_bdb_comm_status_t status = *((ezb_bdb_comm_status_t *) ezb_app_signal_get_params(app_signal));
103 if (status == EZB_BDB_STATUS_SUCCESS) {
104 steering_retry_count = 0;
105 ezb_extpanid_t extended_pan_id;
106 ezb_nwk_get_extended_panid(&extended_pan_id);
107 ESP_LOGD(TAG, "Joined network successfully: PAN ID(0x%04hx, EXT: 0x%llx), Channel(%d), Short Address(0x%04hx)",
108 ezb_nwk_get_panid(), extended_pan_id.u64, ezb_nwk_get_current_channel(), ezb_nwk_get_short_address());
109 global_zigbee->joined_ = true;
110 global_zigbee->join_pending_ = true;
111 global_zigbee->enable_loop_soon_any_context();
112 } else {
113 ESP_LOGD(TAG, "Failed to join network with status(0x%02x)", status);
114 if (steering_retry_count < 10) {
115 steering_retry_count++;
116 global_zigbee->set_timeout(COMMISSIONING_RETRY_TIMEOUT_ID, 1000, []() {
117 ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
118 });
119 } else {
120 global_zigbee->set_timeout(COMMISSIONING_RETRY_TIMEOUT_ID, 600 * 1000, []() {
121 ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
122 });
123 }
124 }
125 } break;
126 case EZB_ZDO_SIGNAL_LEAVE: {
127 const ezb_zdo_signal_leave_params_t *leave_params =
128 (const ezb_zdo_signal_leave_params_t *) ezb_app_signal_get_params(app_signal);
129 if (leave_params->leave_type == EZB_ZDO_LEAVE_TYPE_RESET) {
130 esp_zigbee_factory_reset(); // triggers a reboot
131 }
132 global_zigbee->joined_ = false;
133 } break;
134 case EZB_NWK_SIGNAL_NETWORK_STATUS: {
135 const ezb_nwk_signal_network_status_params_t *network_status_params =
136 (const ezb_nwk_signal_network_status_params_t *) ezb_app_signal_get_params(app_signal);
137 if (network_status_params->status == EZB_NWK_NETWORK_STATUS_PARENT_LINK_FAILURE) {
138 global_zigbee->joined_ = false;
139 ESP_LOGW(TAG, "Parent link failure, attempting rejoin");
140 ezb_zdo_nwk_mgmt_leave_req_t leave_req = {
141 .dst_nwk_addr = ezb_nwk_get_short_address(),
142 .field =
143 {
144 .remove_children = false,
145 .rejoin = true,
146 },
147 };
148 // Send leave request to the network to rejoin
149 // triggers EZB_ZDO_SIGNAL_LEAVE signal first, then EZB_BDB_SIGNAL_DEVICE_REBOOT
150 ezb_zdo_nwk_mgmt_leave_req(&leave_req);
151 } else {
152 ESP_LOGD(TAG, "Zigbee APP Signal NETWORK_STATUS: 0x%02x", network_status_params->status);
153 }
154 } break;
155 default:
156 ESP_LOGD(TAG, "Zigbee APP Signal: %s(type: 0x%02x)", ezb_app_signal_to_string(signal_type), signal_type);
157 break;
158 }
159 return true;
160}
161
162void load_zb_event(ZBEvent *event, ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute) {
163 event->load_set_attr_value_event(info, attribute);
164}
165
166template<typename... Args> void enqueue_zb_event(Args... args) {
167 // Allocate an event from the pool
168 ZBEvent *event = global_zigbee->zb_event_pool_.allocate();
169 if (event == nullptr) {
170 // No events available - queue is full or we're out of memory
171 global_zigbee->zb_events_.increment_dropped_count();
172 return;
173 }
174
175 // Load new event data (replaces previous event)
176 load_zb_event(event, args...);
177
178 // Push the event to the queue
179 global_zigbee->zb_events_.push(event);
180 // Push always succeeds because we're the only producer and the pool ensures we never exceed queue size
181 global_zigbee->enable_loop_soon_any_context();
182}
183
184// Explicit template instantiations for the friend function
185template void enqueue_zb_event(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute);
186
187static void zb_attribute_handler(ezb_zcl_set_attr_value_message_t *message) {
188 ESP_RETURN_ON_FALSE(message, , TAG, "Empty message");
189 ESP_RETURN_ON_FALSE(message->info.status == EZB_ZCL_STATUS_SUCCESS, , TAG, "Received message: error status(%d)",
190 message->info.status);
191 ESP_LOGD(TAG, "ZCL SetAttributeValue message for endpoint(%d) cluster(0x%04x) %s with status(0x%02x)",
192 message->info.dst_ep, message->info.cluster_id,
193 message->info.cluster_role == EZB_ZCL_CLUSTER_SERVER ? "server" : "client", message->info.status);
194 enqueue_zb_event(message->info, message->in.attribute);
195}
196
197static void zb_action_handler(ezb_zcl_core_action_callback_id_t callback_id, void *message) {
198 switch (callback_id) {
199 case EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID:
200 zb_attribute_handler((ezb_zcl_set_attr_value_message_t *) message);
201 break;
202 case EZB_ZCL_CORE_DEFAULT_RSP_CB_ID: {
203#ifdef ESPHOME_LOG_HAS_VERBOSE
204 ezb_zcl_cmd_default_rsp_message_t *default_rsp = (ezb_zcl_cmd_default_rsp_message_t *) message;
205 ESP_LOGV(TAG, "Received ZCL Default Response: 0x%02x", default_rsp->in.status_code);
206#endif
207 } break;
208 default:
209 ESP_LOGD(TAG, "Receive Zigbee action(0x%04x) callback", static_cast<unsigned>(callback_id));
210 break;
211 }
212}
213
214void ZigbeeComponent::handle_attribute_(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute) {
215 auto it = this->attributes_.find({info.dst_ep, info.cluster_id, info.cluster_role, attribute.id});
216 if (it != this->attributes_.end()) {
217 it->second->on_value(attribute);
218 }
219}
220
221void ZigbeeComponent::create_default_cluster(uint8_t endpoint_id, uint16_t device_id) {
222 ezb_af_ep_desc_t ep_desc =
223 esphome_zb_zha_default_ep_desc_create(endpoint_id, device_id, this->basic_cluster_data_.power_source);
224 if (ezb_af_device_add_endpoint_desc(this->dev_desc_, ep_desc) != EZB_ERR_NONE) {
225 ESP_LOGE(TAG, "Could not create endpoint %u", endpoint_id);
226 }
227 // Add basic cluster
228 this->update_basic_cluster_(ep_desc);
229 // Add identify cluster if not already present
230 this->add_cluster(endpoint_id, EZB_ZCL_CLUSTER_ID_IDENTIFY, EZB_ZCL_CLUSTER_SERVER);
231}
232
233void ZigbeeComponent::add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role) {
234 if (cluster_id == EZB_ZCL_CLUSTER_ID_BASIC) {
235 return;
236 }
237 ezb_af_ep_desc_t ep_desc = ezb_af_device_get_endpoint_desc(this->dev_desc_, endpoint_id);
238 if (ep_desc == NULL) {
239 ESP_LOGE(TAG, "Endpoint %u does not exist, cannot add cluster 0x%04X", endpoint_id, cluster_id);
240 return;
241 }
242 esphome_zb_add_or_update_cluster(cluster_id, ep_desc, role);
243 ESP_LOGD(TAG, "Endpoint %u: Added cluster 0x%04X with role %u", endpoint_id, cluster_id, role);
244}
245
246void ZigbeeComponent::set_basic_cluster(const char *model, const char *manufacturer, const char *location,
247 const char *sw_build_id, uint8_t power_source, uint8_t app_version) {
248 char date_buf[16];
249 time_t time_val = App.get_build_time();
250 struct tm *timeinfo = localtime(&time_val);
251 strftime(date_buf, sizeof(date_buf), "%Y%m%d %H%M%S", timeinfo);
252 this->basic_cluster_data_ = {
253 .model = get_zcl_string(model, 31),
254 .manufacturer = get_zcl_string(manufacturer, 31),
255 .date = get_zcl_string(date_buf, 15),
256 .location = get_zcl_string(location, 15),
257 .sw_build_id = get_zcl_string(sw_build_id, 15),
258 .power_source = power_source,
259 .app_version = app_version,
260 };
261}
262
263void ZigbeeComponent::update_basic_cluster_(ezb_af_ep_desc_t ep_desc) {
264 ezb_zcl_cluster_desc_t cluster_desc =
265 ezb_af_endpoint_get_cluster_desc(ep_desc, EZB_ZCL_CLUSTER_ID_BASIC, EZB_ZCL_CLUSTER_SERVER);
266 if (cluster_desc == NULL) {
267 ezb_zcl_basic_cluster_config_t basic_cluster_cfg = {
268 .zcl_version = EZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE,
269 .power_source = this->basic_cluster_data_.power_source,
270 };
271 cluster_desc = ezb_zcl_basic_create_cluster_desc(&basic_cluster_cfg, EZB_ZCL_CLUSTER_SERVER);
272 ezb_af_endpoint_add_cluster_desc(ep_desc, cluster_desc);
273 }
274 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
275 this->basic_cluster_data_.manufacturer);
276 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
277 this->basic_cluster_data_.model);
278 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_DATE_CODE_ID, this->basic_cluster_data_.date);
279 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_APPLICATION_VERSION_ID,
280 &(this->basic_cluster_data_.app_version));
281 uint8_t stack_version = 0;
282 uint8_t hw_version = 0;
283 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_STACK_VERSION_ID, &stack_version);
284 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_HW_VERSION_ID, &hw_version);
285 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_LOCATION_DESCRIPTION_ID,
286 this->basic_cluster_data_.location);
287 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_SW_BUILD_ID_ID,
288 this->basic_cluster_data_.sw_build_id);
289}
290
292 if (ezb_af_device_desc_register(this->dev_desc_) != EZB_ERR_NONE) {
293 ESP_LOGE(TAG, "Could not register the endpoint list");
294 this->mark_failed();
295 return false;
296 }
297 return true;
298}
299
300static void ezb_task(void *pv_parameters) {
301 if (!global_zigbee->register_device()) {
302 vTaskDelete(NULL);
303 return;
304 }
305 if (esp_zigbee_start(false) != ESP_OK) {
306 ESP_LOGE(TAG, "Could not setup Zigbee");
307 global_zigbee->mark_failed();
308 vTaskDelete(NULL);
309 return; // vTaskDelete(NULL) never returns, but keep intent explicit
310 }
311
312 // Increase priority to 5 to align with openthread or BLE
313 vTaskPrioritySet(NULL, 5);
314
315 esp_zigbee_launch_mainloop();
316
317 esp_zigbee_deinit();
318
319 vTaskDelete(NULL);
320}
321
323 global_zigbee = this;
324
325 esp_zigbee_platform_config_t platform_config = {
326 .storage_partition_name = "nvs",
327 .radio_config = EZB_DEFAULT_RADIO_CONFIG(),
328 };
329 esp_zigbee_device_config_t device_config = {
330 .device_type = this->device_role_,
331 .install_code_policy = false,
332 };
333#ifdef CONFIG_ZB_ZCZR
334 esp_zigbee_zczr_config_s zb_zczr_cfg = {
335 .max_children = MAX_CHILDREN,
336 };
337 device_config.zczr_config = zb_zczr_cfg;
338#else
339 esp_zigbee_zed_config_s zb_zed_cfg = {
340 .ed_timeout = EZB_NWK_ED_TIMEOUT_64MIN,
341 .keep_alive = this->keep_alive_,
342 };
343 device_config.zed_config = zb_zed_cfg;
344#endif
345 esp_zigbee_config_t config = {.device_config = device_config, .platform_config = platform_config};
346 if (esp_zigbee_init(&config) != ESP_OK) {
347 ESP_LOGE(TAG, "Could not initialize Zigbee");
348 this->mark_failed();
349 return;
350 }
351
352#ifdef USE_WIFI
353 if (esp_coex_wifi_i154_enable() != ESP_OK) {
354 this->mark_failed();
355 return;
356 }
357#endif
358
359#ifdef CONFIG_ZB_ZCZR
360 ezb_bdb_set_router_rejoin_required(true);
361#else
362 ezb_nwk_set_rx_on_when_idle(!this->sleepy_); // if sleepy, disable RX when idle
363#endif
364
365 ezb_aps_secur_enable_distributed_security(false);
366 ezb_nwk_set_min_join_lqi(32);
367 if (ezb_app_signal_add_handler(ZigbeeComponent::app_signal_handler) != ESP_OK) {
368 ESP_LOGE(TAG, "Could not set application signal handler");
369 this->mark_failed();
370 return;
371 }
372
373 ezb_zcl_core_action_handler_register(zb_action_handler);
374
375 if (ezb_bdb_set_primary_channel_set(EZB_PRIMARY_CHANNEL_MASK) != ESP_OK) {
376 ESP_LOGE(TAG, "Could not setup Zigbee");
377 this->mark_failed();
378 return;
379 }
380
381 uint8_t power_source = static_cast<uint8_t>(this->is_battery_powered() ? EZB_AF_NODE_POWER_SOURCE_RECHARGEABLE_BATTERY
382 : EZB_AF_NODE_POWER_SOURCE_CONSTANT_POWER);
383 ezb_af_node_power_desc_t desc = {
384 .current_power_mode = EZB_AF_NODE_POWER_MODE_SYNC_ON_WHEN_IDLE,
385 .available_power_sources = power_source,
386 .current_power_source = power_source,
387 .current_power_source_level = EZB_AF_NODE_POWER_SOURCE_LEVEL_100_PERCENT,
388 };
389 ezb_af_set_node_power_desc(&desc);
390
391 // Finish zigbee data model
392 for (auto &attr_value : this->attr_values_) {
393 ezb_zcl_attr_desc_t attr_desc = attr_value.attr_desc;
394 void *value_p = &attr_value.value;
395 ezb_zcl_attr_desc_set_value(attr_desc, value_p);
396 }
397 // free memory
398 std::vector<AttrValue>().swap(this->attr_values_);
399
400 // Start the Zigbee task with priority 1 to ensure main loop can still run even if Zigbee is busy
401 xTaskCreate(ezb_task, "Zigbee_main", 4096, NULL, 1, NULL);
402 this->disable_loop(); // loop is only needed for processing events, so disable until we join a network
403}
404
406 // Process all pending events
407 ZBEvent *event = this->zb_events_.pop();
408 while (event != nullptr) {
409 // Handle the event
410 switch (event->callback_id_) {
411 case EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID:
412 this->handle_attribute_(event->event_.set_attr.info, event->event_.set_attr.attribute);
413 break;
414 default:
415 ESP_LOGW(TAG, "Received event with unhandled callback id: 0x%x", static_cast<unsigned>(event->callback_id_));
416 break;
417 }
418
419 // Free the event back to the pool
420 this->zb_event_pool_.release(event);
421 // Get the next event
422 event = this->zb_events_.pop();
423 }
424 // Log dropped events periodically
425 uint16_t dropped = this->zb_events_.get_and_reset_dropped_count();
426 if (dropped > 0) {
427 ESP_LOGW(TAG, "Dropped %u Zigbee events due to buffer overflow", dropped);
428 }
429
430 if (!this->start_reported_ && this->started_) {
431 this->start_cb_.call();
432 this->start_reported_ = true;
433 }
434 if (this->join_pending_.exchange(false)) {
435 this->join_cb_.call(this->factory_new_);
436 this->factory_new_ = false;
437 }
438 this->disable_loop();
439}
440
442 ESP_LOGCONFIG(TAG,
443 "Zigbee\n"
444 " Model: %.*s\n"
445 " Manufacturer: %.*s\n"
446#ifdef CONFIG_ZB_ZCZR
447 " Router: %s\n"
448#else
449 " Sleepy end device: %s\n"
450 " Poll interval: %" PRIu32 " ms\n"
451#endif
452 " App Version: %u",
453 this->basic_cluster_data_.model[0], reinterpret_cast<const char *>(this->basic_cluster_data_.model + 1),
454 this->basic_cluster_data_.manufacturer[0],
455 reinterpret_cast<const char *>(this->basic_cluster_data_.manufacturer + 1),
456#ifdef CONFIG_ZB_ZCZR
457 YESNO(this->device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER),
458#else
459 YESNO(this->sleepy_), this->keep_alive_,
460#endif
461 this->basic_cluster_data_.app_version);
462 if (esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
463 ESP_LOGCONFIG(TAG,
464 " Device is joined to the network: %s\n"
465 " Current channel: %d\n"
466 " Short addr: 0x%04X\n"
467 " Short pan id: 0x%04X",
468 YESNO(ezb_bdb_dev_joined()), ezb_nwk_get_current_channel(), ezb_nwk_get_short_address(),
469 ezb_nwk_get_panid());
470 esp_zigbee_lock_release();
471 }
472}
473
474bool ZigbeeComponent::string_attr_exists_(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id) {
475 ezb_af_ep_desc_t ep_desc = ezb_af_device_get_endpoint_desc(this->dev_desc_, endpoint_id);
476 if (ep_desc == NULL) {
477 return false;
478 }
479 ezb_zcl_cluster_desc_t cluster_desc = ezb_af_endpoint_get_cluster_desc(ep_desc, cluster_id, role);
480 if (cluster_desc == NULL) {
481 return false;
482 }
483 if (ezb_zcl_cluster_get_attr_desc(cluster_desc, attr_id, EZB_ZCL_STD_MANUF_CODE) == NULL) {
484 return false;
485 }
486 ESP_LOGW(TAG, "Attribute 0x%04X already exists in endpoint %u cluster 0x%04X. Can't add new value", attr_id,
487 endpoint_id, cluster_id);
488 return true;
489}
490} // namespace esphome::zigbee
491
492#endif
493#endif
BedjetMode mode
BedJet operating mode.
uint8_t status
Definition bl0942.h:8
time_t get_build_time()
Get the build time as a Unix timestamp.
void mark_failed()
Mark this component as failed.
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
void disable_loop()
Disable this component's loop.
ezb_zcl_core_action_callback_id_t callback_id_
struct esphome::zigbee::ZBEvent::@207::set_attr_event set_attr
union esphome::zigbee::ZBEvent::@207 event_
std::vector< AttrValue > attr_values_
CallbackManager< void(bool)> join_cb_
struct esphome::zigbee::ZigbeeComponent::@206 basic_cluster_data_
bool string_attr_exists_(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role, uint16_t attr_id)
void create_default_cluster(uint8_t endpoint_id, uint16_t device_id)
std::atomic< bool > factory_new_
void handle_attribute_(ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute)
esphome::LockFreeQueue< ZBEvent, MAX_ZB_QUEUE_SIZE > zb_events_
std::map< std::tuple< uint8_t, uint16_t, uint8_t, uint16_t >, ZigbeeAttribute * > attributes_
void update_basic_cluster_(ezb_af_ep_desc_t ep_desc)
void add_cluster(uint8_t endpoint_id, uint16_t cluster_id, uint8_t role)
static void esp_zigbee_alarm_bdb_commissioning(ezb_bdb_comm_mode_mask_t mode)
LazyCallbackManager< void()> start_cb_
static bool app_signal_handler(const ezb_app_signal_t *app_signal)
std::atomic< bool > join_pending_
ezb_nwk_device_type_t device_role_
void set_basic_cluster(const char *model, const char *manufacturer, const char *location, const char *sw_build_id, uint8_t power_source, uint8_t app_version)
esphome::EventPool< ZBEvent, MAX_ZB_QUEUE_SIZE - 1 > zb_event_pool_
ezb_af_device_desc_t dev_desc_
const LogString * message
Definition component.cpp:35
void load_zb_event(ZBEvent *event, ezb_zcl_message_info_t info, ezb_zcl_attribute_t attribute)
uint8_t * get_zcl_string(const char *str, uint8_t max_size, bool use_max_size)
ESPHOME_LOG_TAG(TAG, "zigbee.time")
void enqueue_zb_event(Args... args)
Application App
Global storage of Application pointer - only one Application can exist.
struct tm * localtime(const time_t *timer)
Definition posix_tz.cpp:304
static void uint32_t
ezb_err_t esphome_zb_add_or_update_cluster(uint16_t cluster_id, ezb_af_ep_desc_t ep_desc, uint8_t role_mask)
ezb_af_ep_desc_t esphome_zb_zha_default_ep_desc_create(uint8_t ep_id, uint16_t device_id, uint8_t power_source)