-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Eliminate gigantic blocking time inside ESP8266WiFiMulti::run #4888
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,7 @@ | |
#include <limits.h> | ||
#include <string.h> | ||
|
||
ESP8266WiFiMulti::ESP8266WiFiMulti() { | ||
ESP8266WiFiMulti::ESP8266WiFiMulti() : connect_timeout_ms(0) { | ||
} | ||
|
||
ESP8266WiFiMulti::~ESP8266WiFiMulti() { | ||
|
@@ -38,8 +38,104 @@ 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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only external dependency of this function is on WiFi. It doesn't depend on any WiFiMulti method or member. Therefore, there is no point of having the function in the class as a method. |
||
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() { | ||
wl_status_t status = WiFi.status(); | ||
// wait for connection, fail, or timeout | ||
if (status == WL_CONNECTED || | ||
status == WL_NO_SSID_AVAIL || | ||
status == WL_CONNECT_FAILED || | ||
(millis() > connect_timeout_ms)) | ||
{ | ||
handleConnectComplete(status); | ||
connect_timeout_ms = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a constructor-inited member, yet it is cleared here. Will it never be used again? Is there a need to init it again? |
||
} | ||
|
||
return status; | ||
} | ||
|
||
wl_status_t ESP8266WiFiMulti::run(void) { | ||
|
||
if (connect_timeout_ms != 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The timeout value is cleared above and never set again. Is that correct behavior? |
||
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) { | ||
|
||
|
@@ -66,98 +162,29 @@ wl_status_t ESP8266WiFiMulti::run(void) { | |
} | ||
|
||
if(scanResult > 0) { | ||
static const uint32_t connectTimeout = 5000; // 5s timeout | ||
|
||
// 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(); | ||
|
||
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); | ||
connect_timeout_ms = millis() + connectTimeout; | ||
|
||
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 | ||
} else { | ||
DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,8 @@ struct WifiAPEntry { | |
|
||
typedef std::vector<WifiAPEntry> WifiAPlist; | ||
|
||
struct BestNetwork; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If selectBest is removed from the class and made a static free standing function, there is no need to declare this here, because the definition in the .cpp is enough. Please remove. |
||
|
||
class ESP8266WiFiMulti { | ||
public: | ||
ESP8266WiFiMulti(); | ||
|
@@ -58,6 +60,12 @@ class ESP8266WiFiMulti { | |
|
||
private: | ||
WifiAPlist APlist; | ||
unsigned long connect_timeout_ms; | ||
|
||
void selectBest(BestNetwork& best, int8_t scanResult); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function should be removed from the class, see comment above. |
||
void handleConnectComplete(wl_status_t status); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a debug method, and there is also no need for it to be part of the class, or exported in the .h. Please remove and make the function a static free standing function in the .cpp. |
||
wl_status_t connectLoop(); | ||
|
||
bool APlistAdd(const char* ssid, const char *passphrase = NULL); | ||
void APlistClean(void); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function has no dependencies on other class members or methods, and is not public. Please make it a static free standing function.