mirror of
https://github.com/esphome/esphome.git
synced 2026-10-17 11:42:51 +00:00
[wifi] Leave the cooldown from the loop after a credential save, not from the caller's context (#20802)
This commit is contained in:
@@ -854,10 +854,11 @@ void WiFiComponent::loop() {
|
||||
switch (this->state_) {
|
||||
case WIFI_COMPONENT_STATE_COOLDOWN: {
|
||||
this->status_set_warning(LOG_STR("waiting to reconnect"));
|
||||
// Skip cooldown if new credentials were provided while connecting
|
||||
// Credentials not tried yet: retry whatever the driver reports. The flag outlives an adapter restart,
|
||||
// which only lands back here, and start_connecting() clears it once they are tried
|
||||
if (this->skip_cooldown_next_cycle_) {
|
||||
this->skip_cooldown_next_cycle_ = false;
|
||||
this->check_connecting_finished(now);
|
||||
ESP_LOGD(TAG, "Exiting cooldown early due to new WiFi credentials");
|
||||
this->retry_connect();
|
||||
break;
|
||||
}
|
||||
// Use longer cooldown when a portal/improv is active to avoid disrupting a user on the AP
|
||||
@@ -1183,7 +1184,7 @@ void WiFiComponent::set_sta(const WiFiAP &ap) {
|
||||
this->init_sta(1);
|
||||
this->add_sta(ap);
|
||||
this->selected_sta_index_ = 0;
|
||||
// When new credentials are set (e.g., from improv), skip cooldown to retry immediately
|
||||
// New credentials end the next cooldown early; start_connecting() clears this once they are tried
|
||||
this->skip_cooldown_next_cycle_ = true;
|
||||
#ifdef USE_WIFI_LEASE_CACHE
|
||||
// Index 0 is a different network now, so its cached lease must not be re-applied
|
||||
@@ -1252,29 +1253,18 @@ void WiFiComponent::save_wifi_sta(const char *ssid, const char *password) {
|
||||
WiFiAP sta{};
|
||||
sta.set_ssid(ssid);
|
||||
sta.set_password(password);
|
||||
// No retry here: a captive portal save runs in lwIP's context on the ESP8266, where retry_connect() yields and
|
||||
// panics. set_sta() flags the credentials and loop() tries them
|
||||
this->set_sta(sta);
|
||||
|
||||
// Trigger connection attempt (exits cooldown if needed, no-op if already connecting/connected)
|
||||
this->connect_soon_();
|
||||
}
|
||||
|
||||
void WiFiComponent::connect_soon_() {
|
||||
#ifdef USE_WIFI_AP_EXCLUSIVE
|
||||
// New credentials from the portal: the AP pauses for them once its answer
|
||||
// is out, and the STA state machine picks them up from there.
|
||||
// The AP pauses for the new credentials once its answer is out, and the STA state machine picks them up
|
||||
if (this->ap_setup_) {
|
||||
this->set_timeout(AP_HANDOVER_TIMEOUT_ID, WIFI_AP_EXCLUSIVE_HANDOVER_MS, [this]() {
|
||||
if (this->ap_setup_)
|
||||
this->pause_exclusive_ap_();
|
||||
});
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Only trigger retry if we're in cooldown - if already connecting/connected, do nothing
|
||||
if (this->state_ == WIFI_COMPONENT_STATE_COOLDOWN) {
|
||||
ESP_LOGD(TAG, "Exiting cooldown early due to new WiFi credentials");
|
||||
this->retry_connect();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiComponent::start_connecting(const WiFiAP &ap) {
|
||||
@@ -1366,6 +1356,8 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) {
|
||||
// enters COOLDOWN without calling start_connecting(), and ESP8266 clears it again
|
||||
// after wifi_station_connect(), whose callbacks fire synchronously.
|
||||
this->error_from_callback_ = false;
|
||||
// Every attempt passes through here, so the credentials set_sta() flagged are tried now
|
||||
this->skip_cooldown_next_cycle_ = false;
|
||||
|
||||
if (!this->wifi_sta_connect_(ap)) {
|
||||
ESP_LOGE(TAG, "wifi_sta_connect_ failed");
|
||||
|
||||
@@ -822,8 +822,6 @@ class WiFiComponent final : public Component {
|
||||
return true;
|
||||
}
|
||||
|
||||
void connect_soon_();
|
||||
|
||||
bool wifi_loop_();
|
||||
#ifdef USE_ESP8266
|
||||
void process_pending_callbacks_();
|
||||
|
||||
Reference in New Issue
Block a user