2#if defined(USE_ZIGBEE) && defined(USE_NRF52)
5#include <zephyr/settings/settings.h>
6#include <zephyr/storage/flash_map.h>
11#include <zboss_api_addons.h>
12#include <zb_nrf_platform.h>
13#include <zigbee/zigbee_app_utils.h>
14#include <zb_error_to_string.h>
19static const char *
const TAG =
"zigbee";
21ZigbeeComponent *global_zigbee =
nullptr;
26 zb_zdo_app_signal_hdr_t *sig_hndler =
nullptr;
27 zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &sig_hndler);
28 zb_ret_t
status = ZB_GET_APP_SIGNAL_STATUS(bufid);
31 case ZB_ZDO_SIGNAL_SKIP_STARTUP:
32 ESP_LOGD(TAG,
"ZB_ZDO_SIGNAL_SKIP_STARTUP, status: %d",
status);
37 case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
38 ESP_LOGD(TAG,
"ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY, status: %d",
status);
40 case ZB_ZDO_SIGNAL_LEAVE:
41 ESP_LOGD(TAG,
"ZB_ZDO_SIGNAL_LEAVE, status: %d",
status);
43 case ZB_BDB_SIGNAL_DEVICE_REBOOT:
44 ESP_LOGD(TAG,
"ZB_BDB_SIGNAL_DEVICE_REBOOT, status: %d",
status);
49 case ZB_BDB_SIGNAL_STEERING:
51 case ZB_COMMON_SIGNAL_CAN_SLEEP:
52 ESP_LOGV(TAG,
"ZB_COMMON_SIGNAL_CAN_SLEEP, status: %d",
status);
54 case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
55 ESP_LOGD(TAG,
"ZB_BDB_SIGNAL_DEVICE_FIRST_START, status: %d",
status);
57 case ZB_NLME_STATUS_INDICATION:
58 ESP_LOGD(TAG,
"ZB_NLME_STATUS_INDICATION, status: %d",
status);
60 case ZB_BDB_SIGNAL_TC_REJOIN_DONE:
61 ESP_LOGD(TAG,
"ZB_BDB_SIGNAL_TC_REJOIN_DONE, status: %d",
status);
64 ESP_LOGD(TAG,
"zboss_signal_handler sig: %d, status: %d", sig,
status);
69 auto err = zigbee_default_signal_handler(bufid);
71 ESP_LOGE(TAG,
"Zigbee_default_signal_handler ERROR %u [%s]", err, zb_error_to_string_get(err));
74 if (sig == ZB_COMMON_SIGNAL_CAN_SLEEP) {
82 case ZB_BDB_SIGNAL_STEERING:
83 ESP_LOGD(TAG,
"ZB_BDB_SIGNAL_STEERING, status: %d",
status);
85 zb_ext_pan_id_t extended_pan_id;
89 zb_get_extended_pan_id(extended_pan_id);
90 addr_len = ieee_addr_to_str(ieee_addr_buf,
sizeof(ieee_addr_buf), extended_pan_id);
93 if (ieee_addr_buf[i] !=
'0') {
111 zb_zcl_device_callback_param_t *p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);
112 zb_zcl_device_callback_id_t device_cb_id = p_device_cb_param->device_cb_id;
113 zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id;
114 zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id;
115 auto endpoint = p_device_cb_param->endpoint;
117 ESP_LOGI(TAG,
"%s id %hd, cluster_id %d, attr_id %d, endpoint: %d", __func__, device_cb_id, cluster_id, attr_id,
121 p_device_cb_param->status = RET_OK;
126 if (global_zigbee->callbacks_.size() >= endpoint) {
127 const auto &cb = global_zigbee->callbacks_[endpoint - 1];
133 p_device_cb_param->status = RET_NOT_IMPLEMENTED;
137 this->
defer([
this, factory_new]() {
138 ESP_LOGD(TAG,
"Joined the network");
145 this->
defer([
this]() {
146 ESP_LOGD(TAG,
"Started zigbee stack");
152#ifdef USE_ZIGBEE_WIPE_ON_BOOT
154 const struct flash_area *fap;
155 flash_area_open(area, &fap);
156 flash_area_erase(fap, 0, fap->fa_size);
157 flash_area_close(fap);
162 global_zigbee =
this;
163 auto err = settings_subsys_init();
165 ESP_LOGE(TAG,
"Failed to initialize settings subsystem, err: %d", err);
169#ifdef USE_ZIGBEE_WIPE_ON_BOOT
171#ifdef USE_ZIGBEE_WIPE_ON_BOOT_MAGIC
176 if (wipe_pref.load(&wipe_value)) {
177 wipe = wipe_value != USE_ZIGBEE_WIPE_ON_BOOT_MAGIC;
178 ESP_LOGD(TAG,
"Wipe value in preferences %u, in firmware %u", wipe_value, USE_ZIGBEE_WIPE_ON_BOOT_MAGIC);
185#ifdef USE_ZIGBEE_WIPE_ON_BOOT_MAGIC
186 wipe_value = USE_ZIGBEE_WIPE_ON_BOOT_MAGIC;
187 wipe_pref.save(&wipe_value);
193 err = settings_load();
195 ESP_LOGE(TAG,
"Cannot load settings, err: %d", err);
198#ifdef CONFIG_ZIGBEE_ROLE_END_DEVICE
199 zigbee_configure_sleepy_behavior(this->
sleepy_);
204#ifdef ESPHOME_LOG_HAS_CONFIG
205static const char *role() {
206 switch (zb_get_network_role()) {
207 case ZB_NWK_DEVICE_TYPE_COORDINATOR:
208 return "coordinator";
209 case ZB_NWK_DEVICE_TYPE_ROUTER:
211 case ZB_NWK_DEVICE_TYPE_ED:
217static const char *get_wipe_on_boot() {
218#ifdef USE_ZIGBEE_WIPE_ON_BOOT
219#ifdef USE_ZIGBEE_WIPE_ON_BOOT_MAGIC
233 zb_get_long_address(addr);
234 ieee_addr_to_str(ieee_addr_buf,
sizeof(ieee_addr_buf), addr);
235 zb_ext_pan_id_t extended_pan_id;
237 zb_get_extended_pan_id(extended_pan_id);
238 ieee_addr_to_str(extended_pan_id_buf,
sizeof(extended_pan_id_buf), extended_pan_id);
241 " Wipe on boot: %s\n"
242 " Device is joined to the network: %s\n"
244 " Radio sleep time: %us\n"
245 " RX ON when idle: %s\n"
246 " Current channel: %d\n"
247 " Current page: %d\n"
248 " Sleep threshold: %ums\n"
251 " Short addr: 0x%04X\n"
252 " Long pan id: 0x%s\n"
253 " Short pan id: 0x%04X",
255 YESNO(zb_get_rx_on_when_idle()), zb_get_current_channel(), zb_get_current_page(),
256 zb_get_sleep_threshold(), role(), ieee_addr_buf, zb_get_short_address(), extended_pan_id_buf,
261static void send_attribute_report(zb_bufid_t bufid, zb_uint16_t cmd_id) {
262 ESP_LOGD(TAG,
"Force zboss scheduler to wake and send attribute report");
278 zb_buf_get_out_delayed_ext(send_attribute_report, 0, 0);
283 ESP_LOGD(TAG,
"Factory reset");
284 ZB_SCHEDULE_APP_CALLBACK(zb_bdb_reset_via_local_action, 0);
287static void log_reporting_info(zb_zcl_reporting_info_t *rep_info) {
289 ESP_LOGD(TAG,
"Reporting: endpoint %d, cluster_id 0x%04X, attr_id 0x%04X, flags 0x%02X, report in %ums", rep_info->ep,
290 rep_info->cluster_id, rep_info->attr_id, rep_info->flags,
291 ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED)
292 ? ZB_TIME_BEACON_INTERVAL_TO_MSEC(rep_info->run_time) - now
294 ESP_LOGD(TAG,
" min_interval %ds, max_interval %ds, def_min_interval %ds, def_max_interval %ds",
295 rep_info->u.send_info.min_interval, rep_info->u.send_info.max_interval,
296 rep_info->u.send_info.def_min_interval, rep_info->u.send_info.def_max_interval);
300#ifdef ESPHOME_LOG_HAS_VERBOSE
301 for (zb_uint8_t j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) {
302 if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) {
303 zb_zcl_reporting_info_t *rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info;
304 for (zb_uint8_t i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) {
305 log_reporting_info(rep_info);
314 zb_zcl_attr_addr_info_t *attr_addr_info) {
315#ifdef ESPHOME_LOG_HAS_DEBUG
317 zb_zcl_find_reporting_info_manuf(attr_addr_info->src_ep, attr_addr_info->cluster_id, attr_addr_info->cluster_role,
318 config_rep_req->attr_id, attr_addr_info->manuf_code);
319 if (rep_info ==
nullptr) {
321 "Failed to resolve reporting info (src_ep=%u cluster_id=0x%04x role=%u attr_id=0x%04x manuf_code=0x%04x)",
322 attr_addr_info->src_ep, attr_addr_info->cluster_id, attr_addr_info->cluster_role, config_rep_req->attr_id,
323 attr_addr_info->manuf_code);
326 log_reporting_info(rep_info);
343 zb_zcl_attr_addr_info_t *attr_addr_info);
346 zb_zcl_attr_addr_info_t *attr_addr_info) {
355 zb_uint8_t current_channel);
357static uint32_t radio_sleep_start_ms = 0;
359static void stop_radio_sleep_timer() {
360 if (radio_sleep_start_ms) {
363 radio_sleep_start_ms = 0;
372 stop_radio_sleep_timer();
377 zb_uint8_t current_channel) {
378 stop_radio_sleep_timer();
void wake_loop_threadsafe()
Wake the main event loop from another thread or callback.
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
void after_reporting_info(zb_zcl_configure_reporting_req_t *config_rep_req, zb_zcl_attr_addr_info_t *attr_addr_info)
CallbackManager< void(bool)> join_cb_
uint32_t radio_sleep_remainder_
static void zcl_device_cb(zb_bufid_t bufid)
LazyCallbackManager< void()> start_cb_
void erase_flash_(int area)
void on_join_(bool factory_new)
uint32_t sleep_remainder_
void zboss_signal_handler_esphome(zb_bufid_t bufid)
void dump_config() override
void add_radio_sleep_time_ms(uint32_t ms)
uint32_t radio_sleep_time_
const uint8_t IEEE_ADDR_BUF_SIZE
ESPPreferences * global_preferences
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
ESPPreferenceObject make_preference(size_t, uint32_t, bool)
void __real_zb_trans_enter_receive(void)
zb_bool_t __wrap_zb_trans_transmit(zb_uint8_t wait_type, zb_time_t tx_at, zb_uint8_t *tx_buf, zb_uint8_t current_channel)
zb_ret_t __wrap_zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, zb_zcl_attr_addr_info_t *attr_addr_info)
void zb_osif_serial_init()
zb_bool_t __real_zb_trans_transmit(zb_uint8_t wait_type, zb_time_t tx_at, zb_uint8_t *tx_buf, zb_uint8_t current_channel)
void zb_osif_serial_flush()
void __wrap_zb_trans_enter_receive(void)
void __real_zb_trans_enter_sleep(void)
void zboss_signal_handler(zb_uint8_t param)
zb_ret_t __real_zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, zb_zcl_attr_addr_info_t *attr_addr_info)
void zb_osif_serial_put_bytes(const zb_uint8_t *buf, zb_short_t len)
void __wrap_zb_trans_enter_sleep(void)