Skip to content
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

Include hidden SSID's, scan lists of APs #3464

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion libraries/WiFi/examples/WiFiMulti/WiFiMulti.ino
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ void setup()
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");

Serial.println("Connecting Wifi...");

/*
* wifiMulti.run() with no arguments defaults to
* a connectTimeout of 5000 ms and scanHidden of false.
* These defaults can be found in ../../src/WiFiMulti.h
*
* The default of wifiMulti.run() will scan for the AP's
* added above and will not locate SSIDs that are hidden.
*
* To find both visible and hidden SSIDs, one makes the
* call as follows: wifiMulti.run(5000,true) which will
* scan and connect to visible and hidden SSIDs if the
* password credentials match.
*
*/

/* scan and connect to visible APs */
if(wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Expand All @@ -32,4 +49,4 @@ void loop()
Serial.println("WiFi not connected!");
delay(1000);
}
}
}
149 changes: 79 additions & 70 deletions libraries/WiFi/src/WiFiMulti.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,38 +85,42 @@ bool WiFiMulti::addAP(const char* ssid, const char *passphrase)
return true;
}

uint8_t WiFiMulti::run(uint32_t connectTimeout)
uint8_t WiFiMulti::run(uint32_t connectTimeout, bool scanHidden)
{
int8_t scanResult;
uint8_t status = WiFi.status();
int8_t ci = 0;

if(status == WL_CONNECTED) {
for(uint32_t x = 0; x < APlist.size(); x++) {
if(WiFi.SSID()==APlist[x].ssid) {
return status;
}
}
WiFi.disconnect(false,false);
delay(10);

WiFi.persistent(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks hacky, what is its purpose?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard WiFiMulti code will scan for all SSID it can see, and connected you to one that you have requested if it is available... It will show you some information about the hidden SSID, BUT! if the SSID your requesting is hidden, it will NOT connect you to that SSID. The logic in the code is wrong.

The modification we made to WiFiMulti in the pull request above, will connect you to a hidden SSID if it is available....

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lower level implementation details of WiFi.disconnect() are not available for me to examine and determine why the delay is required. Through numerous experiments on a number of secured, unsecured, hidden, and visible SSIDs the delay creates a high degree of success when trying subsequent network connections. The delay put in place when connecting to hidden SSID's was also determined experimentally and results in successful connections almost every time. Removing the delay causes the connections to fail due to the asynchronous nature of the lower level wifi drivers.

Copy link
Contributor

@tablatronix tablatronix Jan 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like an esp32 equivalent to esp8266/Arduino#4372
I have not encountered this issue on esp32, do you have demo code. I suggest the actual problem be investigated. This comment however was specifically aimed at WiFi.persistent(false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My esp32 is not responding

WiFi.disconnect(false,false);
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
delay(200);
status = WiFi.status();
}

scanResult = WiFi.scanNetworks();
scanResult = WiFi.scanNetworks(false, scanHidden);
if(scanResult == WIFI_SCAN_RUNNING) {
// scan is running
return WL_NO_SSID_AVAIL;
} else if(scanResult >= 0) {
// scan done analyze
WifiAPlist_t bestNetwork { NULL, NULL };
int bestNetworkDb = INT_MIN;
uint8_t bestBSSID[6];
int32_t bestChannel = 0;

log_i("[WIFI] scan done");

if(scanResult == 0) {
log_e("[WIFI] no networks found");
} else {
log_i("[WIFI] %d networks found", scanResult);


for(int8_t i = 0; i < scanResult; ++i) {

String ssid_scan;
Expand All @@ -131,74 +135,79 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
for(uint32_t x = 0; x < APlist.size(); x++) {
WifiAPlist_t entry = APlist[x];

if(ssid_scan == entry.ssid) { // SSID match
// SSID match or hidden SSID
if(ssid_scan == entry.ssid || (scanHidden && ssid_scan.length() == 0) ) {
known = true;
if(rssi_scan > bestNetworkDb) { // best network
if(sec_scan == WIFI_AUTH_OPEN || entry.passphrase) { // check for passphrase if not open wlan
bestNetworkDb = rssi_scan;
bestChannel = chan_scan;
memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork));
memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID));
}
}
break;
}
}

if(known) {
log_d(" ---> %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c", 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 == WIFI_AUTH_OPEN) ? ' ' : '*');
} else {
log_d(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c", 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 == WIFI_AUTH_OPEN) ? ' ' : '*');
}
}
}

// clean up ram
WiFi.scanDelete();

if(bestNetwork.ssid) {
log_i("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb);

WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID);
status = WiFi.status();

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();
log_i("[WIFI] Candidate: %d scan index: %d APlist: %d BSSID:[%02X:%02X:%02X:%02X:%02X:%02X] ssid_scan: %s entry.ssid: %s\n",
ci, i, x,
BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5],
ssid_scan, entry.ssid, rssi_scan);

ci++;

WiFi.begin(entry.ssid, entry.passphrase, chan_scan, BSSID_scan);

// If the ssid returned from the scan is empty, it is a hidden SSID
// it appears that the WiFi.begin() function is asynchronous and takes
// additional time to connect to a hidden SSID. Therefore a delay of 1000ms
// is added for hidden SSIDs before calling WiFi.status()
if( scanHidden && ssid_scan.length() == 0) {
log_i("[WIFI] Hidden SSID, adding a delay.");
delay(1000);
}

status = WiFi.status();

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();
}

switch(status) {
case WL_CONNECTED:
log_i("[WIFI] Connecting done.");
log_d("[WIFI] SSID: %s", WiFi.SSID().c_str());
log_d("[WIFI] IP: %s", WiFi.localIP().toString().c_str());
log_d("[WIFI] MAC: %s", WiFi.BSSIDstr().c_str());
log_d("[WIFI] Channel: %d", WiFi.channel());
break;
case WL_NO_SSID_AVAIL:
log_e("[WIFI] Connecting Failed AP not found.");
break;
case WL_CONNECT_FAILED:
log_e("[WIFI] Connecting Failed.");
break;
default:
log_e("[WIFI] Connecting Failed (%d).", status);
break;
}
// Connection was not successful
// Disconnect and try the next AP
if( status != WL_CONNECTED ) {
log_d("[WIFI] Disconnecting....\n");
WiFi.persistent(false);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
delay(200);
} else {
// connection was successful
// exit both loops w/return status
WiFi.scanDelete();
return status;
}
}
}
}

switch(status) {
case WL_CONNECTED:
log_i("[WIFI] Connecting done.");
log_d("[WIFI] SSID: %s", WiFi.SSID().c_str());
log_d("[WIFI] IP: %s", WiFi.localIP().toString().c_str());
log_d("[WIFI] MAC: %s", WiFi.BSSIDstr().c_str());
log_d("[WIFI] Channel: %d", WiFi.channel());
break;
case WL_NO_SSID_AVAIL:
log_e("[WIFI] Connecting Failed AP not found.");
break;
case WL_CONNECT_FAILED:
log_e("[WIFI] Connecting Failed.");
break;
default:
log_e("[WIFI] Connecting Failed (%d).", status);
break;
}
} else {
log_e("[WIFI] no matching wifi found!");
}
} else {
// start scan
log_d("[WIFI] delete old wifi config...");
WiFi.disconnect();

log_d("[WIFI] start scan");
// scan wifi async mode
WiFi.scanNetworks(true);
}
// clean up ram
WiFi.scanDelete();

return status;
}

2 changes: 1 addition & 1 deletion libraries/WiFi/src/WiFiMulti.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class WiFiMulti

bool addAP(const char* ssid, const char *passphrase = NULL);

uint8_t run(uint32_t connectTimeout=5000);
uint8_t run(uint32_t connectTimeout=5000, bool scanHidden=false);

private:
std::vector<WifiAPlist_t> APlist;
Expand Down