Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e2915c4

Browse filesBrowse files
feat(zigbee): Save network channel after 1st joining for faster rejoin (espressif#11123)
* feat(zigbee): Save network channel after 1st joining for faster rejoin * ci(pre-commit): Apply automatic fixes * feat(zigbee): Add channel mask reset after timeout * feat(zigbee): Add the resetChannelMask to all Begin methods * feaz(zigbee): Move function to private and add set method * fix(example): Remove test from device mode name * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 8e62997 commit e2915c4
Copy full SHA for e2915c4

File tree

Expand file treeCollapse file tree

4 files changed

+55
-9
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+55
-9
lines changed

‎libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino

Copy file name to clipboardExpand all lines: libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void setup() {
7777
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
7878

7979
// Optional: set Zigbee device name and model
80-
zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensorTest");
80+
zbTempSensor.setManufacturerAndModel("Espressif", "SleepyZigbeeTempSensor");
8181

8282
// Set minimum and maximum temperature measurement value (10-50°C is default range for chip temperature measurement)
8383
zbTempSensor.setMinMaxValue(10, 50);
@@ -99,11 +99,15 @@ void setup() {
9999
esp_zb_cfg_t zigbeeConfig = ZIGBEE_DEFAULT_ED_CONFIG();
100100
zigbeeConfig.nwk_cfg.zed_cfg.keep_alive = 10000;
101101

102+
// For battery powered devices, it can be better to set timeout for Zigbee Begin to lower value to save battery
103+
// If the timeout has been reached, the network channel mask will be reset and the device will try to connect again after reset (scanning all channels)
104+
Zigbee.setTimeout(10000); // Set timeout for Zigbee Begin to 10s (default is 30s)
105+
102106
// When all EPs are registered, start Zigbee in End Device mode
103107
if (!Zigbee.begin(&zigbeeConfig, false)) {
104108
Serial.println("Zigbee failed to start!");
105109
Serial.println("Rebooting...");
106-
ESP.restart();
110+
ESP.restart(); // If Zigbee failed to start, reboot the device and try again
107111
}
108112
Serial.println("Connecting to network");
109113
while (!Zigbee.connected()) {

‎libraries/Zigbee/src/ZigbeeCore.cpp

Copy file name to clipboardExpand all lines: libraries/Zigbee/src/ZigbeeCore.cpp
+38-5Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@
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);
1219
static bool edBatteryPowered = false;
1320

1421
ZigbeeCore::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
487520
const char *ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) {
488521
switch (deviceId) {

‎libraries/Zigbee/src/ZigbeeCore.h

Copy file name to clipboardExpand all lines: libraries/Zigbee/src/ZigbeeCore.h
+10-2Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ typedef enum {
2828
#define ZB_SCAN_RUNNING (-1)
2929
#define ZB_SCAN_FAILED (-2)
3030

31+
#define ZB_BEGIN_TIMEOUT_DEFAULT 30000 // 30 seconds
32+
3133
#define ZIGBEE_DEFAULT_ED_CONFIG() \
3234
{ \
3335
.esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, .install_code_policy = false, \
@@ -85,6 +87,7 @@ class ZigbeeCore {
8587
esp_zb_radio_config_t _radio_config;
8688
esp_zb_host_config_t _host_config;
8789
uint32_t _primary_channel_mask;
90+
uint32_t _begin_timeout;
8891
int16_t _scan_status;
8992
uint8_t _scan_duration;
9093
bool _rx_on_when_idle;
@@ -103,6 +106,8 @@ class ZigbeeCore {
103106
const char *getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId);
104107
void searchBindings();
105108
static void bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx);
109+
void resetNVRAMChannelMask(); // Reset to default mask also in NVRAM
110+
void setNVRAMChannelMask(uint32_t mask); // Set channel mask in NVRAM
106111

107112
public:
108113
ZigbeeCore();
@@ -134,7 +139,8 @@ class ZigbeeCore {
134139
esp_zb_host_config_t getHostConfig();
135140

136141
void setPrimaryChannelMask(uint32_t mask); // By default all channels are scanned (11-26) -> mask 0x07FFF800
137-
void setScanDuration(uint8_t duration); // Can be set from 1 - 4. 1 is fastest, 4 is slowest
142+
143+
void setScanDuration(uint8_t duration); // Can be set from 1 - 4. 1 is fastest, 4 is slowest
138144
uint8_t getScanDuration() {
139145
return _scan_duration;
140146
}
@@ -145,7 +151,9 @@ class ZigbeeCore {
145151
bool getRxOnWhenIdle() {
146152
return _rx_on_when_idle;
147153
}
148-
154+
void setTimeout(uint32_t timeout) {
155+
_begin_timeout = timeout;
156+
}
149157
void setRebootOpenNetwork(uint8_t time);
150158
void openNetwork(uint8_t time);
151159

‎libraries/Zigbee/src/ZigbeeEP.cpp

Copy file name to clipboardExpand all lines: libraries/Zigbee/src/ZigbeeEP.cpp
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ void ZigbeeEP::reportBatteryPercentage() {
104104
report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI;
105105
report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG;
106106
report_attr_cmd.zcl_basic_cmd.src_endpoint = _endpoint;
107+
report_attr_cmd.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC;
107108

108109
esp_zb_lock_acquire(portMAX_DELAY);
109110
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.