[wifi] Leave the cooldown from the loop after a credential save, not from the caller's context (#20802)

This commit is contained in:
J. Nick Koston
2026-10-15 12:53:51 -10:00
committed by GitHub
parent c101b3c101
commit 5b234bcc20
2 changed files with 10 additions and 20 deletions
+10 -18
View File
@@ -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");
-2
View File
@@ -822,8 +822,6 @@ class WiFiComponent final : public Component {
return true;
}
void connect_soon_();
bool wifi_loop_();
#ifdef USE_ESP8266
void process_pending_callbacks_();