mirror of
https://github.com/esphome/esphome.git
synced 2026-08-17 10:52:56 +08:00
[zigbee] Improve network handling on esp32 (2/3) (#18008)
This commit is contained in:
@@ -36,6 +36,17 @@ uint8_t *get_zcl_string(const char *str, uint8_t max_size, bool use_max_size) {
|
||||
return zcl_str;
|
||||
}
|
||||
|
||||
void ZigbeeComponent::factory_reset() {
|
||||
esp_zigbee_lock_acquire(portMAX_DELAY);
|
||||
if (this->joined_) {
|
||||
// send leave request and trigger EZB_ZDO_SIGNAL_LEAVE
|
||||
ezb_bdb_reset_via_local_action();
|
||||
} else {
|
||||
esp_zigbee_factory_reset(); // triggers a reboot
|
||||
}
|
||||
esp_zigbee_lock_release();
|
||||
}
|
||||
|
||||
void ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(ezb_bdb_comm_mode_mask_t mode) {
|
||||
if (!esp_zigbee_lock_acquire(10 / portTICK_PERIOD_MS)) {
|
||||
global_zigbee->set_timeout("zb_init", 10, [mode]() { ZigbeeComponent::esp_zigbee_alarm_bdb_commissioning(mode); });
|
||||
@@ -53,7 +64,7 @@ bool ZigbeeComponent::app_signal_handler(const ezb_app_signal_t *app_signal) {
|
||||
switch (signal_type) {
|
||||
case EZB_ZDO_SIGNAL_SKIP_STARTUP:
|
||||
ESP_LOGD(TAG, "Zigbee stack initialized");
|
||||
global_zigbee->started = true;
|
||||
global_zigbee->started_ = true;
|
||||
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_INITIALIZATION);
|
||||
break;
|
||||
case EZB_BDB_SIGNAL_DEVICE_FIRST_START:
|
||||
@@ -62,12 +73,13 @@ bool ZigbeeComponent::app_signal_handler(const ezb_app_signal_t *app_signal) {
|
||||
if (status == EZB_BDB_STATUS_SUCCESS) {
|
||||
ESP_LOGD(TAG, "Device started up in %sfactory-reset mode", ezb_bdb_is_factory_new() ? "" : "non ");
|
||||
if (ezb_bdb_is_factory_new()) {
|
||||
global_zigbee->factory_new = true;
|
||||
global_zigbee->factory_new_ = true;
|
||||
ESP_LOGD(TAG, "Start network steering");
|
||||
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Device rebooted");
|
||||
global_zigbee->joined = true;
|
||||
global_zigbee->joined_ = true;
|
||||
global_zigbee->join_pending_ = true;
|
||||
global_zigbee->enable_loop_soon_any_context();
|
||||
}
|
||||
} else {
|
||||
@@ -85,7 +97,8 @@ bool ZigbeeComponent::app_signal_handler(const ezb_app_signal_t *app_signal) {
|
||||
ezb_nwk_get_extended_panid(&extended_pan_id);
|
||||
ESP_LOGD(TAG, "Joined network successfully: PAN ID(0x%04hx, EXT: 0x%llx), Channel(%d), Short Address(0x%04hx)",
|
||||
ezb_nwk_get_panid(), extended_pan_id.u64, ezb_nwk_get_current_channel(), ezb_nwk_get_short_address());
|
||||
global_zigbee->joined = true;
|
||||
global_zigbee->joined_ = true;
|
||||
global_zigbee->join_pending_ = true;
|
||||
global_zigbee->enable_loop_soon_any_context();
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Failed to join network with status(0x%02x)", status);
|
||||
@@ -105,7 +118,29 @@ bool ZigbeeComponent::app_signal_handler(const ezb_app_signal_t *app_signal) {
|
||||
const ezb_zdo_signal_leave_params_t *leave_params =
|
||||
(const ezb_zdo_signal_leave_params_t *) ezb_app_signal_get_params(app_signal);
|
||||
if (leave_params->leave_type == EZB_ZDO_LEAVE_TYPE_RESET) {
|
||||
esp_zigbee_factory_reset();
|
||||
esp_zigbee_factory_reset(); // triggers a reboot
|
||||
}
|
||||
global_zigbee->joined_ = false;
|
||||
} break;
|
||||
case EZB_NWK_SIGNAL_NETWORK_STATUS: {
|
||||
const ezb_nwk_signal_network_status_params_t *network_status_params =
|
||||
(const ezb_nwk_signal_network_status_params_t *) ezb_app_signal_get_params(app_signal);
|
||||
if (network_status_params->status == EZB_NWK_NETWORK_STATUS_PARENT_LINK_FAILURE) {
|
||||
global_zigbee->joined_ = false;
|
||||
ESP_LOGW(TAG, "Parent link failure, attempting rejoin");
|
||||
ezb_zdo_nwk_mgmt_leave_req_t leave_req = {
|
||||
.dst_nwk_addr = ezb_nwk_get_short_address(),
|
||||
.field =
|
||||
{
|
||||
.remove_children = false,
|
||||
.rejoin = true,
|
||||
},
|
||||
};
|
||||
// Send leave request to the network to rejoin
|
||||
// triggers EZB_ZDO_SIGNAL_LEAVE signal first, then EZB_BDB_SIGNAL_DEVICE_REBOOT
|
||||
ezb_zdo_nwk_mgmt_leave_req(&leave_req);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Zigbee APP Signal NETWORK_STATUS: 0x%02x", network_status_params->status);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
@@ -303,10 +338,9 @@ void ZigbeeComponent::setup() {
|
||||
}
|
||||
|
||||
void ZigbeeComponent::loop() {
|
||||
if (!this->join_reported_ && this->joined) {
|
||||
this->join_reported_ = true;
|
||||
this->join_cb_.call(this->factory_new);
|
||||
this->factory_new = false;
|
||||
if (this->join_pending_.exchange(false)) {
|
||||
this->join_cb_.call(this->factory_new_);
|
||||
this->factory_new_ = false;
|
||||
}
|
||||
this->disable_loop();
|
||||
}
|
||||
|
||||
@@ -54,11 +54,7 @@ class ZigbeeComponent final : public Component {
|
||||
static bool app_signal_handler(const ezb_app_signal_t *app_signal);
|
||||
static void esp_zigbee_alarm_bdb_commissioning(ezb_bdb_comm_mode_mask_t mode);
|
||||
|
||||
void factory_reset() {
|
||||
esp_zigbee_lock_acquire(portMAX_DELAY);
|
||||
esp_zigbee_factory_reset(); // triggers a reboot
|
||||
esp_zigbee_lock_release();
|
||||
}
|
||||
void factory_reset();
|
||||
|
||||
template<typename F> void add_on_join_callback(F &&cb) { this->join_cb_.add(std::forward<F>(cb)); }
|
||||
|
||||
@@ -66,13 +62,10 @@ class ZigbeeComponent final : public Component {
|
||||
|
||||
// True after the Zigbee stack has been initialized and the device has started up. Is set before the stack started
|
||||
// network commissioning or has joined a network and won't be reset until the device is rebooted.
|
||||
bool is_started() { return this->started; }
|
||||
bool is_started() { return this->started_; }
|
||||
|
||||
// True if the device has joined a network and is ready to send and receive messages.
|
||||
bool is_joined() { return this->joined; }
|
||||
std::atomic<bool> started = false;
|
||||
std::atomic<bool> joined = false;
|
||||
std::atomic<bool> factory_new = false;
|
||||
bool is_joined() { return this->joined_; }
|
||||
|
||||
protected:
|
||||
struct {
|
||||
@@ -95,8 +88,11 @@ class ZigbeeComponent final : public Component {
|
||||
// key tuple could be replaced by single 64 (48) bit int with bit fields for endpoint, cluster, role and attr_id
|
||||
std::map<std::tuple<uint8_t, uint16_t, uint8_t, uint16_t>, ZigbeeAttribute *> attributes_;
|
||||
ezb_af_device_desc_t dev_desc_;
|
||||
bool join_reported_{false};
|
||||
CallbackManager<void(bool)> join_cb_{};
|
||||
std::atomic<bool> started_ = false;
|
||||
std::atomic<bool> joined_ = false;
|
||||
std::atomic<bool> join_pending_ = false;
|
||||
std::atomic<bool> factory_new_ = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
Reference in New Issue
Block a user