Optimise wifi scan

- prioritize strongest signal
- prune removed networks
- fill present networks
This commit is contained in:
Blaz Kristan 2024-01-23 20:44:43 +01:00
parent bfb217c203
commit 1bebf3d3d6
5 changed files with 67 additions and 12 deletions

View File

@ -52,8 +52,9 @@
} }
scanLoops = 0; scanLoops = 0;
let cs = d.querySelectorAll("#wifi_entries input[type=text]#CS0"); let cs = d.querySelectorAll("#wifi_entries input[type=text]");
for (let input of (cs||[])) { for (let input of (cs||[])) {
let found = false;
let select = cE("select"); let select = cE("select");
select.id = input.id; select.id = input.id;
select.name = input.name; select.name = input.name;
@ -72,6 +73,7 @@
if (networks[i].ssid === input.value) { if (networks[i].ssid === input.value) {
option.setAttribute("selected", "selected"); option.setAttribute("selected", "selected");
found = true;
} }
select.appendChild(option); select.appendChild(option);
@ -82,7 +84,8 @@
option.textContent = "Other network..."; option.textContent = "Other network...";
select.appendChild(option); select.appendChild(option);
input.replaceWith(select); if (input.value === "" || found) input.replaceWith(select);
else select.remove();
} }
button.disabled = false; button.disabled = false;

View File

@ -81,6 +81,7 @@ input:disabled {
} }
input[type="text"], input[type="text"],
input[type="number"], input[type="number"],
input[type="password"],
select { select {
font-size: medium; font-size: medium;
margin: 2px; margin: 2px;

View File

@ -19,8 +19,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//WIFI SETTINGS //WIFI SETTINGS
if (subPage == SUBPAGE_WIFI) if (subPage == SUBPAGE_WIFI)
{ {
char oldSSID[33]; unsigned cnt = 0;
strlcpy(oldSSID, multiWiFi[0].clientSSID, 33);
for (size_t n = 0; n < WLED_MAX_WIFI_COUNT; n++) { for (size_t n = 0; n < WLED_MAX_WIFI_COUNT; n++) {
char cs[4] = "CS"; cs[2] = 48+n; cs[3] = 0; //client SSID char cs[4] = "CS"; cs[2] = 48+n; cs[3] = 0; //client SSID
char pw[4] = "PW"; pw[2] = 48+n; pw[3] = 0; //client password char pw[4] = "PW"; pw[2] = 48+n; pw[3] = 0; //client password
@ -28,10 +27,11 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
char gw[5] = "GW"; gw[2] = 48+n; gw[4] = 0; //GW address char gw[5] = "GW"; gw[2] = 48+n; gw[4] = 0; //GW address
char sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask char sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask
if (request->hasArg(cs)) { if (request->hasArg(cs)) {
if (n >= multiWiFi.size()) multiWiFi.push_back(WiFiConfig()); if (n >= multiWiFi.size()) multiWiFi.push_back(WiFiConfig()); // expand vector by one
char oldSSID[33]; strcpy(oldSSID, multiWiFi[n].clientSSID); char oldSSID[33]; strcpy(oldSSID, multiWiFi[n].clientSSID);
char oldPass[65]; strcpy(oldPass, multiWiFi[n].clientPass); char oldPass[65]; strcpy(oldPass, multiWiFi[n].clientPass);
if (!strncmp(request->arg(cs).c_str(), oldSSID, 32)) {
if (strlen(oldSSID) == 0 || !strncmp(request->arg(cs).c_str(), oldSSID, 32)) {
strlcpy(multiWiFi[n].clientSSID, request->arg(cs).c_str(), 33); strlcpy(multiWiFi[n].clientSSID, request->arg(cs).c_str(), 33);
forceReconnect = true; forceReconnect = true;
} }
@ -47,18 +47,24 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
multiWiFi[n].staticGW[i] = request->arg(gw).toInt(); multiWiFi[n].staticGW[i] = request->arg(gw).toInt();
multiWiFi[n].staticSN[i] = request->arg(sn).toInt(); multiWiFi[n].staticSN[i] = request->arg(sn).toInt();
} }
cnt++;
} }
} }
// remove unused
if (cnt < multiWiFi.size()) {
cnt = multiWiFi.size() - cnt;
while (cnt--) multiWiFi.pop_back();
multiWiFi.shrink_to_fit(); // release memory
}
if (request->hasArg(F("D0"))) { if (request->hasArg(F("D0"))) {
dnsAddress = IPAddress(request->arg(F("D0")).toInt(),request->arg(F("D1")).toInt(),request->arg(F("D2")).toInt(),request->arg(F("D3")).toInt()); dnsAddress = IPAddress(request->arg(F("D0")).toInt(),request->arg(F("D1")).toInt(),request->arg(F("D2")).toInt(),request->arg(F("D3")).toInt());
DEBUG_PRINTLN(dnsAddress);
} }
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33); strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
apBehavior = request->arg(F("AB")).toInt(); apBehavior = request->arg(F("AB")).toInt();
strcpy(oldSSID, apSSID); char oldSSID[33]; strcpy(oldSSID, apSSID);
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33); strlcpy(apSSID, request->arg(F("AS")).c_str(), 33);
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true; if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true;
apHide = request->hasArg(F("AH")); apHide = request->hasArg(F("AH"));

View File

@ -453,6 +453,8 @@ void WLED::setup()
WiFi.onEvent(WiFiEvent); WiFi.onEvent(WiFiEvent);
#endif #endif
findWiFi(true); // start scanning for available WiFi-s
#ifdef WLED_ENABLE_ADALIGHT #ifdef WLED_ENABLE_ADALIGHT
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused //Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused //Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
@ -698,7 +700,48 @@ bool WLED::initEthernet()
#else #else
return false; // Ethernet not enabled for build return false; // Ethernet not enabled for build
#endif #endif
}
// performs asynchronous scan for available networks (which may take couple of seconds to finish)
// returns true if only one wifi is configured or scan completed
bool WLED::findWiFi(bool doScan) {
if (multiWiFi.size() <= 1) {
DEBUG_PRINTLN(F("Defaulf WiFi used."));
selectedWiFi = 0;
return true;
}
if (doScan) WiFi.scanDelete(); // restart scan
int status = WiFi.scanComplete();
if (status == WIFI_SCAN_FAILED) {
DEBUG_PRINTLN(F("WiFi scan started."));
WiFi.scanNetworks(true); // start scanning in asynchronous mode
return false;
}
if (status > 0) { // status contains number of found networks
DEBUG_PRINT(F("WiFi scan completed: ")); DEBUG_PRINTLN(status);
int rssi = -9999;
for (int o = 0; o < status; o++) {
DEBUG_PRINT(F(" WiFi available: ")); DEBUG_PRINT(WiFi.SSID(o));
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(WiFi.RSSI(o)); DEBUG_PRINTLN(F("dB"));
for (unsigned n = 0; n < multiWiFi.size(); n++)
if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) {
// find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big)
if ((n < selectedWiFi && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) {
rssi = WiFi.RSSI(o);
selectedWiFi = n;
}
break;
}
}
DEBUG_PRINT(F("Selected: ")); DEBUG_PRINT(multiWiFi[selectedWiFi].clientSSID);
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(rssi); DEBUG_PRINTLN(F("dB"));
return true;
}
//DEBUG_PRINT(F("WiFi scan running."));
return false; // scan is still running or there was an error
} }
void WLED::initConnection() void WLED::initConnection()
@ -715,7 +758,7 @@ void WLED::initConnection()
} }
#endif #endif
WiFi.disconnect(true); // close old connections if (findWiFi()) WiFi.disconnect(true); // close old connections (only if scan completed and found networks)
#ifdef ESP8266 #ifdef ESP8266
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N); WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
#endif #endif
@ -752,7 +795,7 @@ void WLED::initConnection()
// convert the "serverDescription" into a valid DNS hostname (alphanumeric) // convert the "serverDescription" into a valid DNS hostname (alphanumeric)
char hostname[25]; char hostname[25];
prepareHostname(hostname); prepareHostname(hostname);
WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); // no harm if called multiple times
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3)) #if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
WiFi.setTxPower(WIFI_POWER_8_5dBm); WiFi.setTxPower(WIFI_POWER_8_5dBm);
@ -907,6 +950,7 @@ void WLED::handleConnection()
if (interfacesInited) { if (interfacesInited) {
DEBUG_PRINTLN(F("Disconnected!")); DEBUG_PRINTLN(F("Disconnected!"));
initConnection(); initConnection();
findWiFi(true); // reinit scan
interfacesInited = false; interfacesInited = false;
} }
//send improv failed 6 seconds after second init attempt (24 sec. after provisioning) //send improv failed 6 seconds after second init attempt (24 sec. after provisioning)
@ -917,15 +961,15 @@ void WLED::handleConnection()
if (now - lastReconnectAttempt > ((stac) ? 300000 : 18000) && WLED_WIFI_CONFIGURED) { if (now - lastReconnectAttempt > ((stac) ? 300000 : 18000) && WLED_WIFI_CONFIGURED) {
if (improvActive == 2) improvActive = 3; if (improvActive == 2) improvActive = 3;
DEBUG_PRINTLN(F("Last reconnect too old.")); DEBUG_PRINTLN(F("Last reconnect too old."));
if (++selectedWiFi >= multiWiFi.size()) selectedWiFi = 0;
initConnection(); initConnection();
findWiFi(true); // reinit scan
} }
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) { if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
DEBUG_PRINTLN(F("Not connected AP.")); DEBUG_PRINTLN(F("Not connected AP."));
initAP(); initAP();
} }
} else if (!interfacesInited) { //newly connected } else if (!interfacesInited) { //newly connected
DEBUG_PRINTLN(""); DEBUG_PRINTLN();
DEBUG_PRINT(F("Connected! IP address: ")); DEBUG_PRINT(F("Connected! IP address: "));
DEBUG_PRINTLN(Network.localIP()); DEBUG_PRINTLN(Network.localIP());
if (improvActive) { if (improvActive) {

View File

@ -881,6 +881,7 @@ public:
void initAP(bool resetAP = false); void initAP(bool resetAP = false);
void initConnection(); void initConnection();
void initInterfaces(); void initInterfaces();
bool findWiFi(bool doScan = false);
#if defined(STATUSLED) #if defined(STATUSLED)
void handleStatusLED(); void handleStatusLED();
#endif #endif