mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-10-28 11:14:58 +00:00
fix SoftAP fallback to keep retrying WiFi STA after cold boot
This commit is contained in:
@@ -68,11 +68,13 @@ This release is based on the latest Espressif/Arduino core version 3. It brings
|
||||
- a read or write aimed at EMS-ESP's own bus id was left unanswered, so the sender waited for a timeout. EMS-ESP now sends an empty reply to those reads and acknowledges those writes [#3094](https://github.com/emsesp/EMS-ESP32/issues/3094)
|
||||
- a second boiler monitor `0xE4` carrying `0xFFFF` cleared a valid `pc0Flow`. That empty value is now ignored [#3224](https://github.com/emsesp/EMS-ESP32/issues/3224)
|
||||
- writing a negative custom entity value was always 1 too high because float-to-int rounding always added +0.5. Negative values now round the same way as positive ones [#3297](https://github.com/emsesp/EMS-ESP32/issues/3297)
|
||||
- after a cold boot, SoftAP fallback no longer abandons STA forever. If a home WiFi SSID is configured, EMS-ESP keeps retrying STA while the captive portal is up so a late-booting router (e.g. after a power outage) can still be joined; SoftAP stops once STA gets an IP
|
||||
|
||||
## Changed
|
||||
|
||||
- various memory optimizations [#3083](https://github.com/emsesp/EMS-ESP32/issues/3083)
|
||||
- Scheduler name is now mandatory
|
||||
- Access Point provision mode label renamed from "When network connection is lost" to "When network connection not found" (all languages)
|
||||
- network fallback to AP only after start [#3090](https://github.com/emsesp/EMS-ESP32/issues/3090)
|
||||
- replaced Web async-validator with custom validator and toast with native snackbar to reduce bundle size
|
||||
- Gateway and Connect devices are shown in the Devices page, but disabled [3126](https://github.com/emsesp/EMS-ESP32/discussions/3126)
|
||||
|
||||
@@ -238,7 +238,7 @@ const cs: Translation = {
|
||||
TIME_ZONE: 'Časová zóna',
|
||||
ACCESS_POINT: 'Přístupový bod',
|
||||
AP_PROVIDE: 'Povolit přístupový bod',
|
||||
AP_PROVIDE_TEXT_2: 'Když je síťové připojení stratené',
|
||||
AP_PROVIDE_TEXT_2: 'Když není síťové připojení nalezeno',
|
||||
AP_PROVIDE_TEXT_3: 'Nikdy',
|
||||
AP_PREFERRED_CHANNEL: 'Preferovaný kanál',
|
||||
AP_HIDE_SSID: 'Skrýt SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const de: Translation = {
|
||||
TIME_ZONE: 'Zeitzone',
|
||||
ACCESS_POINT: 'Zugangspunkt',
|
||||
AP_PROVIDE: 'Aktiviere Zugangspunkt',
|
||||
AP_PROVIDE_TEXT_2: 'Wenn Netzwerkverbindung verloren geht',
|
||||
AP_PROVIDE_TEXT_2: 'Wenn keine Netzwerkverbindung gefunden wird',
|
||||
AP_PROVIDE_TEXT_3: 'Niemals',
|
||||
AP_PREFERRED_CHANNEL: 'Bevorzugter Kanal',
|
||||
AP_HIDE_SSID: 'Verstecke SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const en: Translation = {
|
||||
TIME_ZONE: 'Time Zone',
|
||||
ACCESS_POINT: 'Access Point',
|
||||
AP_PROVIDE: 'Enable Access Point',
|
||||
AP_PROVIDE_TEXT_2: 'When network connection is lost',
|
||||
AP_PROVIDE_TEXT_2: 'When network connection not found',
|
||||
AP_PROVIDE_TEXT_3: 'Never',
|
||||
AP_PREFERRED_CHANNEL: 'Preferred Channel',
|
||||
AP_HIDE_SSID: 'Hide SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const fr: Translation = {
|
||||
TIME_ZONE: 'Fuseau horaire',
|
||||
ACCESS_POINT: "Point d'accès",
|
||||
AP_PROVIDE: "Activer le Point d'Accès",
|
||||
AP_PROVIDE_TEXT_2: 'quand la connexion réseau est perdue',
|
||||
AP_PROVIDE_TEXT_2: 'quand la connexion réseau n\'est pas trouvée',
|
||||
AP_PROVIDE_TEXT_3: 'jamais',
|
||||
AP_PREFERRED_CHANNEL: 'Canal préféré',
|
||||
AP_HIDE_SSID: 'Cacher le SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const it: Translation = {
|
||||
TIME_ZONE: 'Fuso orario',
|
||||
ACCESS_POINT: 'Access Point',
|
||||
AP_PROVIDE: 'Abilita Access Point',
|
||||
AP_PROVIDE_TEXT_2: 'quando la connessione di rete è persa',
|
||||
AP_PROVIDE_TEXT_2: 'quando la connessione di rete non è trovata',
|
||||
AP_PROVIDE_TEXT_3: 'mai',
|
||||
AP_PREFERRED_CHANNEL: 'Canale preferito',
|
||||
AP_HIDE_SSID: 'Nascondi SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const nl: Translation = {
|
||||
TIME_ZONE: 'Tijdzone',
|
||||
ACCESS_POINT: 'Access Point',
|
||||
AP_PROVIDE: 'Activeer Access Point',
|
||||
AP_PROVIDE_TEXT_2: 'als netwerk verbinding verloren gaat',
|
||||
AP_PROVIDE_TEXT_2: 'als netwerkverbinding niet gevonden wordt',
|
||||
AP_PROVIDE_TEXT_3: 'nooit',
|
||||
AP_PREFERRED_CHANNEL: 'Voorkeurskanaal',
|
||||
AP_HIDE_SSID: 'SSID verbergen',
|
||||
|
||||
@@ -238,7 +238,7 @@ const no: Translation = {
|
||||
TIME_ZONE: 'Tidssone',
|
||||
ACCESS_POINT: 'Aksesspunkt',
|
||||
AP_PROVIDE: 'Aktiver Aksesspunkt',
|
||||
AP_PROVIDE_TEXT_2: 'når nettverksforbindelsen er utilgjengelig',
|
||||
AP_PROVIDE_TEXT_2: 'når nettverksforbindelsen ikke finnes',
|
||||
AP_PROVIDE_TEXT_3: 'aldri',
|
||||
AP_PREFERRED_CHANNEL: 'Foretrukket kanal',
|
||||
AP_HIDE_SSID: 'Skjul SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const pl: BaseTranslation = {
|
||||
TIME_ZONE: 'Strefa czasowa',
|
||||
ACCESS_POINT: '{{Punkt|punktu|}} {{dostępowy|dostępowego|}}',
|
||||
AP_PROVIDE: 'Punkt dostępowy',
|
||||
AP_PROVIDE_TEXT_2: 'aktywny jeśli brak połączenia z siecią',
|
||||
AP_PROVIDE_TEXT_2: 'gdy nie znaleziono połączenia z siecią',
|
||||
AP_PROVIDE_TEXT_3: 'nieaktywny',
|
||||
AP_PREFERRED_CHANNEL: 'Preferowany kanał',
|
||||
AP_HIDE_SSID: 'Ukryj SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const sk: Translation = {
|
||||
TIME_ZONE: 'Časová zóna',
|
||||
ACCESS_POINT: 'Prístupový bod',
|
||||
AP_PROVIDE: 'Povoliť prístupový bod',
|
||||
AP_PROVIDE_TEXT_2: 'keď je sieťové pripojenie stratené',
|
||||
AP_PROVIDE_TEXT_2: 'keď sieťové pripojenie nie je nájdené',
|
||||
AP_PROVIDE_TEXT_3: 'nikdy',
|
||||
AP_PREFERRED_CHANNEL: 'Preferovaný kanál',
|
||||
AP_HIDE_SSID: 'Skryť SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const sv: Translation = {
|
||||
TIME_ZONE: 'Tidszon',
|
||||
ACCESS_POINT: 'Accesspunkt',
|
||||
AP_PROVIDE: 'Aktivera accesspunkt',
|
||||
AP_PROVIDE_TEXT_2: 'när nätverksanslutningen är bortkopplad',
|
||||
AP_PROVIDE_TEXT_2: 'när nätverksanslutningen inte hittas',
|
||||
AP_PROVIDE_TEXT_3: 'aldrig',
|
||||
AP_PREFERRED_CHANNEL: 'Kanal',
|
||||
AP_HIDE_SSID: 'Göm SSID',
|
||||
|
||||
@@ -238,7 +238,7 @@ const tr: Translation = {
|
||||
TIME_ZONE: 'Saat dilimi',
|
||||
ACCESS_POINT: 'Erişim Noktası',
|
||||
AP_PROVIDE: 'Erişim noktasını çalıştır',
|
||||
AP_PROVIDE_TEXT_2: 'Ağ bağlantısı kesildiğinde',
|
||||
AP_PROVIDE_TEXT_2: 'Ağ bağlantısı bulunamadığında',
|
||||
AP_PROVIDE_TEXT_3: 'asla',
|
||||
AP_PREFERRED_CHANNEL: 'Tercih edilen kanal',
|
||||
AP_HIDE_SSID: 'SSID yi gizle',
|
||||
|
||||
+18
-4
@@ -125,6 +125,10 @@ void Network::begin() {
|
||||
wifi_connect_pending_ = false;
|
||||
if (wifi_ever_connected_) {
|
||||
LOG_WARNING("WiFi disconnected (reason: %s)", disconnectReason(last_disconnect_reason_));
|
||||
} else if (phase_ == NetPhase::AP) {
|
||||
// SoftAP fallback is up and we're periodically retrying STA (slow router after
|
||||
// power restore) — don't flood the log with WARNING on every failed attempt
|
||||
LOG_DEBUG("WiFi STA retry while AP active failed (reason: %s)", disconnectReason(last_disconnect_reason_));
|
||||
} else {
|
||||
LOG_WARNING("WiFi initial connect attempt failed (reason: %s)", disconnectReason(last_disconnect_reason_));
|
||||
}
|
||||
@@ -663,13 +667,17 @@ void Network::stopWiFiRadio() {
|
||||
// WiFi management
|
||||
void Network::startWIFI() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// only run during the WIFI phase; ETHERNET phase keeps WiFi quiet, AP phase has its own bring-up
|
||||
if (phase_ != NetPhase::WIFI) {
|
||||
// WIFI phase: normal STA connect. AP phase with a configured SSID: keep retrying STA while
|
||||
// SoftAP is up so a late-booting router (e.g. after a power outage) can still be joined —
|
||||
// findNetworks() stops SoftAP once STA gets an IP. ETHERNET phase keeps WiFi quiet.
|
||||
const bool ap_fallback_retry = (phase_ == NetPhase::AP && !ssid_.isEmpty());
|
||||
if (phase_ != NetPhase::WIFI && !ap_fallback_retry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// the radio was powered down while Ethernet was up, so bring it back before trying to associate
|
||||
if (wifi_radio_off_) {
|
||||
// the radio was powered down while Ethernet was up, so bring it back before trying to associate.
|
||||
// Don't call this during SoftAP fallback — startWiFiRadio() forces WIFI_STA and would kill the AP.
|
||||
if (wifi_radio_off_ && !ap_fallback_retry) {
|
||||
startWiFiRadio();
|
||||
}
|
||||
|
||||
@@ -678,6 +686,11 @@ void Network::startWIFI() {
|
||||
return;
|
||||
}
|
||||
|
||||
// SoftAP is serving the captive portal — keep it and enable STA alongside
|
||||
if (ap_fallback_retry && (WiFi.getMode() & WIFI_AP)) {
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
}
|
||||
|
||||
wifi_connect_pending_ = true;
|
||||
|
||||
// attempt to connect to the wifi network
|
||||
@@ -969,6 +982,7 @@ void Network::findNetworks() {
|
||||
: "AP");
|
||||
|
||||
// give up on this interface and try the next one. ETHERNET -> WIFI (or straight to AP if no SSID configured); WIFI -> AP.
|
||||
// Once in AP phase with a configured SSID, startWIFI() keeps retrying STA (WIFI_AP_STA) so a late router can still be joined.
|
||||
// AP_MODE_NEVER: never promote to the AP phase — keep waiting on the current interface.
|
||||
if (connect_retry_ >= MAX_NETWORK_RECONNECTION_ATTEMPTS && phase_ != NetPhase::AP) {
|
||||
if (phase_ == NetPhase::ETHERNET) {
|
||||
|
||||
Reference in New Issue
Block a user