mirror of
https://github.com/esphome/esphome.git
synced 2026-05-29 23:07:16 +08:00
[wifi] Avoid redundant SDK calls in WiFi loop on ESP8266 (#15303)
This commit is contained in:
@@ -784,7 +784,8 @@ void WiFiComponent::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case WIFI_COMPONENT_STATE_STA_CONNECTED: {
|
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");
|
ESP_LOGW(TAG, "Connection lost; reconnecting");
|
||||||
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
|
this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING;
|
||||||
this->retry_connect();
|
this->retry_connect();
|
||||||
@@ -2129,11 +2130,6 @@ void WiFiComponent::retry_connect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
|
||||||
bool WiFiComponent::is_connected_() const {
|
|
||||||
return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED &&
|
|
||||||
this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_;
|
|
||||||
}
|
|
||||||
void WiFiComponent::update_connected_state_() { this->connected_ = this->is_connected_(); }
|
|
||||||
void WiFiComponent::set_power_save_mode(WiFiPowerSaveMode power_save) {
|
void WiFiComponent::set_power_save_mode(WiFiPowerSaveMode power_save) {
|
||||||
this->power_save_ = power_save;
|
this->power_save_ = power_save;
|
||||||
#if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE)
|
#if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE)
|
||||||
|
|||||||
@@ -670,8 +670,11 @@ class WiFiComponent final : public Component {
|
|||||||
bool wifi_sta_connect_(const WiFiAP &ap);
|
bool wifi_sta_connect_(const WiFiAP &ap);
|
||||||
void wifi_pre_setup_();
|
void wifi_pre_setup_();
|
||||||
WiFiSTAConnectStatus wifi_sta_connect_status_() const;
|
WiFiSTAConnectStatus wifi_sta_connect_status_() const;
|
||||||
bool is_connected_() const;
|
bool is_connected_() const {
|
||||||
void update_connected_state_();
|
return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED &&
|
||||||
|
this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_;
|
||||||
|
}
|
||||||
|
void update_connected_state_() { this->connected_ = this->is_connected_(); }
|
||||||
bool wifi_scan_start_(bool passive);
|
bool wifi_scan_start_(bool passive);
|
||||||
|
|
||||||
#ifdef USE_WIFI_AP
|
#ifdef USE_WIFI_AP
|
||||||
@@ -811,6 +814,12 @@ class WiFiComponent final : public Component {
|
|||||||
uint8_t num_ipv6_addresses_{0};
|
uint8_t num_ipv6_addresses_{0};
|
||||||
#endif /* USE_NETWORK_IPV6 */
|
#endif /* USE_NETWORK_IPV6 */
|
||||||
bool error_from_callback_{false};
|
bool error_from_callback_{false};
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
// ESP8266WiFiSTAState enum, defined in wifi_component_esp8266.cpp.
|
||||||
|
// Written from SDK system context (wifi_event_callback) — uint8_t writes
|
||||||
|
// are atomic on Xtensa LX106 so no synchronization is needed.
|
||||||
|
uint8_t sta_state_{0};
|
||||||
|
#endif
|
||||||
RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY};
|
RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY};
|
||||||
RoamingState roaming_state_{RoamingState::IDLE};
|
RoamingState roaming_state_{RoamingState::IDLE};
|
||||||
bssid_t roaming_target_bssid_{}; // BSSID of the AP we're trying to roam to
|
bssid_t roaming_target_bssid_{}; // BSSID of the AP we're trying to roam to
|
||||||
|
|||||||
@@ -44,11 +44,14 @@ namespace esphome::wifi {
|
|||||||
|
|
||||||
static const char *const TAG = "wifi_esp8266";
|
static const char *const TAG = "wifi_esp8266";
|
||||||
|
|
||||||
static bool s_sta_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
enum class ESP8266WiFiSTAState : uint8_t {
|
||||||
static bool s_sta_got_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
IDLE, // Not connecting
|
||||||
static bool s_sta_connect_not_found = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
CONNECTING, // Connection in progress
|
||||||
static bool s_sta_connect_error = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
ASSOCIATED, // Associated to AP, waiting for IP
|
||||||
static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
CONNECTED, // Successfully connected with IP
|
||||||
|
ERROR_NOT_FOUND, // AP not found (probe failed)
|
||||||
|
ERROR_FAILED, // Connection failed (auth, timeout, etc.)
|
||||||
|
};
|
||||||
|
|
||||||
bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
|
bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
|
||||||
uint8_t current_mode = wifi_get_opmode();
|
uint8_t current_mode = wifi_get_opmode();
|
||||||
@@ -359,11 +362,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
|
|||||||
|
|
||||||
// Reset flags, do this _before_ wifi_station_connect as the callback method
|
// Reset flags, do this _before_ wifi_station_connect as the callback method
|
||||||
// may be called from wifi_station_connect
|
// may be called from wifi_station_connect
|
||||||
s_sta_connecting = true;
|
this->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::CONNECTING);
|
||||||
s_sta_connected = false;
|
|
||||||
s_sta_got_ip = false;
|
|
||||||
s_sta_connect_error = false;
|
|
||||||
s_sta_connect_not_found = false;
|
|
||||||
|
|
||||||
ETS_UART_INTR_DISABLE();
|
ETS_UART_INTR_DISABLE();
|
||||||
ret = wifi_station_connect();
|
ret = wifi_station_connect();
|
||||||
@@ -493,7 +492,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,
|
ESP_LOGV(TAG, "Connected ssid='%.*s' bssid=%s channel=%u", it.ssid_len, (const char *) it.ssid, bssid_buf,
|
||||||
it.channel);
|
it.channel);
|
||||||
#endif
|
#endif
|
||||||
s_sta_connected = true;
|
global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ASSOCIATED);
|
||||||
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
|
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
|
||||||
// Defer listener notification until state machine reaches STA_CONNECTED
|
// Defer listener notification until state machine reaches STA_CONNECTED
|
||||||
// This ensures wifi.connected condition returns true in listener automations
|
// This ensures wifi.connected condition returns true in listener automations
|
||||||
@@ -506,16 +505,14 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
|
|||||||
if (it.reason == REASON_NO_AP_FOUND) {
|
if (it.reason == REASON_NO_AP_FOUND) {
|
||||||
ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len,
|
ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len,
|
||||||
(const char *) it.ssid);
|
(const char *) it.ssid);
|
||||||
s_sta_connect_not_found = true;
|
global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_NOT_FOUND);
|
||||||
} else {
|
} else {
|
||||||
char bssid_s[18];
|
char bssid_s[18];
|
||||||
format_mac_addr_upper(it.bssid, bssid_s);
|
format_mac_addr_upper(it.bssid, bssid_s);
|
||||||
ESP_LOGW(TAG, "Disconnected ssid='%.*s' bssid=" LOG_SECRET("%s") " reason='%s'", it.ssid_len,
|
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)));
|
(const char *) it.ssid, bssid_s, LOG_STR_ARG(get_disconnect_reason_str(it.reason)));
|
||||||
s_sta_connect_error = true;
|
global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_FAILED);
|
||||||
}
|
}
|
||||||
s_sta_connected = false;
|
|
||||||
s_sta_connecting = false;
|
|
||||||
global_wifi_component->error_from_callback_ = true;
|
global_wifi_component->error_from_callback_ = true;
|
||||||
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
|
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS
|
||||||
global_wifi_component->pending_.disconnect = true;
|
global_wifi_component->pending_.disconnect = true;
|
||||||
@@ -541,7 +538,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
|
|||||||
mask_buf[network::IP_ADDRESS_BUFFER_SIZE];
|
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),
|
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));
|
network::IPAddress(&it.gw).str_to(gw_buf), network::IPAddress(&it.mask).str_to(mask_buf));
|
||||||
s_sta_got_ip = true;
|
global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::CONNECTED);
|
||||||
#ifdef USE_WIFI_IP_STATE_LISTENERS
|
#ifdef USE_WIFI_IP_STATE_LISTENERS
|
||||||
// Defer listener callbacks to main loop - system context has limited stack
|
// Defer listener callbacks to main loop - system context has limited stack
|
||||||
global_wifi_component->pending_.got_ip = true;
|
global_wifi_component->pending_.got_ip = true;
|
||||||
@@ -636,17 +633,22 @@ void WiFiComponent::wifi_pre_setup_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const {
|
WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const {
|
||||||
station_status_t status = wifi_station_get_connect_status();
|
// Use cached state from wifi_event_callback() instead of calling
|
||||||
if (status == STATION_GOT_IP)
|
// wifi_station_get_connect_status() which queries the SDK every time.
|
||||||
|
// Use if statements with early returns instead of switch to avoid GCC
|
||||||
|
// generating a CSWTCH lookup table in .rodata (flash) on ESP8266.
|
||||||
|
auto state = static_cast<ESP8266WiFiSTAState>(this->sta_state_);
|
||||||
|
if (state == ESP8266WiFiSTAState::CONNECTED)
|
||||||
return WiFiSTAConnectStatus::CONNECTED;
|
return WiFiSTAConnectStatus::CONNECTED;
|
||||||
if (status == STATION_NO_AP_FOUND)
|
if (state == ESP8266WiFiSTAState::ERROR_NOT_FOUND)
|
||||||
return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND;
|
return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND;
|
||||||
if (status == STATION_CONNECT_FAIL || status == STATION_WRONG_PASSWORD)
|
if (state == ESP8266WiFiSTAState::ERROR_FAILED)
|
||||||
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
|
return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED;
|
||||||
if (status == STATION_CONNECTING)
|
if (state == ESP8266WiFiSTAState::CONNECTING || state == ESP8266WiFiSTAState::ASSOCIATED)
|
||||||
return WiFiSTAConnectStatus::CONNECTING;
|
return WiFiSTAConnectStatus::CONNECTING;
|
||||||
return WiFiSTAConnectStatus::IDLE;
|
return WiFiSTAConnectStatus::IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiFiComponent::wifi_scan_start_(bool passive) {
|
bool WiFiComponent::wifi_scan_start_(bool passive) {
|
||||||
// enable STA
|
// enable STA
|
||||||
if (!this->wifi_mode_(true, {}))
|
if (!this->wifi_mode_(true, {}))
|
||||||
|
|||||||
Reference in New Issue
Block a user