Skip to content

Commit 3afddfc

Browse files
authored
Merge branch 'espressif:master' into master
2 parents a9f6400 + e2915c4 commit 3afddfc

File tree

4 files changed

+55
-9
lines changed

4 files changed

+55
-9
lines changed

libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino

+6-2
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

+38-5
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

+10-2
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

+1
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)