[wifi] Avoid redundant SDK calls in WiFi loop on ESP8266

Replace five separate boolean state variables in the ESP8266 WiFi
implementation with a single enum state machine, matching the pattern
already used by LibreTiny. This eliminates the per-loop call to
wifi_station_get_connect_status() by reading cached state from the
existing event callback instead.

Also use the cached connected_ field (set unconditionally at the top
of loop()) in the STA_CONNECTED branch instead of calling
is_connected_() a second time. This applies to all platforms.
This commit is contained in:
J. Nick Koston
2026-03-29 17:55:55 -10:00
parent 18168ad7fd
commit f43a598a83
2 changed files with 34 additions and 27 deletions
+2 -1
View File
@@ -784,7 +784,8 @@ void WiFiComponent::loop() {
}
case WIFI_COMPONENT_STATE_STA_CONNECTED: {
if (!this->is_connected_()) {
// Use cached connected_ set unconditionally at the top of loop()
if (!this->connected_) {
ESP_LOGW(TAG, "Connection lost; reconnecting");
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
this->retry_connect();
@@ -44,11 +44,17 @@ namespace esphome::wifi {
static const char *const TAG = "wifi_esp8266";
static bool s_sta_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static bool s_sta_got_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static bool s_sta_connect_not_found = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static bool s_sta_connect_error = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
enum class ESP8266WiFiSTAState : uint8_t {
IDLE, // Not connecting
CONNECTING, // Connection in progress
ASSOCIATED, // Associated to AP, waiting for IP
CONNECTED, // Successfully connected with IP
ERROR_NOT_FOUND, // AP not found (probe failed)
ERROR_FAILED, // Connection failed (auth, timeout, etc.)
};
static ESP8266WiFiSTAState s_sta_state =
ESP8266WiFiSTAState::IDLE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
uint8_t current_mode = wifi_get_opmode();
@@ -359,11 +365,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
// Reset flags, do this _before_ wifi_station_connect as the callback method
// may be called from wifi_station_connect
s_sta_connecting = true;
s_sta_connected = false;
s_sta_got_ip = false;
s_sta_connect_error = false;
s_sta_connect_not_found = false;
s_sta_state = ESP8266WiFiSTAState::CONNECTING;
ETS_UART_INTR_DISABLE();
ret = wifi_station_connect();
@@ -493,7 +495,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
ESP_LOGV(TAG, "Connected ssid='%.*s' bssid=%s channel=%u", it.ssid_len, (const char *) it.ssid, bssid_buf,
it.channel);
#endif
s_sta_connected = true;
s_sta_state = ESP8266WiFiSTAState::ASSOCIATED;
#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
@@ -506,16 +508,14 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
if (it.reason == REASON_NO_AP_FOUND) {
ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len,
(const char *) it.ssid);
s_sta_connect_not_found = true;
s_sta_state = ESP8266WiFiSTAState::ERROR_NOT_FOUND;
} else {
char bssid_s[18];
format_mac_addr_upper(it.bssid, bssid_s);
ESP_LOGW(TAG, "Disconnected ssid='%.*s' bssid=" LOG_SECRET("%s") " reason='%s'", it.ssid_len,
(const char *) it.ssid, bssid_s, LOG_STR_ARG(get_disconnect_reason_str(it.reason)));
s_sta_connect_error = true;
s_sta_state = ESP8266WiFiSTAState::ERROR_FAILED;
}
s_sta_connected = false;
s_sta_connecting = false;
global_wifi_component->error_from_callback_ = true;
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
global_wifi_component->pending_.disconnect = true;
@@ -541,7 +541,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
mask_buf[network::IP_ADDRESS_BUFFER_SIZE];
ESP_LOGV(TAG, "static_ip=%s gateway=%s netmask=%s", network::IPAddress(&it.ip).str_to(ip_buf),
network::IPAddress(&it.gw).str_to(gw_buf), network::IPAddress(&it.mask).str_to(mask_buf));
s_sta_got_ip = true;
s_sta_state = ESP8266WiFiSTAState::CONNECTED;
#ifdef USE_WIFI_IP_STATE_LISTENERS
// Defer listener callbacks to main loop - system context has limited stack
global_wifi_component->pending_.got_ip = true;
@@ -636,16 +636,22 @@ void WiFiComponent::wifi_pre_setup_() {
}
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const {
station_status_t status = wifi_station_get_connect_status();
if (status == STATION_GOT_IP)
return WiFiSTAConnectStatus::CONNECTED;
if (status == STATION_NO_AP_FOUND)
return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND;
if (status == STATION_CONNECT_FAIL || status == STATION_WRONG_PASSWORD)
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
if (status == STATION_CONNECTING)
return WiFiSTAConnectStatus::CONNECTING;
return WiFiSTAConnectStatus::IDLE;
// Use cached state from wifi_event_callback() instead of calling
// wifi_station_get_connect_status() which queries the SDK every time
switch (s_sta_state) {
case ESP8266WiFiSTAState::CONNECTED:
return WiFiSTAConnectStatus::CONNECTED;
case ESP8266WiFiSTAState::ERROR_NOT_FOUND:
return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND;
case ESP8266WiFiSTAState::ERROR_FAILED:
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
case ESP8266WiFiSTAState::CONNECTING:
case ESP8266WiFiSTAState::ASSOCIATED:
return WiFiSTAConnectStatus::CONNECTING;
case ESP8266WiFiSTAState::IDLE:
default:
return WiFiSTAConnectStatus::IDLE;
}
}
bool WiFiComponent::wifi_scan_start_(bool passive) {
// enable STA