mirror of
https://github.com/esphome/esphome.git
synced 2025-11-19 08:15:49 +00:00
[wifi] Refactor AP selection to use index instead of copy (saves 88 bytes) (#11749)
This commit is contained in:
@@ -54,6 +54,10 @@ AUTO_LOAD = ["network"]
|
|||||||
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
|
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
|
||||||
CONF_SAVE = "save"
|
CONF_SAVE = "save"
|
||||||
|
|
||||||
|
# Maximum number of WiFi networks that can be configured
|
||||||
|
# Limited to 127 because selected_sta_index_ is int8_t in C++
|
||||||
|
MAX_WIFI_NETWORKS = 127
|
||||||
|
|
||||||
wifi_ns = cg.esphome_ns.namespace("wifi")
|
wifi_ns = cg.esphome_ns.namespace("wifi")
|
||||||
EAPAuth = wifi_ns.struct("EAPAuth")
|
EAPAuth = wifi_ns.struct("EAPAuth")
|
||||||
ManualIP = wifi_ns.struct("ManualIP")
|
ManualIP = wifi_ns.struct("ManualIP")
|
||||||
@@ -260,7 +264,9 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(WiFiComponent),
|
cv.GenerateID(): cv.declare_id(WiFiComponent),
|
||||||
cv.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA),
|
cv.Optional(CONF_NETWORKS): cv.All(
|
||||||
|
cv.ensure_list(WIFI_NETWORK_STA), cv.Length(max=MAX_WIFI_NETWORKS)
|
||||||
|
),
|
||||||
cv.Optional(CONF_SSID): cv.ssid,
|
cv.Optional(CONF_SSID): cv.ssid,
|
||||||
cv.Optional(CONF_PASSWORD): validate_password,
|
cv.Optional(CONF_PASSWORD): validate_password,
|
||||||
cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
|
cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "wifi_component.h"
|
#include "wifi_component.h"
|
||||||
#ifdef USE_WIFI
|
#ifdef USE_WIFI
|
||||||
|
#include <cassert>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
@@ -109,12 +110,15 @@ void WiFiComponent::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
this->trying_loaded_ap_ = this->load_fast_connect_settings_();
|
WiFiAP params;
|
||||||
|
this->trying_loaded_ap_ = this->load_fast_connect_settings_(params);
|
||||||
if (!this->trying_loaded_ap_) {
|
if (!this->trying_loaded_ap_) {
|
||||||
this->ap_index_ = 0;
|
// FAST CONNECT FALLBACK: No saved settings available
|
||||||
this->selected_ap_ = this->sta_[this->ap_index_];
|
// Use first config (will use SSID from config)
|
||||||
|
this->selected_sta_index_ = 0;
|
||||||
|
params = this->build_wifi_ap_from_selected_();
|
||||||
}
|
}
|
||||||
this->start_connecting(this->selected_ap_, false);
|
this->start_connecting(params, false);
|
||||||
#else
|
#else
|
||||||
this->start_scanning();
|
this->start_scanning();
|
||||||
#endif
|
#endif
|
||||||
@@ -169,15 +173,16 @@ void WiFiComponent::loop() {
|
|||||||
this->status_set_warning(LOG_STR("waiting to reconnect"));
|
this->status_set_warning(LOG_STR("waiting to reconnect"));
|
||||||
if (millis() - this->action_started_ > 5000) {
|
if (millis() - this->action_started_ > 5000) {
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
// NOTE: This check may not make sense here as it could interfere with AP cycling
|
// Safety check: Ensure selected_sta_index_ is valid before retrying
|
||||||
if (!this->selected_ap_.get_bssid().has_value())
|
// (should already be set by retry_connect(), but check for robustness)
|
||||||
this->selected_ap_ = this->sta_[0];
|
this->reset_selected_ap_to_first_if_invalid_();
|
||||||
this->start_connecting(this->selected_ap_, false);
|
WiFiAP params = this->build_wifi_ap_from_selected_();
|
||||||
|
this->start_connecting(params, false);
|
||||||
#else
|
#else
|
||||||
if (this->retry_hidden_) {
|
if (this->retry_hidden_) {
|
||||||
if (!this->selected_ap_.get_bssid().has_value())
|
this->reset_selected_ap_to_first_if_invalid_();
|
||||||
this->selected_ap_ = this->sta_[0];
|
WiFiAP params = this->build_wifi_ap_from_selected_();
|
||||||
this->start_connecting(this->selected_ap_, false);
|
this->start_connecting(params, false);
|
||||||
} else {
|
} else {
|
||||||
this->start_scanning();
|
this->start_scanning();
|
||||||
}
|
}
|
||||||
@@ -336,8 +341,42 @@ void WiFiComponent::set_sta(const WiFiAP &ap) {
|
|||||||
this->clear_sta();
|
this->clear_sta();
|
||||||
this->init_sta(1);
|
this->init_sta(1);
|
||||||
this->add_sta(ap);
|
this->add_sta(ap);
|
||||||
|
this->selected_sta_index_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiAP WiFiComponent::build_wifi_ap_from_selected_() const {
|
||||||
|
// PRECONDITION: selected_sta_index_ must be valid (ensured by all callers)
|
||||||
|
const WiFiAP *config = this->get_selected_sta_();
|
||||||
|
assert(config != nullptr);
|
||||||
|
WiFiAP params = *config;
|
||||||
|
|
||||||
|
// SYNCHRONIZATION: selected_sta_index_ and scan_result_[0] are kept in sync after wifi_scan_done():
|
||||||
|
// - wifi_scan_done() sorts all scan results by priority/RSSI (best first)
|
||||||
|
// - It then finds which sta_[i] config matches scan_result_[0]
|
||||||
|
// - Sets selected_sta_index_ = i to record that matching config
|
||||||
|
// This sync holds until scan_result_ is cleared (e.g., after connection or in reset_for_next_ap_attempt_())
|
||||||
|
if (!this->scan_result_.empty()) {
|
||||||
|
// Override with scan data - network is visible
|
||||||
|
const WiFiScanResult &scan = this->scan_result_[0];
|
||||||
|
params.set_hidden(false);
|
||||||
|
params.set_ssid(scan.get_ssid());
|
||||||
|
params.set_bssid(scan.get_bssid());
|
||||||
|
params.set_channel(scan.get_channel());
|
||||||
|
} else if (params.get_hidden()) {
|
||||||
|
// Hidden network - clear BSSID and channel even if set in config
|
||||||
|
// There might be multiple hidden networks with same SSID but we can't know which is correct
|
||||||
|
// Rely on probe-req with just SSID. Empty channel triggers ALL_CHANNEL_SCAN.
|
||||||
|
params.set_bssid(optional<bssid_t>{});
|
||||||
|
params.set_channel(optional<uint8_t>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiAP WiFiComponent::get_sta() const {
|
||||||
|
const WiFiAP *config = this->get_selected_sta_();
|
||||||
|
return config ? *config : WiFiAP{};
|
||||||
}
|
}
|
||||||
void WiFiComponent::clear_sta() { this->sta_.clear(); }
|
|
||||||
void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) {
|
void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) {
|
||||||
SavedWifiSettings save{}; // zero-initialized - all bytes set to \0, guaranteeing null termination
|
SavedWifiSettings save{}; // zero-initialized - all bytes set to \0, guaranteeing null termination
|
||||||
strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0
|
strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0
|
||||||
@@ -485,8 +524,8 @@ void WiFiComponent::print_connect_params_() {
|
|||||||
LOG_STR_ARG(get_signal_bars(rssi)), get_wifi_channel(), wifi_subnet_mask_().str().c_str(),
|
LOG_STR_ARG(get_signal_bars(rssi)), get_wifi_channel(), wifi_subnet_mask_().str().c_str(),
|
||||||
wifi_gateway_ip_().str().c_str(), wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
|
wifi_gateway_ip_().str().c_str(), wifi_dns_ip_(0).str().c_str(), wifi_dns_ip_(1).str().c_str());
|
||||||
#ifdef ESPHOME_LOG_HAS_VERBOSE
|
#ifdef ESPHOME_LOG_HAS_VERBOSE
|
||||||
if (this->selected_ap_.get_bssid().has_value()) {
|
if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_bssid().has_value()) {
|
||||||
ESP_LOGV(TAG, " Priority: %.1f", this->get_sta_priority(*this->selected_ap_.get_bssid()));
|
ESP_LOGV(TAG, " Priority: %.1f", this->get_sta_priority(*config->get_bssid()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_WIFI_11KV_SUPPORT
|
#ifdef USE_WIFI_11KV_SUPPORT
|
||||||
@@ -633,55 +672,38 @@ void WiFiComponent::check_scanning_finished() {
|
|||||||
log_scan_result(res);
|
log_scan_result(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->scan_result_[0].get_matches()) {
|
// SYNCHRONIZATION POINT: Establish link between scan_result_[0] and selected_sta_index_
|
||||||
|
// After sorting, scan_result_[0] contains the best network. Now find which sta_[i] config
|
||||||
|
// matches that network and record it in selected_sta_index_. This keeps the two indices
|
||||||
|
// synchronized so build_wifi_ap_from_selected_() can safely use both to build connection parameters.
|
||||||
|
const WiFiScanResult &scan_res = this->scan_result_[0];
|
||||||
|
if (!scan_res.get_matches()) {
|
||||||
ESP_LOGW(TAG, "No matching network found");
|
ESP_LOGW(TAG, "No matching network found");
|
||||||
this->retry_connect();
|
this->retry_connect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build connection params directly into selected_ap_ to avoid extra copy
|
bool found_match = false;
|
||||||
const WiFiScanResult &scan_res = this->scan_result_[0];
|
for (size_t i = 0; i < this->sta_.size(); i++) {
|
||||||
WiFiAP &selected = this->selected_ap_;
|
if (scan_res.matches(this->sta_[i])) {
|
||||||
for (auto &config : this->sta_) {
|
// Safe cast: sta_.size() limited to MAX_WIFI_NETWORKS (127) in __init__.py validation
|
||||||
// search for matching STA config, at least one will match (from checks before)
|
// No overflow check needed - YAML validation prevents >127 networks
|
||||||
if (!scan_res.matches(config)) {
|
this->selected_sta_index_ = static_cast<int8_t>(i); // Links scan_result_[0] with sta_[i]
|
||||||
continue;
|
found_match = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (config.get_hidden()) {
|
if (!found_match) {
|
||||||
// selected network is hidden, we use the data from the config
|
ESP_LOGW(TAG, "No matching network found");
|
||||||
selected.set_hidden(true);
|
this->retry_connect();
|
||||||
selected.set_ssid(config.get_ssid());
|
return;
|
||||||
// Clear channel and BSSID for hidden networks - there might be multiple hidden networks
|
|
||||||
// but we can't know which one is the correct one. Rely on probe-req with just SSID.
|
|
||||||
selected.set_channel(0);
|
|
||||||
selected.set_bssid(optional<bssid_t>{});
|
|
||||||
} else {
|
|
||||||
// selected network is visible, we use the data from the scan
|
|
||||||
// limit the connect params to only connect to exactly this network
|
|
||||||
// (network selection is done during scan phase).
|
|
||||||
selected.set_hidden(false);
|
|
||||||
selected.set_ssid(scan_res.get_ssid());
|
|
||||||
selected.set_channel(scan_res.get_channel());
|
|
||||||
selected.set_bssid(scan_res.get_bssid());
|
|
||||||
}
|
|
||||||
// copy manual IP (if set)
|
|
||||||
selected.set_manual_ip(config.get_manual_ip());
|
|
||||||
|
|
||||||
#ifdef USE_WIFI_WPA2_EAP
|
|
||||||
// copy EAP parameters (if set)
|
|
||||||
selected.set_eap(config.get_eap());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// copy password (if set)
|
|
||||||
selected.set_password(config.get_password());
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
this->start_connecting(this->selected_ap_, false);
|
WiFiAP params = this->build_wifi_ap_from_selected_();
|
||||||
|
this->start_connecting(params, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiComponent::dump_config() {
|
void WiFiComponent::dump_config() {
|
||||||
@@ -700,9 +722,12 @@ void WiFiComponent::check_connecting_finished() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Connected");
|
ESP_LOGI(TAG, "Connected");
|
||||||
// We won't retry hidden networks unless a reconnect fails more than three times again
|
// Warn if we had to retry with hidden network mode for a network that's not marked hidden
|
||||||
if (this->retry_hidden_ && !this->selected_ap_.get_hidden())
|
// Only warn if we actually connected without scan data (SSID only), not if scan succeeded on retry
|
||||||
ESP_LOGW(TAG, "Network '%s' should be marked as hidden", this->selected_ap_.get_ssid().c_str());
|
if (const WiFiAP *config = this->get_selected_sta_();
|
||||||
|
this->retry_hidden_ && config && !config->get_hidden() && this->scan_result_.empty()) {
|
||||||
|
ESP_LOGW(TAG, "Network '%s' should be marked as hidden", config->get_ssid().c_str());
|
||||||
|
}
|
||||||
this->retry_hidden_ = false;
|
this->retry_hidden_ = false;
|
||||||
|
|
||||||
this->print_connect_params_();
|
this->print_connect_params_();
|
||||||
@@ -725,16 +750,16 @@ void WiFiComponent::check_connecting_finished() {
|
|||||||
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTED;
|
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTED;
|
||||||
this->num_retried_ = 0;
|
this->num_retried_ = 0;
|
||||||
|
|
||||||
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
|
this->save_fast_connect_settings_();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Free scan results memory unless a component needs them
|
// Free scan results memory unless a component needs them
|
||||||
if (!this->keep_scan_results_) {
|
if (!this->keep_scan_results_) {
|
||||||
this->scan_result_.clear();
|
this->scan_result_.clear();
|
||||||
this->scan_result_.shrink_to_fit();
|
this->scan_result_.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
|
||||||
this->save_fast_connect_settings_();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,8 +797,8 @@ void WiFiComponent::check_connecting_finished() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WiFiComponent::retry_connect() {
|
void WiFiComponent::retry_connect() {
|
||||||
if (this->selected_ap_.get_bssid()) {
|
if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_bssid()) {
|
||||||
auto bssid = *this->selected_ap_.get_bssid();
|
auto bssid = *config->get_bssid();
|
||||||
float priority = this->get_sta_priority(bssid);
|
float priority = this->get_sta_priority(bssid);
|
||||||
this->set_sta_priority(bssid, priority - 1.0f);
|
this->set_sta_priority(bssid, priority - 1.0f);
|
||||||
}
|
}
|
||||||
@@ -782,19 +807,26 @@ void WiFiComponent::retry_connect() {
|
|||||||
if (!this->is_captive_portal_active_() && !this->is_esp32_improv_active_() &&
|
if (!this->is_captive_portal_active_() && !this->is_esp32_improv_active_() &&
|
||||||
(this->num_retried_ > 3 || this->error_from_callback_)) {
|
(this->num_retried_ > 3 || this->error_from_callback_)) {
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
|
// No empty check needed - YAML validation requires at least one network for fast_connect
|
||||||
if (this->trying_loaded_ap_) {
|
if (this->trying_loaded_ap_) {
|
||||||
this->trying_loaded_ap_ = false;
|
this->trying_loaded_ap_ = false;
|
||||||
this->ap_index_ = 0; // Retry from the first configured AP
|
this->selected_sta_index_ = 0; // Retry from the first configured AP
|
||||||
} else if (this->ap_index_ >= this->sta_.size() - 1) {
|
this->reset_for_next_ap_attempt_();
|
||||||
|
} else if (this->selected_sta_index_ >= static_cast<int8_t>(this->sta_.size()) - 1) {
|
||||||
|
// Safe cast: sta_.size() limited to MAX_WIFI_NETWORKS (127) in __init__.py validation
|
||||||
|
// Exhausted all configured APs, restart adapter and cycle back to first
|
||||||
|
// Restart clears any stuck WiFi driver state
|
||||||
|
// Each AP is tried with config data only (SSID + optional BSSID/channel if user configured them)
|
||||||
|
// Typically SSID only, which triggers ESP-IDF internal scanning
|
||||||
ESP_LOGW(TAG, "No more APs to try");
|
ESP_LOGW(TAG, "No more APs to try");
|
||||||
this->ap_index_ = 0;
|
this->selected_sta_index_ = 0;
|
||||||
|
this->reset_for_next_ap_attempt_();
|
||||||
this->restart_adapter();
|
this->restart_adapter();
|
||||||
} else {
|
} else {
|
||||||
// Try next AP
|
// Try next AP
|
||||||
this->ap_index_++;
|
this->selected_sta_index_++;
|
||||||
|
this->reset_for_next_ap_attempt_();
|
||||||
}
|
}
|
||||||
this->num_retried_ = 0;
|
|
||||||
this->selected_ap_ = this->sta_[this->ap_index_];
|
|
||||||
#else
|
#else
|
||||||
if (this->num_retried_ > 5) {
|
if (this->num_retried_ > 5) {
|
||||||
// If retry failed for more than 5 times, let's restart STA
|
// If retry failed for more than 5 times, let's restart STA
|
||||||
@@ -813,7 +845,8 @@ void WiFiComponent::retry_connect() {
|
|||||||
if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING) {
|
if (this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTING) {
|
||||||
yield();
|
yield();
|
||||||
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2;
|
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING_2;
|
||||||
this->start_connecting(this->selected_ap_, true);
|
WiFiAP params = this->build_wifi_ap_from_selected_();
|
||||||
|
this->start_connecting(params, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,16 +885,29 @@ bool WiFiComponent::is_esp32_improv_active_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
bool WiFiComponent::load_fast_connect_settings_() {
|
bool WiFiComponent::load_fast_connect_settings_(WiFiAP ¶ms) {
|
||||||
SavedWifiFastConnectSettings fast_connect_save{};
|
SavedWifiFastConnectSettings fast_connect_save{};
|
||||||
|
|
||||||
if (this->fast_connect_pref_.load(&fast_connect_save)) {
|
if (this->fast_connect_pref_.load(&fast_connect_save)) {
|
||||||
|
// Validate saved AP index
|
||||||
|
if (fast_connect_save.ap_index < 0 || static_cast<size_t>(fast_connect_save.ap_index) >= this->sta_.size()) {
|
||||||
|
ESP_LOGW(TAG, "AP index out of bounds");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set selected index for future operations (save, retry, etc)
|
||||||
|
this->selected_sta_index_ = fast_connect_save.ap_index;
|
||||||
|
|
||||||
|
// Copy entire config, then override with fast connect data
|
||||||
|
params = this->sta_[fast_connect_save.ap_index];
|
||||||
|
|
||||||
|
// Override with saved BSSID/channel from fast connect (SSID/password/etc already copied from config)
|
||||||
bssid_t bssid{};
|
bssid_t bssid{};
|
||||||
std::copy(fast_connect_save.bssid, fast_connect_save.bssid + 6, bssid.begin());
|
std::copy(fast_connect_save.bssid, fast_connect_save.bssid + 6, bssid.begin());
|
||||||
this->ap_index_ = fast_connect_save.ap_index;
|
params.set_bssid(bssid);
|
||||||
this->selected_ap_ = this->sta_[this->ap_index_];
|
params.set_channel(fast_connect_save.channel);
|
||||||
this->selected_ap_.set_bssid(bssid);
|
// Fast connect uses specific BSSID+channel, not hidden network probe (even if config has hidden: true)
|
||||||
this->selected_ap_.set_channel(fast_connect_save.channel);
|
params.set_hidden(false);
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Loaded fast_connect settings");
|
ESP_LOGD(TAG, "Loaded fast_connect settings");
|
||||||
return true;
|
return true;
|
||||||
@@ -873,18 +919,25 @@ bool WiFiComponent::load_fast_connect_settings_() {
|
|||||||
void WiFiComponent::save_fast_connect_settings_() {
|
void WiFiComponent::save_fast_connect_settings_() {
|
||||||
bssid_t bssid = wifi_bssid();
|
bssid_t bssid = wifi_bssid();
|
||||||
uint8_t channel = get_wifi_channel();
|
uint8_t channel = get_wifi_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;
|
||||||
|
|
||||||
if (bssid != this->selected_ap_.get_bssid() || channel != this->selected_ap_.get_channel()) {
|
// Skip save if settings haven't changed (compare with previously saved settings to reduce flash wear)
|
||||||
SavedWifiFastConnectSettings fast_connect_save{};
|
SavedWifiFastConnectSettings previous_save{};
|
||||||
|
if (this->fast_connect_pref_.load(&previous_save) && memcmp(previous_save.bssid, bssid.data(), 6) == 0 &&
|
||||||
memcpy(fast_connect_save.bssid, bssid.data(), 6);
|
previous_save.channel == channel && previous_save.ap_index == ap_index) {
|
||||||
fast_connect_save.channel = channel;
|
return; // No change, nothing to save
|
||||||
fast_connect_save.ap_index = this->ap_index_;
|
|
||||||
|
|
||||||
this->fast_connect_pref_.save(&fast_connect_save);
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Saved fast_connect settings");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SavedWifiFastConnectSettings fast_connect_save{};
|
||||||
|
memcpy(fast_connect_save.bssid, bssid.data(), 6);
|
||||||
|
fast_connect_save.channel = channel;
|
||||||
|
fast_connect_save.ap_index = ap_index;
|
||||||
|
|
||||||
|
this->fast_connect_pref_.save(&fast_connect_save);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Saved fast_connect settings");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -218,10 +218,14 @@ class WiFiComponent : public Component {
|
|||||||
WiFiComponent();
|
WiFiComponent();
|
||||||
|
|
||||||
void set_sta(const WiFiAP &ap);
|
void set_sta(const WiFiAP &ap);
|
||||||
WiFiAP get_sta() { return this->selected_ap_; }
|
// Returns a copy of the currently selected AP configuration
|
||||||
|
WiFiAP get_sta() const;
|
||||||
void init_sta(size_t count);
|
void init_sta(size_t count);
|
||||||
void add_sta(const WiFiAP &ap);
|
void add_sta(const WiFiAP &ap);
|
||||||
void clear_sta();
|
void clear_sta() {
|
||||||
|
this->sta_.clear();
|
||||||
|
this->selected_sta_index_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_WIFI_AP
|
#ifdef USE_WIFI_AP
|
||||||
/** Setup an Access Point that should be created if no connection to a station can be made.
|
/** Setup an Access Point that should be created if no connection to a station can be made.
|
||||||
@@ -337,6 +341,29 @@ class WiFiComponent : public Component {
|
|||||||
#endif // USE_WIFI_AP
|
#endif // USE_WIFI_AP
|
||||||
|
|
||||||
void print_connect_params_();
|
void print_connect_params_();
|
||||||
|
WiFiAP build_wifi_ap_from_selected_() const;
|
||||||
|
|
||||||
|
const WiFiAP *get_selected_sta_() const {
|
||||||
|
if (this->selected_sta_index_ >= 0 && static_cast<size_t>(this->selected_sta_index_) < this->sta_.size()) {
|
||||||
|
return &this->sta_[this->selected_sta_index_];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_selected_ap_to_first_if_invalid_() {
|
||||||
|
if (this->selected_sta_index_ < 0 || static_cast<size_t>(this->selected_sta_index_) >= this->sta_.size()) {
|
||||||
|
this->selected_sta_index_ = this->sta_.empty() ? -1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
|
// Reset state for next fast connect AP attempt
|
||||||
|
// Clears old scan data so the new AP is tried with config only (SSID without specific BSSID/channel)
|
||||||
|
void reset_for_next_ap_attempt_() {
|
||||||
|
this->num_retried_ = 0;
|
||||||
|
this->scan_result_.clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void wifi_loop_();
|
void wifi_loop_();
|
||||||
bool wifi_mode_(optional<bool> sta, optional<bool> ap);
|
bool wifi_mode_(optional<bool> sta, optional<bool> ap);
|
||||||
@@ -365,7 +392,7 @@ class WiFiComponent : public Component {
|
|||||||
bool is_esp32_improv_active_();
|
bool is_esp32_improv_active_();
|
||||||
|
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
#ifdef USE_WIFI_FAST_CONNECT
|
||||||
bool load_fast_connect_settings_();
|
bool load_fast_connect_settings_(WiFiAP ¶ms);
|
||||||
void save_fast_connect_settings_();
|
void save_fast_connect_settings_();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -396,7 +423,6 @@ class WiFiComponent : public Component {
|
|||||||
FixedVector<WiFiAP> sta_;
|
FixedVector<WiFiAP> sta_;
|
||||||
std::vector<WiFiSTAPriority> sta_priorities_;
|
std::vector<WiFiSTAPriority> sta_priorities_;
|
||||||
wifi_scan_vector_t<WiFiScanResult> scan_result_;
|
wifi_scan_vector_t<WiFiScanResult> scan_result_;
|
||||||
WiFiAP selected_ap_;
|
|
||||||
#ifdef USE_WIFI_AP
|
#ifdef USE_WIFI_AP
|
||||||
WiFiAP ap_;
|
WiFiAP ap_;
|
||||||
#endif
|
#endif
|
||||||
@@ -418,9 +444,10 @@ class WiFiComponent : public Component {
|
|||||||
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
|
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
|
||||||
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
|
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
|
||||||
uint8_t num_retried_{0};
|
uint8_t num_retried_{0};
|
||||||
#ifdef USE_WIFI_FAST_CONNECT
|
// Index into sta_ array for the currently selected AP configuration (-1 = none selected)
|
||||||
uint8_t ap_index_{0};
|
// Used to access password, manual_ip, priority, EAP settings, and hidden flag
|
||||||
#endif
|
// int8_t limits to 127 APs (enforced in __init__.py via MAX_WIFI_NETWORKS)
|
||||||
|
int8_t selected_sta_index_{-1};
|
||||||
#if USE_NETWORK_IPV6
|
#if USE_NETWORK_IPV6
|
||||||
uint8_t num_ipv6_addresses_{0};
|
uint8_t num_ipv6_addresses_{0};
|
||||||
#endif /* USE_NETWORK_IPV6 */
|
#endif /* USE_NETWORK_IPV6 */
|
||||||
|
|||||||
Reference in New Issue
Block a user