Last active
February 13, 2023 06:23
-
-
Save AndiSHFR/e9c46890af7cddff6cb5ea7d4f1c5c49 to your computer and use it in GitHub Desktop.
ESP8266 : WiFiAutoSelector - Pick wifi with best signal from a list and connect to it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* WiFiAutoSelector.h - Include file for class WiFiAutoSelector | |
* Copyright (c) 2016 Andreas Schaefer <[email protected]> | |
* | |
* A class to pick a wifi network from a list, based on the | |
* highest receive signal strength, and connect to it. | |
* Inspired by "WiFiMulti" | |
* | |
* This source code is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License as published by the Free Software Foundation; either | |
* version 2.1 of the License, or (at your option) any later version. | |
* This file is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* Usage example: | |
* | |
* #include <ESP8266WiFi.h> | |
* #include "WiFiAutoSelector.h" | |
* | |
* #define WIFI_CONNECT_TIMEOUT 8000 | |
* WiFiAutoSelector wifiAutoSelector(WIFI_CONNECT_TIMEOUT); | |
* | |
* void setup() { | |
* Serial.begin(9600); | |
* wifiAutoSelector.add("myApOne", "s4crzt"); | |
* wifiAutoSelector.add("anotherApTwo", "moreSecret"); | |
* } | |
* | |
* void loop() { | |
* if(WiFi.status() != WL_CONNECTED) { | |
* Serial.print("Connecting wifi "); | |
* if(-1 < wifiAutoSelector.scanAndConnect()) { | |
* int connectedIndex = wifiAutoSelector.getConnectedIndex(); | |
* Serial.print("to '"); | |
* Serial.print(wifiAutoSelector.getSSID(connectedIndex)); | |
* Serial.println("'. Done."); | |
* }else{ | |
* Serial.println("failed."); | |
* } | |
* } | |
* delay(1000); | |
* } | |
* | |
*/ | |
class WiFiAutoSelector { | |
private: | |
typedef struct _NetworkInfo { | |
int rssi; | |
char ssid[32]; | |
char key[64]; | |
} NetworkInfo; | |
protected: | |
const int _WAIT_CONNECT_DELAY = 500; | |
NetworkInfo* _networks; | |
int _count; | |
int _capacity; | |
int _connectedIndex; | |
int _connectTimeout; | |
int _debug; | |
bool resize(int newCapacity) { | |
if(newCapacity <= _capacity) return true; | |
NetworkInfo* tni = (NetworkInfo*)malloc( sizeof(NetworkInfo) * newCapacity ); | |
if(!tni) return false; | |
memset(tni, 0, sizeof(NetworkInfo) * newCapacity); | |
for(int i=0; i < _count; i++) { | |
tni[i] = _networks[i]; | |
} | |
if(_networks) free(_networks); | |
_networks = tni; | |
_capacity = newCapacity; | |
return true; | |
} | |
public: | |
int getCount() { return _count; } | |
int getCapacity() { return _capacity; } | |
int getConnectedIndex() { return _connectedIndex; } | |
int getRSSI(int index) { return _networks[index].rssi; } | |
char* getSSID(int index) { return _networks[index].ssid; } | |
char* getKey(int index) { return _networks[index].key; } | |
void clear() { | |
memset(_networks, 0, sizeof(NetworkInfo) * _capacity ); | |
_count = 0; | |
} | |
int add(const char* ssid, const char* key) { | |
bool canAdd = true; | |
if((_count + 1) >= _capacity) { canAdd = resize( _capacity + 4 ); } | |
if(canAdd) { | |
_networks[_count].rssi = -1000; | |
strncpy(_networks[_count].ssid, ssid, sizeof(_networks[_count].ssid)); | |
strncpy(_networks[_count].key, key, sizeof(_networks[_count].key)); | |
_count++; | |
return _count - 1; | |
} | |
// Could not add the ssid so return -1 | |
return -1; | |
} | |
int scanAndConnect() { | |
// Initialize some variables | |
_connectedIndex = -1; | |
// No networks, then return; | |
if(!_networks || !_count) return _connectedIndex; | |
// Reset RSSI for every known network to lowest value | |
for(int i = 0; i < _count; i++) { | |
_networks[i].rssi = -1000; | |
} | |
int foundNetworkCount = WiFi.scanNetworks(); | |
if(0 >= foundNetworkCount) return _connectedIndex; | |
int bestRSSI = -1000; | |
int bestNetworkIndex = -1; | |
while(foundNetworkCount-- > 0 ) { | |
String foundSSID = WiFi.SSID(foundNetworkCount); | |
if(_debug) { | |
Serial.print("WiFiAutoSelector found network: "); | |
Serial.println(foundSSID); | |
} | |
for(int i = 0; i < _count; i++ ) { | |
if(foundSSID.equals(_networks[i].ssid)) { | |
// RSSI : the current RSSI / Received Signal Strength in dBm | |
_networks[i].rssi = WiFi.RSSI(foundNetworkCount); | |
// Keep the network index with the best signal strength | |
if(bestRSSI < _networks[i].rssi) { | |
bestRSSI = _networks[i].rssi; | |
bestNetworkIndex = i; | |
} | |
break; | |
} | |
} // for(int i = 0; i < _count; i++ ) ... | |
} // while(foundNetworkCount > 0 ) ... | |
// If we have found a best network, connect to it. | |
if(-1 < bestNetworkIndex) { | |
if(_debug) { | |
Serial.print("WiFiAutoSelector will connect to: "); | |
Serial.print(_networks[bestNetworkIndex].ssid); | |
} | |
WiFi.disconnect(); | |
delay(_WAIT_CONNECT_DELAY); | |
WiFi.begin(_networks[bestNetworkIndex].ssid, _networks[bestNetworkIndex].key); | |
// Wait for the wifi to connect. This should happen within the timeout period. | |
for(int loop = _connectTimeout; loop > 0; loop -= _WAIT_CONNECT_DELAY ) { | |
delay(_WAIT_CONNECT_DELAY); | |
if(WiFi.status() == WL_CONNECTED) { | |
_connectedIndex = bestNetworkIndex; | |
if(_debug) { | |
Serial.print("WiFi IP Address: "); | |
Serial.println(WiFi.localIP()); | |
} | |
break; | |
} | |
} | |
} | |
return _connectedIndex; | |
} | |
~WiFiAutoSelector() { | |
if(_networks) free(_networks); | |
} | |
WiFiAutoSelector(int connectTimeout, int debug = false) : | |
_networks(0L), _count(0), _capacity(0) | |
, _connectedIndex(-1) , _connectTimeout(connectTimeout), _debug(debug) { | |
} | |
}; |
On a trip currently with rare wifi.
Checked the code and what i see, as long as the underlying WiFi.SSID() will return an entry for every MAC the best signal will be choosen.
The point is another one. I‘m not sure if you can supply a MAC when connecting to the wifi network. So it depends here if the underlying WiFi code will also pick the strongest AP.
I would assume it will pick the first AP matching the SSID name from the list.
Need to give it a try….
Regards
Andi
… Am 20.06.2022 um 02:41 schrieb maurimerel ***@***.***>:
***@***.*** commented on this gist.
Hi there , Your library is just what I was looking for , just one thing I don't know if can be done . I have at least 10 AP with the same SSID distributed across a building , would it be possible to select the one with strongest signal in that case ??? If not ,could I let's say somehow list the macids instead and select based on them???
Thank you !!!!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi there , Your library is just what I was looking for , just one thing I don't know if can be done . I have at least 10 AP with the same SSID distributed across a building , would it be possible to select the one with strongest signal in that case ??? If not ,could I let's say somehow list the macids instead and select based on them???
Thank you !!!!