5#include "freertos/FreeRTOS.h"
6#include "freertos/task.h"
15#include "esp_coexist.h"
20static const char *
const TAG =
"zigbee";
22static ZigbeeComponent *global_zigbee =
nullptr;
24uint8_t *
get_zcl_string(
const char *str, uint8_t max_size,
bool use_max_size) {
25 uint8_t str_len =
static_cast<uint8_t
>(strlen(str));
26 uint8_t zcl_str_size = use_max_size ? max_size : std::min(max_size, str_len);
27 uint8_t *zcl_str =
new uint8_t[zcl_str_size + 1];
28 zcl_str[0] = zcl_str_size;
31 memset(zcl_str + 1, 0, zcl_str_size);
32 uint8_t copy_len = std::min(zcl_str_size, str_len);
34 memcpy(zcl_str + 1, str, copy_len);
40 esp_zigbee_lock_acquire(portMAX_DELAY);
43 ezb_bdb_reset_via_local_action();
45 esp_zigbee_factory_reset();
47 esp_zigbee_lock_release();
51 if (!esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
55 if (ezb_bdb_start_top_level_commissioning(
mode) != EZB_ERR_NONE) {
56 ESP_LOGE(TAG,
"Start top level commissioning failed!");
58 esp_zigbee_lock_release();
62 static uint8_t steering_retry_count = 0;
63 ezb_app_signal_type_t signal_type = ezb_app_signal_get_type(app_signal);
64 switch (signal_type) {
65 case EZB_ZDO_SIGNAL_SKIP_STARTUP:
66 ESP_LOGD(TAG,
"Zigbee stack initialized");
69 ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_INITIALIZATION);
71 case EZB_BDB_SIGNAL_DEVICE_FIRST_START:
72 case EZB_BDB_SIGNAL_DEVICE_REBOOT: {
73 ezb_bdb_comm_status_t
status = *((ezb_bdb_comm_status_t *) ezb_app_signal_get_params(app_signal));
74 if (
status == EZB_BDB_STATUS_SUCCESS) {
75 ESP_LOGD(TAG,
"Device started up in %sfactory-reset mode", ezb_bdb_is_factory_new() ?
"" :
"non ");
76 if (ezb_bdb_is_factory_new()) {
78 ESP_LOGD(TAG,
"Start network steering");
79 ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
81 ESP_LOGD(TAG,
"Device rebooted");
87 ESP_LOGW(TAG,
"The %s failed with status(0x%02x), please retry", ezb_app_signal_to_string(signal_type),
status);
93 case EZB_BDB_SIGNAL_STEERING: {
94 ezb_bdb_comm_status_t
status = *((ezb_bdb_comm_status_t *) ezb_app_signal_get_params(app_signal));
95 if (
status == EZB_BDB_STATUS_SUCCESS) {
96 steering_retry_count = 0;
97 ezb_extpanid_t extended_pan_id;
98 ezb_nwk_get_extended_panid(&extended_pan_id);
99 ESP_LOGD(TAG,
"Joined network successfully: PAN ID(0x%04hx, EXT: 0x%llx), Channel(%d), Short Address(0x%04hx)",
100 ezb_nwk_get_panid(), extended_pan_id.u64, ezb_nwk_get_current_channel(), ezb_nwk_get_short_address());
105 ESP_LOGD(TAG,
"Failed to join network with status(0x%02x)",
status);
106 if (steering_retry_count < 10) {
107 steering_retry_count++;
112 global_zigbee->
set_timeout(
"zb_init", 600 * 1000, []() {
118 case EZB_ZDO_SIGNAL_LEAVE: {
119 const ezb_zdo_signal_leave_params_t *leave_params =
120 (
const ezb_zdo_signal_leave_params_t *) ezb_app_signal_get_params(app_signal);
121 if (leave_params->leave_type == EZB_ZDO_LEAVE_TYPE_RESET) {
122 esp_zigbee_factory_reset();
124 global_zigbee->
joined_ =
false;
126 case EZB_NWK_SIGNAL_NETWORK_STATUS: {
127 const ezb_nwk_signal_network_status_params_t *network_status_params =
128 (
const ezb_nwk_signal_network_status_params_t *) ezb_app_signal_get_params(app_signal);
129 if (network_status_params->status == EZB_NWK_NETWORK_STATUS_PARENT_LINK_FAILURE) {
130 global_zigbee->
joined_ =
false;
131 ESP_LOGW(TAG,
"Parent link failure, attempting rejoin");
132 ezb_zdo_nwk_mgmt_leave_req_t leave_req = {
133 .dst_nwk_addr = ezb_nwk_get_short_address(),
136 .remove_children =
false,
142 ezb_zdo_nwk_mgmt_leave_req(&leave_req);
144 ESP_LOGD(TAG,
"Zigbee APP Signal NETWORK_STATUS: 0x%02x", network_status_params->status);
148 ESP_LOGD(TAG,
"Zigbee APP Signal: %s(type: 0x%02x)", ezb_app_signal_to_string(signal_type), signal_type);
154static void zb_attribute_handler(ezb_zcl_set_attr_value_message_t *
message) {
155 ESP_RETURN_ON_FALSE(
message, , TAG,
"Empty message");
156 ESP_RETURN_ON_FALSE(
message->info.status == EZB_ZCL_STATUS_SUCCESS, , TAG,
"Received message: error status(%d)",
158 ESP_LOGD(TAG,
"ZCL SetAttributeValue message for endpoint(%d) cluster(0x%04x) %s with status(0x%02x)",
160 message->info.cluster_role == EZB_ZCL_CLUSTER_SERVER ?
"server" :
"client",
message->info.status);
163static void zb_action_handler(ezb_zcl_core_action_callback_id_t callback_id,
void *
message) {
164 switch (callback_id) {
165 case EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID:
166 zb_attribute_handler((ezb_zcl_set_attr_value_message_t *)
message);
168 case EZB_ZCL_CORE_DEFAULT_RSP_CB_ID: {
169#ifdef ESPHOME_LOG_HAS_VERBOSE
170 ezb_zcl_cmd_default_rsp_message_t *default_rsp = (ezb_zcl_cmd_default_rsp_message_t *)
message;
171 ESP_LOGV(TAG,
"Received ZCL Default Response: 0x%02x", default_rsp->in.status_code);
175 ESP_LOGD(TAG,
"Receive Zigbee action(0x%04x) callback",
static_cast<unsigned>(callback_id));
181 ezb_af_ep_config_t config = {
182 .ep_id = endpoint_id,
183 .app_profile_id = EZB_AF_HA_PROFILE_ID,
184 .app_device_id = device_id,
185 .app_device_version = 0,
187 ezb_af_ep_desc_t ep_desc = ezb_af_create_endpoint_desc(&config);
188 if (ezb_af_device_add_endpoint_desc(this->
dev_desc_, ep_desc) != EZB_ERR_NONE) {
189 ESP_LOGE(TAG,
"Could not create endpoint %u", endpoint_id);
194 this->
add_cluster(endpoint_id, EZB_ZCL_CLUSTER_ID_IDENTIFY, EZB_ZCL_CLUSTER_SERVER);
198 if (cluster_id == EZB_ZCL_CLUSTER_ID_BASIC) {
201 ezb_af_ep_desc_t ep_desc = ezb_af_device_get_endpoint_desc(this->
dev_desc_, endpoint_id);
202 if (ep_desc == NULL) {
203 ESP_LOGE(TAG,
"Endpoint %u does not exist, cannot add cluster 0x%04X", endpoint_id, cluster_id);
207 ESP_LOGD(TAG,
"Endpoint %u: Added cluster 0x%04X with role %u", endpoint_id, cluster_id, role);
213 struct tm *timeinfo =
localtime(&time_val);
214 strftime(date_buf,
sizeof(date_buf),
"%Y%m%d %H%M%S", timeinfo);
224 ezb_zcl_cluster_desc_t cluster_desc =
225 ezb_af_endpoint_get_cluster_desc(ep_desc, EZB_ZCL_CLUSTER_ID_BASIC, EZB_ZCL_CLUSTER_SERVER);
226 if (cluster_desc == NULL) {
227 ezb_zcl_basic_cluster_config_t basic_cluster_cfg = {
228 .zcl_version = EZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE,
231 cluster_desc = ezb_zcl_basic_create_cluster_desc(&basic_cluster_cfg, EZB_ZCL_CLUSTER_SERVER);
233 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
235 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
237 ezb_zcl_basic_cluster_desc_add_attr(cluster_desc, EZB_ZCL_ATTR_BASIC_DATE_CODE_ID, this->
basic_cluster_data_.date);
238 ezb_af_endpoint_add_cluster_desc(ep_desc, cluster_desc);
242 if (ezb_af_device_desc_register(this->
dev_desc_) != EZB_ERR_NONE) {
243 ESP_LOGE(TAG,
"Could not register the endpoint list");
250static void ezb_task(
void *pv_parameters) {
255 if (esp_zigbee_start(
false) != ESP_OK) {
256 ESP_LOGE(TAG,
"Could not setup Zigbee");
263 vTaskPrioritySet(NULL, 5);
265 esp_zigbee_launch_mainloop();
273 esp_zigbee_platform_config_t platform_config = {
274 .storage_partition_name =
"nvs",
275 .radio_config = EZB_DEFAULT_RADIO_CONFIG(),
277 esp_zigbee_device_config_t device_config = {
279 .install_code_policy =
false,
282 esp_zigbee_zczr_config_s zb_zczr_cfg = {
283 .max_children = MAX_CHILDREN,
285 device_config.zczr_config = zb_zczr_cfg;
287 esp_zigbee_zed_config_s zb_zed_cfg = {
288 .ed_timeout = EZB_NWK_ED_TIMEOUT_64MIN,
289 .keep_alive = ED_KEEP_ALIVE,
291 device_config.zed_config = zb_zed_cfg;
293 esp_zigbee_config_t config = {.device_config = device_config, .platform_config = platform_config};
294 if (esp_zigbee_init(&config) != ESP_OK) {
295 ESP_LOGE(TAG,
"Could not initialize Zigbee");
299 this->
dev_desc_ = ezb_af_create_device_desc();
303 global_zigbee =
this;
305 if (esp_coex_wifi_i154_enable() != ESP_OK) {
312 ezb_bdb_set_router_rejoin_required(
true);
315 ezb_aps_secur_enable_distributed_security(
false);
316 ezb_nwk_set_min_join_lqi(32);
318 ESP_LOGE(TAG,
"Could not set application signal handler");
323 ezb_zcl_core_action_handler_register(zb_action_handler);
325 if (ezb_bdb_set_primary_channel_set(EZB_PRIMARY_CHANNEL_MASK) != ESP_OK) {
326 ESP_LOGE(TAG,
"Could not setup Zigbee");
332 : EZB_AF_NODE_POWER_SOURCE_CONSTANT_POWER);
333 ezb_af_node_power_desc_t desc = {
334 .current_power_mode = EZB_AF_NODE_POWER_MODE_SYNC_ON_WHEN_IDLE,
337 .current_power_source_level = EZB_AF_NODE_POWER_SOURCE_LEVEL_100_PERCENT,
339 ezb_af_set_node_power_desc(&desc);
342 xTaskCreate(ezb_task,
"Zigbee_main", 4096, NULL, 1, NULL);
359 if (esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
364 " Device is joined to the network: %s\n"
365 " Current channel: %d\n"
366 " Short addr: 0x%04X\n"
367 " Short pan id: 0x%04X",
369 reinterpret_cast<const char *
>(this->basic_cluster_data_.model + 1),
370 YESNO(this->
device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER), YESNO(ezb_bdb_dev_joined()),
371 ezb_nwk_get_current_channel(), ezb_nwk_get_short_address(), ezb_nwk_get_panid());
372 esp_zigbee_lock_release();
379 reinterpret_cast<const char *
>(this->basic_cluster_data_.model + 1),
380 YESNO(this->
device_role_ == EZB_NWK_DEVICE_TYPE_ROUTER));
BedjetMode mode
BedJet operating mode.
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.
void disable_loop()
Disable this component's loop.
struct esphome::zigbee::ZigbeeComponent::@202 basic_cluster_data_
CallbackManager< void(bool)> join_cb_
bool is_battery_powered()
void create_default_cluster(uint8_t endpoint_id, uint16_t device_id)
std::atomic< bool > factory_new_
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 > joined_
std::atomic< bool > started_
std::atomic< bool > join_pending_
ezb_nwk_device_type_t device_role_
void dump_config() override
void set_basic_cluster(const char *model, const char *manufacturer, uint8_t power_source)
ezb_af_device_desc_t dev_desc_
const LogString * message
uint8_t * get_zcl_string(const char *str, uint8_t max_size, bool use_max_size)
Application App
Global storage of Application pointer - only one Application can exist.
struct tm * localtime(const time_t *timer)
ezb_err_t esphome_zb_add_or_update_cluster(uint16_t cluster_id, ezb_af_ep_desc_t ep_desc, uint8_t role_mask)