From 13522c8f1944a85766b80a231be2d1b6296e71ca Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 2 Jul 2019 13:03:11 +0200 Subject: [PATCH] WIP: ESP8266 work on connection issues (#648) * Erase all flash for USB uploads on ESP8266s Previously, only erased "write regions". Downside: Config for other FWs like tasmota could be affected Upside: Potentially fixes some ESP8266 connection issues Related: https://github.com/esphome/issues/issues/455#issuecomment-503524479 * Clear WiFi settings for ESP8266 Clears wifi settings from retained storage on ESP8266 (if set). Unsure if this is the actual issue, but it won't cause problems either. * Update wifi_component_esp8266.cpp * Revert erase chip for testing * Improve wait_time calculation --- esphome/api/client.py | 2 +- esphome/components/wifi/wifi_component.cpp | 17 +--- esphome/components/wifi/wifi_component.h | 5 +- .../components/wifi/wifi_component_esp32.cpp | 11 ++- .../wifi/wifi_component_esp8266.cpp | 93 +++++++++++++------ 5 files changed, 84 insertions(+), 44 deletions(-) diff --git a/esphome/api/client.py b/esphome/api/client.py index 9306064a61..0c52674287 100644 --- a/esphome/api/client.py +++ b/esphome/api/client.py @@ -452,7 +452,7 @@ def run_logs(config, address): _LOGGER.info("Successfully connected to %s", address) return - wait_time = min(2**tries, 300) + wait_time = int(min(1.5**min(tries, 100), 30)) if not has_connects: _LOGGER.warning(u"Initial connection failed. The ESP might not be connected " u"to WiFi yet (%s). Re-Trying in %s seconds", diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index c111bc0025..7af6176402 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -31,22 +31,15 @@ float WiFiComponent::get_setup_priority() const { return setup_priority::WIFI; } void WiFiComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up WiFi..."); - this->last_connected_ = millis(); - - this->wifi_register_callbacks_(); - - bool ret = this->wifi_mode_(this->has_sta(), false); - if (!ret) { - this->mark_failed(); - return; - } + this->wifi_pre_setup_(); if (this->has_sta()) { - this->wifi_disable_auto_connect_(); - delay(10); + this->wifi_sta_pre_setup_(); - this->wifi_apply_power_save_(); + if (!this->wifi_apply_power_save_()) { + ESP_LOGV(TAG, "Setting Power Save Option failed!"); + } if (this->fast_connect_) { this->selected_ap_ = this->sta_[0]; diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index ffb3d6271f..cbdde7245f 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -181,17 +181,18 @@ class WiFiComponent : public Component { void print_connect_params_(); bool wifi_mode_(optional sta, optional ap); - bool wifi_disable_auto_connect_(); + bool wifi_sta_pre_setup_(); bool wifi_apply_power_save_(); bool wifi_sta_ip_config_(optional manual_ip); IPAddress wifi_sta_ip_(); bool wifi_apply_hostname_(); bool wifi_sta_connect_(WiFiAP ap); - void wifi_register_callbacks_(); + void wifi_pre_setup_(); wl_status_t wifi_sta_status_(); bool wifi_scan_start_(); bool wifi_ap_ip_config_(optional manual_ip); bool wifi_start_ap_(const WiFiAP &ap); + bool wifi_disconnect_(); bool is_captive_portal_active_(); diff --git a/esphome/components/wifi/wifi_component_esp32.cpp b/esphome/components/wifi/wifi_component_esp32.cpp index 9181e84981..87298f2608 100644 --- a/esphome/components/wifi/wifi_component_esp32.cpp +++ b/esphome/components/wifi/wifi_component_esp32.cpp @@ -53,8 +53,12 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { return ret; } -bool WiFiComponent::wifi_disable_auto_connect_() { +bool WiFiComponent::wifi_sta_pre_setup_() { + if (!this->wifi_mode_(true, {})) + return false; + WiFi.setAutoReconnect(false); + delay(10); return true; } bool WiFiComponent::wifi_apply_power_save_() { @@ -382,10 +386,12 @@ void WiFiComponent::wifi_event_callback_(system_event_id_t event, system_event_i this->wifi_scan_done_callback_(); } } -void WiFiComponent::wifi_register_callbacks_() { +void WiFiComponent::wifi_pre_setup_() { auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); WiFi.onEvent(f); WiFi.persistent(false); + // Make sure WiFi is in clean state before anything starts + this->wifi_mode_(false, false); } wl_status_t WiFiComponent::wifi_sta_status_() { return WiFi.status(); } bool WiFiComponent::wifi_scan_start_() { @@ -522,6 +528,7 @@ IPAddress WiFiComponent::wifi_soft_ap_ip() { tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip); return IPAddress(ip.ip.addr); } +bool WiFiComponent::wifi_disconnect_() { return esp_wifi_disconnect(); } } // namespace wifi } // namespace esphome diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index df22de361a..ed6e616b3d 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -58,19 +58,6 @@ bool WiFiComponent::wifi_mode_(optional sta, optional ap) { return ret; } -bool WiFiComponent::wifi_disable_auto_connect_() { - bool ret1, ret2; - ETS_UART_INTR_DISABLE(); - ret1 = wifi_station_set_auto_connect(0); - ret2 = wifi_station_set_reconnect_policy(false); - ETS_UART_INTR_ENABLE(); - - if (!ret1 || !ret2) { - ESP_LOGV(TAG, "Disabling Auto-Connect failed!"); - } - - return ret1 && ret2; -} bool WiFiComponent::wifi_apply_power_save_() { sleep_type_t power_save; switch (this->power_save_) { @@ -158,9 +145,7 @@ bool WiFiComponent::wifi_sta_connect_(WiFiAP ap) { if (!this->wifi_mode_(true, {})) return false; - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); + this->wifi_disconnect_(); struct station_config conf {}; memset(&conf, 0, sizeof(conf)); @@ -330,11 +315,6 @@ const char *get_disconnect_reason_str(uint8_t reason) { } void WiFiComponent::wifi_event_callback(System_Event_t *event) { - // TODO: this callback is called while in cont context, so delay will fail - // We need to defer the log messages until we're out of this context - // only affects verbose log level - // reproducible by enabling verbose log level and letting the ESP disconnect and - // then reconnect to WiFi. switch (event->event) { case EVENT_STAMODE_CONNECTED: { auto it = event->event_info.connected; @@ -410,7 +390,62 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { WiFiMockClass::_event_callback(event); } -void WiFiComponent::wifi_register_callbacks_() { wifi_set_event_handler_cb(&WiFiComponent::wifi_event_callback); } +bool WiFiComponent::wifi_sta_pre_setup_() { + if (!this->wifi_mode_(true, {})) + return false; + + // Clear saved STA config + station_config default_config{}; + wifi_station_get_config_default(&default_config); + bool is_zero = default_config.ssid[0] == '\0' && default_config.password[0] == '\0' && default_config.bssid[0] == 0 && + default_config.bssid_set == 0; + if (!is_zero) { + ESP_LOGV(TAG, "Clearing default wifi STA config"); + + memset(&default_config, 0, sizeof(default_config)); + ETS_UART_INTR_DISABLE(); + bool ret = wifi_station_set_config(&default_config); + ETS_UART_INTR_ENABLE(); + + if (!ret) { + ESP_LOGW(TAG, "Clearing default wif STA config failed!"); + } + } + + bool ret1, ret2; + ETS_UART_INTR_DISABLE(); + ret1 = wifi_station_set_auto_connect(0); + ret2 = wifi_station_set_reconnect_policy(false); + ETS_UART_INTR_ENABLE(); + + if (!ret1 || !ret2) { + ESP_LOGV(TAG, "Disabling Auto-Connect failed!"); + } + + delay(10); + return true; +} + +void WiFiComponent::wifi_pre_setup_() { + wifi_set_event_handler_cb(&WiFiComponent::wifi_event_callback); + // Make sure the default opmode is OFF + uint8_t default_opmode = wifi_get_opmode_default(); + if (default_opmode != 0) { + ESP_LOGV(TAG, "Setting default WiFi Mode to 0 (was %u)", default_opmode); + + ETS_UART_INTR_DISABLE(); + bool ret = wifi_set_opmode(0); + ETS_UART_INTR_ENABLE(); + + if (!ret) { + ESP_LOGW(TAG, "Setting default WiFi mode failed!"); + } + } + + // Make sure WiFi is in clean state before anything starts + this->wifi_mode_(false, false); +} + wl_status_t WiFiComponent::wifi_sta_status_() { station_status_t status = wifi_station_get_connect_status(); switch (status) { @@ -435,11 +470,6 @@ bool WiFiComponent::wifi_scan_start_() { if (!this->wifi_mode_(true, {})) return false; - station_status_t sta_status = wifi_station_get_connect_status(); - if (sta_status != STATION_GOT_IP && sta_status != STATION_IDLE) { - wifi_station_disconnect(); - } - struct scan_config config {}; memset(&config, 0, sizeof(config)); config.ssid = nullptr; @@ -465,6 +495,15 @@ bool WiFiComponent::wifi_scan_start_() { return ret; } +bool WiFiComponent::wifi_disconnect_() { + station_config conf{}; + memset(&conf, 0, sizeof(conf)); + ETS_UART_INTR_DISABLE(); + wifi_station_set_config(&conf); + bool ret = wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + return ret; +} void WiFiComponent::s_wifi_scan_done_callback(void *arg, STATUS status) { global_wifi_component->wifi_scan_done_callback_(arg, status); }