From a1b949113257f29a24d9895fd836c96a62146773 Mon Sep 17 00:00:00 2001 From: Brad Roberts Date: Tue, 3 Jul 2018 19:45:54 -0700 Subject: [PATCH 1/2] ESP8266WiFiMulti: refactor ESP8266WiFiMulti::run in preparation for reducing blocking --- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 175 ++++++++++-------- libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h | 7 + 2 files changed, 105 insertions(+), 77 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 7bb7f3c61a..baf22d9aba 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -38,6 +38,98 @@ bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) { return APlistAdd(ssid, passphrase); } +void ESP8266WiFiMulti::handleConnectComplete(wl_status_t status) { +#ifdef DEBUG_ESP_WIFI + IPAddress ip; + uint8_t * mac; + switch(status) { + case WL_CONNECTED: + ip = WiFi.localIP(); + mac = WiFi.BSSID(); + DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); + DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID().c_str()); + DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); + break; + case WL_NO_SSID_AVAIL: + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed AP not found.\n"); + break; + case WL_CONNECT_FAILED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n"); + break; + default: + DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n", status); + break; + } +#else + (void)status; +#endif +} + +struct BestNetwork { + WifiAPEntry Network; + int NetworkDb; + uint8 BSSID[6]; + int32_t Channel; + + BestNetwork() : Network({NULL, NULL}), NetworkDb(INT_MIN) {} +}; + +void ESP8266WiFiMulti::selectBest(BestNetwork& best, int8_t scanResult) { + for(int8_t i = 0; i < scanResult; ++i) { + + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* BSSID_scan; + int32_t chan_scan; + bool hidden_scan; + + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); + + bool known = false; + for(auto entry : APlist) { + if(ssid_scan == entry.ssid) { // SSID match + known = true; + if(rssi_scan > best.NetworkDb) { // best network + if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan + best.NetworkDb = rssi_scan; + best.Channel = chan_scan; + best.Network = entry; + memcpy((void*) &best.BSSID, (void*) BSSID_scan, sizeof(best.BSSID)); + } + } + break; + } + } + + if(known) { + DEBUG_WIFI_MULTI(" ---> "); + } else { + DEBUG_WIFI_MULTI(" "); + } + + DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); + delay(0); + } +} + +wl_status_t ESP8266WiFiMulti::connectLoop() { + static const uint32_t connectTimeout = 5000; //5s timeout + + auto startTime = millis(); + wl_status_t status = WiFi.status(); + // wait for connection, fail, or timeout + while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED && (millis() - startTime) <= connectTimeout) { + delay(10); + status = WiFi.status(); + } + + handleConnectComplete(status); + return status; +} + wl_status_t ESP8266WiFiMulti::run(void) { wl_status_t status = WiFi.status(); @@ -67,51 +159,13 @@ wl_status_t ESP8266WiFiMulti::run(void) { if(scanResult > 0) { // scan done, analyze - WifiAPEntry bestNetwork { NULL, NULL }; - int bestNetworkDb = INT_MIN; - uint8 bestBSSID[6]; - int32_t bestChannel; + BestNetwork best; DEBUG_WIFI_MULTI("[WIFI] scan done\n"); delay(0); DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult); - for(int8_t i = 0; i < scanResult; ++i) { - - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* BSSID_scan; - int32_t chan_scan; - bool hidden_scan; - - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); - - bool known = false; - for(auto entry : APlist) { - if(ssid_scan == entry.ssid) { // SSID match - known = true; - if(rssi_scan > bestNetworkDb) { // best network - if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan - bestNetworkDb = rssi_scan; - bestChannel = chan_scan; - bestNetwork = entry; - memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID)); - } - } - break; - } - } - - if(known) { - DEBUG_WIFI_MULTI(" ---> "); - } else { - DEBUG_WIFI_MULTI(" "); - } - - DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); - delay(0); - } + selectBest(best, scanResult); // clean up ram WiFi.scanDelete(); @@ -119,45 +173,12 @@ wl_status_t ESP8266WiFiMulti::run(void) { DEBUG_WIFI_MULTI("\n\n"); delay(0); - if(bestNetwork.ssid) { - DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); + if(best.Network.ssid) { + DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)\n", best.BSSID[0], best.BSSID[1], best.BSSID[2], best.BSSID[3], best.BSSID[4], best.BSSID[5], best.Network.ssid, best.Channel, best.NetworkDb); - WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); - status = WiFi.status(); + WiFi.begin(best.Network.ssid, best.Network.passphrase, best.Channel, best.BSSID); - static const uint32_t connectTimeout = 5000; //5s timeout - - auto startTime = millis(); - // wait for connection, fail, or timeout - while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED && (millis() - startTime) <= connectTimeout) { - delay(10); - status = WiFi.status(); - } - -#ifdef DEBUG_ESP_WIFI - IPAddress ip; - uint8_t * mac; - switch(status) { - case WL_CONNECTED: - ip = WiFi.localIP(); - mac = WiFi.BSSID(); - DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); - DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID().c_str()); - DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); - DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); - break; - case WL_NO_SSID_AVAIL: - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed AP not found.\n"); - break; - case WL_CONNECT_FAILED: - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n"); - break; - default: - DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n", status); - break; - } -#endif + status = connectLoop(); } else { DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h index af8c00307b..4a8247258c 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -47,6 +47,8 @@ struct WifiAPEntry { typedef std::vector WifiAPlist; +struct BestNetwork; + class ESP8266WiFiMulti { public: ESP8266WiFiMulti(); @@ -58,6 +60,11 @@ class ESP8266WiFiMulti { private: WifiAPlist APlist; + + void selectBest(BestNetwork& best, int8_t scanResult); + void handleConnectComplete(wl_status_t status); + wl_status_t connectLoop(); + bool APlistAdd(const char* ssid, const char *passphrase = NULL); void APlistClean(void); From eb12b495bf4c64085548263a62145cd5919f234a Mon Sep 17 00:00:00 2001 From: Brad Roberts Date: Wed, 4 Jul 2018 00:32:15 -0700 Subject: [PATCH 2/2] ESP8266WiFiMulti: change the connection loop to be async --- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 24 ++++++++++++------- libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index baf22d9aba..bf1aabbd3d 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -27,7 +27,7 @@ #include #include -ESP8266WiFiMulti::ESP8266WiFiMulti() { +ESP8266WiFiMulti::ESP8266WiFiMulti() : connect_timeout_ms(0) { } ESP8266WiFiMulti::~ESP8266WiFiMulti() { @@ -116,22 +116,26 @@ void ESP8266WiFiMulti::selectBest(BestNetwork& best, int8_t scanResult) { } wl_status_t ESP8266WiFiMulti::connectLoop() { - static const uint32_t connectTimeout = 5000; //5s timeout - - auto startTime = millis(); wl_status_t status = WiFi.status(); // wait for connection, fail, or timeout - while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED && (millis() - startTime) <= connectTimeout) { - delay(10); - status = WiFi.status(); + if (status == WL_CONNECTED || + status == WL_NO_SSID_AVAIL || + status == WL_CONNECT_FAILED || + (millis() > connect_timeout_ms)) + { + handleConnectComplete(status); + connect_timeout_ms = 0; } - handleConnectComplete(status); return status; } wl_status_t ESP8266WiFiMulti::run(void) { + if (connect_timeout_ms != 0) { + return connectLoop(); + } + wl_status_t status = WiFi.status(); if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) { @@ -158,6 +162,8 @@ wl_status_t ESP8266WiFiMulti::run(void) { } if(scanResult > 0) { + static const uint32_t connectTimeout = 5000; // 5s timeout + // scan done, analyze BestNetwork best; @@ -177,8 +183,8 @@ wl_status_t ESP8266WiFiMulti::run(void) { DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channel: %d (%d)\n", best.BSSID[0], best.BSSID[1], best.BSSID[2], best.BSSID[3], best.BSSID[4], best.BSSID[5], best.Network.ssid, best.Channel, best.NetworkDb); WiFi.begin(best.Network.ssid, best.Network.passphrase, best.Channel, best.BSSID); + connect_timeout_ms = millis() + connectTimeout; - status = connectLoop(); } else { DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h index 4a8247258c..dbe35eac80 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -60,6 +60,7 @@ class ESP8266WiFiMulti { private: WifiAPlist APlist; + unsigned long connect_timeout_ms; void selectBest(BestNetwork& best, int8_t scanResult); void handleConnectComplete(wl_status_t status);