mirror of
https://github.com/esphome/esphome.git
synced 2026-08-23 06:36:23 +00:00
[wifi] Save fast connect settings and reset roaming bookkeeping after driver initiated roams (#18167)
This commit is contained in:
@@ -1676,7 +1676,7 @@ void WiFiComponent::check_connecting_finished(uint32_t now) {
|
||||
this->clear_all_bssid_priorities_();
|
||||
|
||||
#ifdef USE_WIFI_FAST_CONNECT
|
||||
this->save_fast_connect_settings_();
|
||||
this->save_fast_connect_settings_(this->wifi_bssid(), get_wifi_channel());
|
||||
#endif
|
||||
|
||||
this->release_scan_results_();
|
||||
@@ -2301,9 +2301,7 @@ bool WiFiComponent::load_fast_connect_settings_(WiFiAP ¶ms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WiFiComponent::save_fast_connect_settings_() {
|
||||
bssid_t bssid = wifi_bssid();
|
||||
uint8_t channel = get_wifi_channel();
|
||||
void WiFiComponent::save_fast_connect_settings_(const bssid_t &bssid, uint8_t channel) {
|
||||
// selected_sta_index_ is always valid here (called only after successful connection)
|
||||
// Fallback to 0 is defensive programming for robustness
|
||||
int8_t ap_index = this->selected_sta_index_ >= 0 ? this->selected_sta_index_ : 0;
|
||||
@@ -2416,6 +2414,25 @@ void WiFiComponent::clear_roaming_state_() {
|
||||
this->roaming_state_ = RoamingState::IDLE;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32
|
||||
void WiFiComponent::handle_driver_roam_(const bssid_t &bssid, uint8_t channel) {
|
||||
// A driver-initiated roam (e.g. 802.11v BTM) re-associates without the state
|
||||
// machine ever leaving STA_CONNECTED, so check_connecting_finished() never runs.
|
||||
// Redo its post-connect bookkeeping here. roaming_state_ is deliberately left
|
||||
// untouched so an in-flight roaming scan is not orphaned. The BSSID and
|
||||
// channel both come from the connected event so the saved pair is consistent:
|
||||
// the radio may be off-channel during a roaming scan, and a later queued
|
||||
// event may have moved the driver on again by the time this one is processed.
|
||||
this->roaming_last_check_ = App.get_loop_component_start_time();
|
||||
this->roaming_attempts_ = 0;
|
||||
this->roaming_scan_end_ = 0;
|
||||
this->clear_all_bssid_priorities_();
|
||||
#ifdef USE_WIFI_FAST_CONNECT
|
||||
this->save_fast_connect_settings_(bssid, channel);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void WiFiComponent::release_scan_results_() {
|
||||
if (!this->keep_scan_results_) {
|
||||
ScanResultsLock lock(this);
|
||||
|
||||
@@ -781,13 +781,19 @@ class WiFiComponent final : public Component {
|
||||
|
||||
#ifdef USE_WIFI_FAST_CONNECT
|
||||
bool load_fast_connect_settings_(WiFiAP ¶ms);
|
||||
void save_fast_connect_settings_();
|
||||
void save_fast_connect_settings_(const bssid_t &bssid, uint8_t channel);
|
||||
#endif
|
||||
|
||||
// Post-connect roaming methods
|
||||
void check_roaming_(uint32_t now);
|
||||
void process_roaming_scan_();
|
||||
void clear_roaming_state_();
|
||||
#ifdef USE_ESP32
|
||||
/// Redo post-connect bookkeeping after a driver-initiated roam (e.g. 802.11v BTM)
|
||||
/// @param bssid The new AP's BSSID, taken from the connected event
|
||||
/// @param channel The new AP's channel, taken from the connected event
|
||||
void handle_driver_roam_(const bssid_t &bssid, uint8_t channel);
|
||||
#endif
|
||||
|
||||
/// Returns true if a component has requested that roaming scans be suppressed (e.g. during audio playback).
|
||||
bool roaming_suppressed_() const {
|
||||
|
||||
@@ -825,6 +825,19 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
|
||||
(const char *) it.ssid, bssid_buf, it.channel, get_auth_mode_str(it.authmode));
|
||||
#endif
|
||||
s_sta_connected = true;
|
||||
if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED) {
|
||||
// Driver-initiated roam: the WIFI_REASON_ROAMING disconnect was ignored,
|
||||
// so the state machine never left STA_CONNECTED.
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_INFO
|
||||
char roam_bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
|
||||
format_mac_addr_upper(it.bssid, roam_bssid_s);
|
||||
ESP_LOGI(TAG, "Roamed ssid='%.*s' bssid=" LOG_SECRET("%s") " channel=%u", it.ssid_len, (const char *) it.ssid,
|
||||
roam_bssid_s, it.channel);
|
||||
#endif
|
||||
bssid_t roam_bssid;
|
||||
std::copy(it.bssid, it.bssid + 6, roam_bssid.begin());
|
||||
this->handle_driver_roam_(roam_bssid, it.channel);
|
||||
}
|
||||
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
|
||||
// Defer listener notification until state machine reaches STA_CONNECTED
|
||||
// This ensures wifi.connected condition returns true in listener automations
|
||||
|
||||
Reference in New Issue
Block a user