From 50c7586f649e9c2209cd973152797196c158dd12 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Sun, 24 Jan 2021 18:41:42 +0200 Subject: [PATCH 1/8] Don't block while waiting for WiFi to connect --- src/net/networking.cpp | 64 ++++++++++++++++++++++++------------------ src/net/networking.h | 7 ++++- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index c5156b9bc..2321fc1dd 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -38,19 +38,6 @@ Networking::Networking(String config_path, String ssid, String password, wifi_manager = new AsyncWiFiManager(server, dns); } -void Networking::check_connection() { - if (WiFi.status() != WL_CONNECTED) { - // if connection is lost, simply restart - debugD("Wifi disconnected: restarting..."); - - // Might be futile to notify about a disconnection if it results in - // a reboot anyway - this->emit(WifiState::kWifiDisconnected); - - ESP.restart(); - } -} - void Networking::setup() { if (ap_ssid != "" && ap_password != "") { setup_saved_ssid(); @@ -58,38 +45,59 @@ void Networking::setup() { if (ap_ssid == "" && WiFi.status() != WL_CONNECTED) { setup_wifi_manager(); } - app.onRepeat(1000, std::bind(&Networking::check_connection, this)); +} + +void Networking::setup_wifi_callbacks() { +#if defined(ESP8266) + WiFi.onStationModeConnected([this](const WiFiEventStationModeConnected& event) { + this->wifi_station_connected(); + }); + WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected& event) { + this->wifi_station_disconnected(); + }); +#elif defined(ESP32) + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { + this->wifi_station_connected(); + }, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP); + WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { + this->wifi_station_disconnected(); + }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); +#endif } void Networking::setup_saved_ssid() { - WiFi.begin(ap_ssid.c_str(), ap_password.c_str()); this->emit(WifiState::kWifiDisconnected); - + setup_wifi_callbacks(); + WiFi.begin(ap_ssid.c_str(), ap_password.c_str()); + uint32_t timer_start = millis(); debugI("Connecting to wifi %s.", ap_ssid.c_str()); - int printCounter = 0; - while (WiFi.status() != WL_CONNECTED && - (millis() - timer_start) < 3 * 60 * 1000) { - delay(500); - if (printCounter % 4) { - debugI("Wifi status=%d, time=%d ms", WiFi.status(), 500 * printCounter); - } - printCounter++; - } +} - if (WiFi.status() == WL_CONNECTED) { +void Networking::wifi_station_connected() { debugI("Connected to wifi, SSID: %s (signal: %d)", WiFi.SSID().c_str(), WiFi.RSSI()); debugI("IP address of Device: %s", WiFi.localIP().toString().c_str()); this->emit(WifiState::kWifiConnectedToAP); - WiFi.mode(WIFI_STA); - } +} + +void Networking::wifi_station_disconnected() { + // if connection is lost, simply restart + debugD("Wifi disconnected"); + + // Might be futile to notify about a disconnection if it results in + // a reboot anyway + this->emit(WifiState::kWifiDisconnected); + + //ESP.restart(); } void Networking::setup_wifi_manager() { should_save_config = false; + setup_wifi_callbacks(); + // set config save notify callback wifi_manager->setSaveConfigCallback(save_config_callback); diff --git a/src/net/networking.h b/src/net/networking.h index c5b865d56..1f87398f9 100644 --- a/src/net/networking.h +++ b/src/net/networking.h @@ -33,10 +33,15 @@ class Networking : public Configurable, public ValueProducer { void reset_settings(); protected: - void check_connection(); void setup_saved_ssid(); + void setup_wifi_callbacks(); void setup_wifi_manager(); + // callbacks + + void wifi_station_connected(); + void wifi_station_disconnected(); + private: AsyncWebServer* server; // FIXME: DNSServer and AsyncWiFiManager could be instantiated in From d499fc7b51c2e309aa1da2580a60b9ad7b576bca Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Sun, 24 Jan 2021 20:23:06 +0200 Subject: [PATCH 2/8] Move the wifi connection watchdog from networking to sensesp_app.cpp --- src/net/networking.cpp | 7 ------- src/sensesp_app.cpp | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index 2321fc1dd..f6d875429 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -83,14 +83,7 @@ void Networking::wifi_station_connected() { } void Networking::wifi_station_disconnected() { - // if connection is lost, simply restart - debugD("Wifi disconnected"); - - // Might be futile to notify about a disconnection if it results in - // a reboot anyway this->emit(WifiState::kWifiDisconnected); - - //ESP.restart(); } void Networking::setup_wifi_manager() { diff --git a/src/sensesp_app.cpp b/src/sensesp_app.cpp index bb4e16d00..909534c32 100644 --- a/src/sensesp_app.cpp +++ b/src/sensesp_app.cpp @@ -15,6 +15,7 @@ #include "signalk/signalk_output.h" #include "system/spiffs_storage.h" #include "system/system_status_led.h" +#include "transforms/debounce.h" #include "transforms/difference.h" #include "transforms/frequency.h" #include "transforms/linear.h" @@ -99,6 +100,21 @@ void SensESPApp::setup() { this->networking_->connect_to(&system_status_controller_); this->ws_client_->connect_to(&system_status_controller_); + // create the wifi disconnect watchdog + + this->system_status_controller_ + .connect_to(new DebounceTemplate( + 3*60*1000, // 180 s = 180000 ms = 3 minutes + "/system/wifi_reboot_watchdog")) + ->connect_to(new LambdaConsumer([](SystemStatus input) { + debugD("Got system status: %d", (int)input); + if (input == SystemStatus::kWifiDisconnected || + input == SystemStatus::kWifiNoAP) { + debugW("Unable to connect to wifi for too long; restarting."); + app.onDelay(1000, []() { ESP.restart(); }); + } + })); + // create a system status led and connect it if (system_status_led_ == NULL) { @@ -181,7 +197,7 @@ void SensESPApp::reset() { debugW("Resetting the device configuration."); networking_->reset_settings(); SPIFFS.format(); - app.onDelay(1000, []() { ESP.restart(); }); + app.onDelay(1000, []() { ESP.restart(); delay(1000); }); } String SensESPApp::get_hostname() { return networking_->get_hostname()->get(); } From ca2f4605f6b1c3fbbe7c58af397a7693b3c89881 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:32:52 +0200 Subject: [PATCH 3/8] Make WifiDisconnected have precedence over Disconnected --- src/controllers/system_status_controller.cpp | 21 ++++++++++++-------- src/controllers/system_status_controller.h | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/controllers/system_status_controller.cpp b/src/controllers/system_status_controller.cpp index 2b82ff1fc..d7888ccc4 100644 --- a/src/controllers/system_status_controller.cpp +++ b/src/controllers/system_status_controller.cpp @@ -6,16 +6,16 @@ void SystemStatusController::set_input(WifiState new_value, // this would be a simple array dereferencing switch (new_value) { case WifiState::kWifiNoAP: - this->emit(SystemStatus::kWifiNoAP); + this->update_state(SystemStatus::kWifiNoAP); break; case WifiState::kWifiDisconnected: - this->emit(SystemStatus::kWifiDisconnected); + this->update_state(SystemStatus::kWifiDisconnected); break; case WifiState::kWifiConnectedToAP: - this->emit(SystemStatus::kWSDisconnected); + this->update_state(SystemStatus::kWSDisconnected); break; case WifiState::kWifiManagerActivated: - this->emit(SystemStatus::kWifiManagerActivated); + this->update_state(SystemStatus::kWifiManagerActivated); break; } } @@ -24,16 +24,21 @@ void SystemStatusController::set_input(WSConnectionState new_value, uint8_t input_channel) { switch (new_value) { case WSConnectionState::kWSDisconnected: - this->emit(SystemStatus::kWSDisconnected); + if (current_state_ != SystemStatus::kWifiDisconnected && + current_state_ != SystemStatus::kWifiNoAP && + current_state_ != SystemStatus::kWifiManagerActivated) { + // Wifi disconnection states override the higher level protocol state + this->update_state(SystemStatus::kWSDisconnected); + } break; case WSConnectionState::kWSConnecting: - this->emit(SystemStatus::kWSConnecting); + this->update_state(SystemStatus::kWSConnecting); break; case WSConnectionState::kWSAuthorizing: - this->emit(SystemStatus::kWSAuthorizing); + this->update_state(SystemStatus::kWSAuthorizing); break; case WSConnectionState::kWSConnected: - this->emit(SystemStatus::kWSConnected); + this->update_state(SystemStatus::kWSConnected); break; } } diff --git a/src/controllers/system_status_controller.h b/src/controllers/system_status_controller.h index e5010ec57..0d4e4e9ad 100644 --- a/src/controllers/system_status_controller.h +++ b/src/controllers/system_status_controller.h @@ -36,6 +36,13 @@ class SystemStatusController : public ValueConsumer, /// (WSClient object state updates) virtual void set_input(WSConnectionState new_value, uint8_t input_channel = 0) override; + protected: + void update_state(const SystemStatus new_state) { + current_state_ = new_state; + this->emit(new_state); + } + private: + SystemStatus current_state_ = SystemStatus::kWifiNoAP; }; #endif \ No newline at end of file From 65047089500dbee177981ff19750cec35165c55f Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:34:29 +0200 Subject: [PATCH 4/8] Save the handle to event handlers on ESP8266 --- src/net/networking.cpp | 14 ++++++++------ src/net/networking.h | 13 ++++++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index f6d875429..ab2afa23d 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -49,12 +49,14 @@ void Networking::setup() { void Networking::setup_wifi_callbacks() { #if defined(ESP8266) - WiFi.onStationModeConnected([this](const WiFiEventStationModeConnected& event) { - this->wifi_station_connected(); - }); - WiFi.onStationModeDisconnected([this](const WiFiEventStationModeDisconnected& event) { - this->wifi_station_disconnected(); - }); + got_ip_event_handler_ = + WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& event) { + this->wifi_station_connected(); + }); + wifi_disconnected_event_handler_ = WiFi.onStationModeDisconnected( + [this](const WiFiEventStationModeDisconnected& event) { + this->wifi_station_disconnected(); + }); #elif defined(ESP32) WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { this->wifi_station_connected(); diff --git a/src/net/networking.h b/src/net/networking.h index 1f87398f9..2268ffd49 100644 --- a/src/net/networking.h +++ b/src/net/networking.h @@ -3,6 +3,10 @@ #include "Arduino.h" +#ifdef ESP8266 +#include +#endif + // Local WebServer used to serve the configuration portal #include #include @@ -19,7 +23,7 @@ enum class WifiState { }; /** - * @brief Manages the ESP's connection to the Wifi network. + * @brief Manages the ESP's connection to the Wifi network. */ class Networking : public Configurable, public ValueProducer { public: @@ -48,6 +52,13 @@ class Networking : public Configurable, public ValueProducer { // respective methods to save some runtime memory DNSServer* dns; AsyncWiFiManager* wifi_manager; + +#ifdef ESP8266 + // event handlers must be saved to keep the handlers activated + WiFiEventHandler got_ip_event_handler_; + WiFiEventHandler wifi_disconnected_event_handler_; +#endif + ObservableValue* hostname; String ap_ssid = ""; String ap_password = ""; From f2d8e73e406888fa30dc9efaebf09ca0fa6f1cc3 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:35:29 +0200 Subject: [PATCH 5/8] Remove an unused variable --- src/net/networking.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index ab2afa23d..dffb17214 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -71,8 +71,6 @@ void Networking::setup_saved_ssid() { this->emit(WifiState::kWifiDisconnected); setup_wifi_callbacks(); WiFi.begin(ap_ssid.c_str(), ap_password.c_str()); - - uint32_t timer_start = millis(); debugI("Connecting to wifi %s.", ap_ssid.c_str()); } From a336b4ebcba313be591cc001a6858cccea2d1ad8 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:35:55 +0200 Subject: [PATCH 6/8] Don't save wifi settings on SPIFFS --- src/net/networking.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index dffb17214..a846bddcf 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -163,21 +163,13 @@ String Networking::get_config_schema() { // Config UI. If preset_hostname is not "SensESP", then it was set in // main.cpp, so it should be read-only. bool hostname_preset = preset_hostname != "SensESP"; - bool wifi_preset = preset_ssid != ""; return String(FPSTR(SCHEMA_PREFIX)) + get_property_row("hostname", "ESP device hostname", hostname_preset) + - "," + - get_property_row("ap_ssid", "Wifi Access Point SSID", wifi_preset) + - "," + - get_property_row("ap_password", "Wifi Access Point Password", - wifi_preset) + "}}"; } void Networking::get_configuration(JsonObject& root) { root["hostname"] = this->hostname->get(); - root["ap_ssid"] = this->ap_ssid; - root["ap_password"] = this->ap_password; } bool Networking::set_configuration(const JsonObject& config) { @@ -189,11 +181,6 @@ bool Networking::set_configuration(const JsonObject& config) { this->hostname->set(config["hostname"].as()); } - if (preset_ssid == "") { - debugW("Using saved SSID and password"); - this->ap_ssid = config["ap_ssid"].as(); - this->ap_password = config["ap_password"].as(); - } return true; } From f630fcf0eb4f8b869632c42bda1dfb7c37dace77 Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:36:26 +0200 Subject: [PATCH 7/8] Invalidate old wifi settings on reset --- src/net/networking.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index a846bddcf..f766ba456 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -189,5 +189,8 @@ void Networking::reset_settings() { ap_password = preset_password; save_configuration(); - wifi_manager->resetSettings(); + WiFi.disconnect(true); + // On ESP32, disconnect does not erase previous credentials. Let's connect + // to a bogus network instead + WiFi.begin("0", "0"); } From 095fd055d60a25ff9c18bc5e9a813963ae4646bb Mon Sep 17 00:00:00 2001 From: Matti Airas Date: Mon, 25 Jan 2021 14:38:09 +0200 Subject: [PATCH 8/8] Add a bit of debugging for wifi state --- src/net/networking.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/networking.cpp b/src/net/networking.cpp index f766ba456..399d8a053 100644 --- a/src/net/networking.cpp +++ b/src/net/networking.cpp @@ -83,6 +83,7 @@ void Networking::wifi_station_connected() { } void Networking::wifi_station_disconnected() { + debugI("Disconnected from wifi."); this->emit(WifiState::kWifiDisconnected); }