diff --git a/wled00/data/settings_wifi.htm b/wled00/data/settings_wifi.htm index 1f18dbec4..e07ef3401 100644 --- a/wled00/data/settings_wifi.htm +++ b/wled00/data/settings_wifi.htm @@ -52,8 +52,9 @@ } 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||[])) { + let found = false; let select = cE("select"); select.id = input.id; select.name = input.name; @@ -72,6 +73,7 @@ if (networks[i].ssid === input.value) { option.setAttribute("selected", "selected"); + found = true; } select.appendChild(option); @@ -82,7 +84,8 @@ option.textContent = "Other network..."; select.appendChild(option); - input.replaceWith(select); + if (input.value === "" || found) input.replaceWith(select); + else select.remove(); } button.disabled = false; diff --git a/wled00/data/style.css b/wled00/data/style.css index 52b26a825..b6cb0f9e6 100644 --- a/wled00/data/style.css +++ b/wled00/data/style.css @@ -81,6 +81,7 @@ input:disabled { } input[type="text"], input[type="number"], +input[type="password"], select { font-size: medium; margin: 2px; diff --git a/wled00/set.cpp b/wled00/set.cpp index 6c20289f6..3d0e06815 100755 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -19,8 +19,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) //WIFI SETTINGS if (subPage == SUBPAGE_WIFI) { - char oldSSID[33]; - strlcpy(oldSSID, multiWiFi[0].clientSSID, 33); + unsigned cnt = 0; 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 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 sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask 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 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); forceReconnect = true; } @@ -47,18 +47,24 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) multiWiFi[n].staticGW[i] = request->arg(gw).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"))) { 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); apBehavior = request->arg(F("AB")).toInt(); - strcpy(oldSSID, apSSID); + char oldSSID[33]; strcpy(oldSSID, apSSID); strlcpy(apSSID, request->arg(F("AS")).c_str(), 33); if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true; apHide = request->hasArg(F("AH")); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index f386707c6..5a0054107 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -453,6 +453,8 @@ void WLED::setup() WiFi.onEvent(WiFiEvent); #endif + findWiFi(true); // start scanning for available WiFi-s + #ifdef WLED_ENABLE_ADALIGHT //Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused //Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused @@ -698,7 +700,48 @@ bool WLED::initEthernet() #else return false; // Ethernet not enabled for build #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() @@ -715,7 +758,7 @@ void WLED::initConnection() } #endif - WiFi.disconnect(true); // close old connections + if (findWiFi()) WiFi.disconnect(true); // close old connections (only if scan completed and found networks) #ifdef ESP8266 WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N); #endif @@ -752,7 +795,7 @@ void WLED::initConnection() // convert the "serverDescription" into a valid DNS hostname (alphanumeric) char hostname[25]; 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 #if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3)) WiFi.setTxPower(WIFI_POWER_8_5dBm); @@ -907,6 +950,7 @@ void WLED::handleConnection() if (interfacesInited) { DEBUG_PRINTLN(F("Disconnected!")); initConnection(); + findWiFi(true); // reinit scan interfacesInited = false; } //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 (improvActive == 2) improvActive = 3; DEBUG_PRINTLN(F("Last reconnect too old.")); - if (++selectedWiFi >= multiWiFi.size()) selectedWiFi = 0; initConnection(); + findWiFi(true); // reinit scan } if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) { DEBUG_PRINTLN(F("Not connected AP.")); initAP(); } } else if (!interfacesInited) { //newly connected - DEBUG_PRINTLN(""); + DEBUG_PRINTLN(); DEBUG_PRINT(F("Connected! IP address: ")); DEBUG_PRINTLN(Network.localIP()); if (improvActive) { diff --git a/wled00/wled.h b/wled00/wled.h index 174cb771b..a513de398 100755 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -881,6 +881,7 @@ public: void initAP(bool resetAP = false); void initConnection(); void initInterfaces(); + bool findWiFi(bool doScan = false); #if defined(STATUSLED) void handleStatusLED(); #endif