This commit is contained in:
J. Nick Koston
2026-02-06 09:31:06 +01:00
parent 8fa94dbdf3
commit 2573863d82
3 changed files with 27 additions and 31 deletions
+13 -4
View File
@@ -1464,13 +1464,22 @@ void WiFiComponent::check_connecting_finished(uint32_t now) {
this->release_scan_results_();
#if defined(USE_WIFI_CONNECT_STATE_LISTENERS) && !defined(USE_ESP8266)
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
// Notify listeners now that state machine has reached STA_CONNECTED
// This ensures wifi.connected condition returns true in listener automations
// On ESP8266, this is handled by process_pending_callbacks_() instead.
this->notify_connect_state_listeners_();
#endif
#if defined(USE_ESP8266) && defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP)
// On ESP8266, GOT_IP event may not fire for static IP configurations,
// so notify IP state listeners here as a fallback.
if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) {
for (auto *listener : this->ip_state_listeners_) {
listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1));
}
}
#endif
return;
}
@@ -2194,7 +2203,7 @@ void WiFiComponent::release_scan_results_() {
}
}
#if defined(USE_WIFI_CONNECT_STATE_LISTENERS) && !defined(USE_ESP8266)
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
void WiFiComponent::notify_connect_state_listeners_() {
if (!this->pending_.connect_state)
return;
@@ -2207,7 +2216,7 @@ void WiFiComponent::notify_connect_state_listeners_() {
listener->on_wifi_connect_state(StringRef(ssid, strlen(ssid)), bssid);
}
}
#endif // USE_WIFI_CONNECT_STATE_LISTENERS && !USE_ESP8266
#endif // USE_WIFI_CONNECT_STATE_LISTENERS
void WiFiComponent::check_roaming_(uint32_t now) {
// Guard: not for hidden networks (may not appear in scan)
+6 -7
View File
@@ -641,9 +641,8 @@ class WiFiComponent : public Component {
/// Free scan results memory unless a component needs them
void release_scan_results_();
#if defined(USE_WIFI_CONNECT_STATE_LISTENERS) && !defined(USE_ESP8266)
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
/// Notify connect state listeners (called after state machine reaches STA_CONNECTED)
/// On ESP8266, this is handled by process_pending_callbacks_() instead.
void notify_connect_state_listeners_();
#endif
@@ -729,18 +728,18 @@ class WiFiComponent : public Component {
// Pending listener callbacks deferred from platform callbacks to main loop.
struct {
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
// Deferred until state machine reaches STA_CONNECTED so wifi.connected
// condition returns true in listener automations.
bool connect_state : 1;
#endif
#ifdef USE_ESP8266
// ESP8266 callbacks run in SDK system context with ~2KB stack where
// calling arbitrary listener callbacks is unsafe. These flags defer
// listener notifications to wifi_loop_() which runs with full stack.
bool connect : 1; // STA connected, notify listeners
bool disconnect : 1; // STA disconnected, notify listeners
bool got_ip : 1; // Got IP, notify listeners
bool scan_complete : 1; // Scan complete, notify listeners
#elif defined(USE_WIFI_CONNECT_STATE_LISTENERS)
// Non-ESP8266 platforms: deferred until state machine reaches STA_CONNECTED
// so wifi.connected condition returns true in listener automations.
bool connect_state : 1;
#endif
} pending_{};
@@ -515,8 +515,11 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
it.channel);
#endif
s_sta_connected = true;
// Defer listener callbacks to main loop - system context has limited stack
global_wifi_component->pending_.connect = true;
#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
global_wifi_component->pending_.connect_state = true;
#endif
break;
}
case EVENT_STAMODE_DISCONNECTED: {
@@ -959,24 +962,9 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddr
void WiFiComponent::wifi_loop_() { this->process_pending_callbacks_(); }
void WiFiComponent::process_pending_callbacks_() {
// Notify listeners for connect event (logging already done in callback)
if (this->pending_.connect) {
this->pending_.connect = false;
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
bssid_t bssid = this->wifi_bssid();
char ssid_buf[SSID_BUFFER_SIZE];
for (auto *listener : this->connect_state_listeners_) {
listener->on_wifi_connect_state(StringRef(this->wifi_ssid_to(ssid_buf)), bssid);
}
#endif
#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP)
if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) {
for (auto *listener : this->ip_state_listeners_) {
listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1));
}
}
#endif
}
// Process callbacks deferred from ESP8266 SDK system context (~2KB stack)
// to main loop context (full stack). Connect state listeners are handled
// by notify_connect_state_listeners_() in the shared state machine code.
// Notify listeners for disconnect event (logging already done in callback)
if (this->pending_.disconnect) {