66#include " ZigbeeHandlers.cpp"
77#include " Arduino.h"
88
9- #define ZB_INIT_TIMEOUT 30000 // 30 seconds
9+ #ifdef __cplusplus
10+ extern " C" {
11+ #endif
12+ #include " zboss_api.h"
13+ extern zb_ret_t zb_nvram_write_dataset (zb_nvram_dataset_types_t t); // rejoin scanning workaround
14+ extern void zb_set_ed_node_descriptor (bool power_src, bool rx_on_when_idle, bool alloc_addr); // sleepy device power mode workaround
15+ #ifdef __cplusplus
16+ }
17+ #endif
1018
11- extern " C" void zb_set_ed_node_descriptor (bool power_src, bool rx_on_when_idle, bool alloc_addr);
1219static bool edBatteryPowered = false ;
1320
1421ZigbeeCore::ZigbeeCore () {
@@ -18,6 +25,7 @@ ZigbeeCore::ZigbeeCore() {
1825 _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK;
1926 _open_network = 0 ;
2027 _scan_status = ZB_SCAN_FAILED;
28+ _begin_timeout = ZB_BEGIN_TIMEOUT_DEFAULT;
2129 _started = false ;
2230 _connected = false ;
2331 _scan_duration = 3 ; // default scan duration
@@ -39,8 +47,11 @@ bool ZigbeeCore::begin(esp_zb_cfg_t *role_cfg, bool erase_nvs) {
3947 return false ;
4048 }
4149 _role = (zigbee_role_t )role_cfg->esp_zb_role ;
42- if (xSemaphoreTake (lock, ZB_INIT_TIMEOUT) != pdTRUE) {
43- log_e (" ZigbeeCore begin timeout" );
50+ if (xSemaphoreTake (lock, _begin_timeout) != pdTRUE) {
51+ log_e (" ZigbeeCore begin failed or timeout" );
52+ if (_role != ZIGBEE_COORDINATOR) { // Only End Device and Router can rejoin
53+ resetNVRAMChannelMask ();
54+ }
4455 }
4556 return started ();
4657}
@@ -71,8 +82,11 @@ bool ZigbeeCore::begin(zigbee_role_t role, bool erase_nvs) {
7182 }
7283 default : log_e (" Invalid Zigbee Role" ); return false ;
7384 }
74- if (!status || xSemaphoreTake (lock, ZB_INIT_TIMEOUT ) != pdTRUE) {
85+ if (!status || xSemaphoreTake (lock, _begin_timeout ) != pdTRUE) {
7586 log_e (" ZigbeeCore begin failed or timeout" );
87+ if (_role != ZIGBEE_COORDINATOR) { // Only End Device and Router can rejoin
88+ resetNVRAMChannelMask ();
89+ }
7690 }
7791 return started ();
7892}
@@ -220,6 +234,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
220234 switch (sig_type) {
221235 case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: // Common
222236 log_i (" Zigbee stack initialized" );
237+ log_d (" Zigbee channel mask: 0x%08x" , esp_zb_get_channel_mask ());
223238 esp_zb_bdb_start_top_level_commissioning (ESP_ZB_BDB_MODE_INITIALIZATION);
224239 break ;
225240 case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Common
@@ -245,6 +260,8 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
245260 log_i (" Opening network for joining for %d seconds" , Zigbee._open_network );
246261 esp_zb_bdb_open_network (Zigbee._open_network );
247262 } else {
263+ // Save the channel mask to NVRAM in case of reboot which may be on a different channel after a change in the network
264+ Zigbee.setNVRAMChannelMask (1 << esp_zb_get_current_channel ());
248265 Zigbee._connected = true ;
249266 }
250267 Zigbee.searchBindings ();
@@ -289,6 +306,8 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) {
289306 extended_pan_id[0 ], esp_zb_get_pan_id (), esp_zb_get_current_channel (), esp_zb_get_short_address ()
290307 );
291308 Zigbee._connected = true ;
309+ // Set channel mask and write to NVRAM, so that the device will re-join the network faster after reboot (scan only on the current channel)
310+ Zigbee.setNVRAMChannelMask (1 << esp_zb_get_current_channel ());
292311 } else {
293312 log_i (" Network steering was not successful (status: %s)" , esp_err_to_name (err_status));
294313 esp_zb_scheduler_alarm ((esp_zb_callback_t )bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000 );
@@ -483,6 +502,20 @@ void ZigbeeCore::searchBindings() {
483502 esp_zb_zdo_binding_table_req (mb_req, bindingTableCb, (void *)mb_req);
484503}
485504
505+ void ZigbeeCore::resetNVRAMChannelMask () {
506+ _primary_channel_mask = ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK;
507+ esp_zb_set_channel_mask (_primary_channel_mask);
508+ zb_nvram_write_dataset (ZB_NVRAM_COMMON_DATA);
509+ log_v (" Channel mask reset to all channels" );
510+ }
511+
512+ void ZigbeeCore::setNVRAMChannelMask (uint32_t mask) {
513+ _primary_channel_mask = mask;
514+ esp_zb_set_channel_mask (_primary_channel_mask);
515+ zb_nvram_write_dataset (ZB_NVRAM_COMMON_DATA);
516+ log_v (" Channel mask set to 0x%08x" , mask);
517+ }
518+
486519// Function to convert enum value to string
487520const char *ZigbeeCore::getDeviceTypeString (esp_zb_ha_standard_devices_t deviceId) {
488521 switch (deviceId) {
0 commit comments