2019-11-27 21:28:13 +00:00
<!DOCTYPE html>
2020-12-23 20:43:30 +00:00
< html lang = "en" >
2019-11-27 21:28:13 +00:00
< head >
2020-06-10 10:45:44 +00:00
< meta charset = "utf-8" >
2023-10-04 19:37:10 +00:00
< meta content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name = "viewport" >
2019-11-27 21:28:13 +00:00
< title > WiFi Settings< / title >
< script >
2022-11-24 01:50:24 +00:00
var d = document;
2023-06-04 16:40:29 +00:00
var loc = false, locip, locproto = "http:";
2022-11-24 01:50:24 +00:00
var scanLoops = 0, preScanSSID = "";
2024-01-20 23:30:15 +00:00
var maxNetworks = 3;
2022-11-24 01:50:24 +00:00
function gId(e) { return d.getElementById(e); }
function cE(e) { return d.createElement(e); }
2023-09-10 16:52:14 +00:00
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
2021-12-08 21:05:51 +00:00
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
2023-06-04 16:40:29 +00:00
function B(){window.open(getURL("/settings"),"_self");}
2022-11-24 01:50:24 +00:00
function N() {
const button = gId("scan");
button.disabled = true;
2023-06-10 23:39:48 +00:00
button.textContent = "Scanning...";
2022-11-24 01:50:24 +00:00
2023-06-04 16:40:29 +00:00
fetch(getURL("/json/net")).then((response) => {
2022-11-24 01:50:24 +00:00
return response.json();
}).then((json) => {
// Get the list of networks only, defaulting to an empty array.
return Object.assign(
{},
{"networks": []},
json,
).networks.sort(
// Sort by signal strength, descending.
(a, b) => b.rssi - a.rssi
).reduce(
// Filter out duplicate SSIDs. Since it is sorted by signal
// strength, the strongest signal will be kept in the
// order it orginally appeared in the array.
(unique, other) => {
if(!unique.some(obj => obj.ssid === other.ssid)) {
unique.push(other);
}
return unique;
},
[],
);
}).then((networks) => {
// If there are no networks, fetch it again in a second.
// but only do this a few times.
if (networks.length === 0 & & scanLoops < 10 ) {
scanLoops++;
setTimeout(N, 1000);
return;
}
scanLoops = 0;
2024-01-23 19:44:43 +00:00
let cs = d.querySelectorAll("#wifi_entries input[type=text]");
2024-01-20 23:30:15 +00:00
for (let input of (cs||[])) {
2024-01-23 19:44:43 +00:00
let found = false;
2022-11-24 01:50:24 +00:00
let select = cE("select");
2024-01-20 23:30:15 +00:00
select.id = input.id;
select.name = input.name;
select.setAttribute("onchange", "T(this)");
preScanSSID = input.value;
2022-11-24 01:50:24 +00:00
for (let i = 0; i < select.children.length ; i + + ) {
select.removeChild(select.children[i]);
}
for (let i = 0; i < networks.length ; i + + ) {
const option = cE("option");
option.setAttribute("value", networks[i].ssid);
2023-06-10 23:39:48 +00:00
option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`;
2022-11-24 01:50:24 +00:00
2024-01-20 23:30:15 +00:00
if (networks[i].ssid === input.value) {
2022-11-24 01:50:24 +00:00
option.setAttribute("selected", "selected");
2024-01-23 19:44:43 +00:00
found = true;
2022-11-24 01:50:24 +00:00
}
select.appendChild(option);
}
const option = cE("option");
option.setAttribute("value", "!Cs");
2024-01-20 23:30:15 +00:00
option.textContent = "Other network...";
2022-11-24 01:50:24 +00:00
select.appendChild(option);
2024-01-23 19:44:43 +00:00
if (input.value === "" || found) input.replaceWith(select);
else select.remove();
2022-11-24 01:50:24 +00:00
}
button.disabled = false;
2023-06-10 23:39:48 +00:00
button.textContent = "Scan";
2022-11-24 01:50:24 +00:00
});
}
// replace WiFi select with custom SSID input field again
2024-01-20 23:30:15 +00:00
function T(cs) {
2022-11-24 01:50:24 +00:00
if (!cs || cs.value != "!Cs") return;
let input = cE("input");
input.type = "text";
2024-01-20 23:30:15 +00:00
input.id = cs.id;
input.name = cs.name;
2022-11-24 01:50:24 +00:00
input.setAttribute("maxlength",32);
input.value = preScanSSID;
cs.replaceWith(input);
}
2024-01-20 23:30:15 +00:00
function resetWiFi(maxN = undefined) {
if (maxN) maxNetworks = maxN;
let entries = gId("wifi_entries").children
for (let i = entries.length; i > 0; i--) entries[i-1].remove();
btnWiFi(0);
}
function btnWiFi(i) {
gId("wifi_add").style.display = (i< maxNetworks ) ? " inline " : " none " ;
gId("wifi_rem").style.display = (i>1) ? "inline":"none";
}
function addWiFi(ssid="",pass="",ip=0,gw=0,sn=0x00ffffff) { // little endian
var i = gId("wifi_entries").childNodes.length;
if (i >= maxNetworks) return;
var b = `< div id = "net${i}" > < hr class = "sml" >
Network name (SSID${i==0?", empty to not connect":""}):< br > < input type = "text" id = "CS${i}" name = "CS${i}" maxlength = "32" value = "${ssid}" $ { i > 1?"required":""}>< br >
Network password:< br > < input type = "password" name = "PW${i}" maxlength = "64" value = "${pass}" > < br >
Static IP (leave at 0.0.0.0 for DHCP)${i==0?"< br > Also used by Ethernet":""}:< br >
< input name = "IP${i}0" type = "number" class = "s" min = "0" max = "255" value = "${ip&0xFF}" required > .< input name = "IP${i}1" type = "number" class = "s" min = "0" max = "255" value = "${(ip>>8)&0xFF}" required > .< input name = "IP${i}2" type = "number" class = "s" min = "0" max = "255" value = "${(ip>>16)&0xFF}" required > .< input name = "IP${i}3" type = "number" class = "s" min = "0" max = "255" value = "${(ip>>24)&0xFF}" required > < br >
Static gateway:< br >
< input name = "GW${i}0" type = "number" class = "s" min = "0" max = "255" value = "${gw&0xFF}" required > .< input name = "GW${i}1" type = "number" class = "s" min = "0" max = "255" value = "${(gw>>8)&0xFF}" required > .< input name = "GW${i}2" type = "number" class = "s" min = "0" max = "255" value = "${(gw>>16)&0xFF}" required > .< input name = "GW${i}3" type = "number" class = "s" min = "0" max = "255" value = "${(gw>>24)&0xFF}" required > < br >
Static subnet mask:< br >
< input name = "SN${i}0" type = "number" class = "s" min = "0" max = "255" value = "${sn&0xFF}" required > .< input name = "SN${i}1" type = "number" class = "s" min = "0" max = "255" value = "${(sn>>8)&0xFF}" required > .< input name = "SN${i}2" type = "number" class = "s" min = "0" max = "255" value = "${(sn>>16)&0xFF}" required > .< input name = "SN${i}3" type = "number" class = "s" min = "0" max = "255" value = "${(sn>>24)&0xFF}" required > < / div > `;
gId("wifi_entries").insertAdjacentHTML("beforeend", b);
btnWiFi(i+1);
}
function remWiFi() {
const entries = gId("wifi_entries").children;
const i = entries.length;
if (i < 2 ) return ;
entries[i-1].remove();
btnWiFi(i-1);
}
2022-07-17 13:58:41 +00:00
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
2022-11-24 01:50:24 +00:00
let scE = cE("script");
2022-07-17 13:58:41 +00:00
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
2022-11-24 01:50:24 +00:00
// success event
2022-07-17 13:58:41 +00:00
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S() {
2023-06-07 19:37:54 +00:00
let l = window.location;
if (l.protocol == "file:") {
2022-07-17 13:58:41 +00:00
loc = true;
2023-06-04 16:40:29 +00:00
locip = localStorage.getItem('locIp');
2022-07-17 13:58:41 +00:00
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
2023-06-04 16:40:29 +00:00
localStorage.setItem('locIp', locip);
}
} else {
// detect reverse proxy
2023-06-07 19:37:54 +00:00
let path = l.pathname;
2023-06-04 16:40:29 +00:00
let paths = path.slice(1,path.endsWith('/')?-1:undefined).split("/");
if (paths.length > 2) {
2023-11-08 17:40:52 +00:00
paths.pop(); // remove "wifi"
paths.pop(); // remove "settings"
2023-06-07 19:37:54 +00:00
locproto = l.protocol;
2023-06-04 16:40:29 +00:00
loc = true;
2023-11-08 17:40:52 +00:00
locip = l.hostname + (l.port ? ":" + l.port : "") + "/" + paths.join('/');
2022-07-17 13:58:41 +00:00
}
}
2023-06-04 16:40:29 +00:00
loadJS(getURL('/settings/s.js?p=1'), false); // If we set async false, file is loaded and executed, then next statement is processed
if (loc) d.Sf.action = getURL('/settings/wifi');
}
function getURL(path) {
return (loc ? locproto + "//" + locip : "") + path;
2019-11-27 21:28:13 +00:00
}
< / script >
2021-12-06 19:53:09 +00:00
< style > @ import url ( "style.css" ) ; < / style >
2019-11-27 21:28:13 +00:00
< / head >
2022-07-17 13:58:41 +00:00
< body onload = "S()" >
2019-11-27 21:28:13 +00:00
< form id = "form_s" name = "Sf" method = "post" >
2021-03-05 08:50:59 +00:00
< div class = "toprow" >
2019-11-27 21:28:13 +00:00
< div class = "helpB" > < button type = "button" onclick = "H()" > ?< / button > < / div >
2020-06-10 10:45:44 +00:00
< button type = "button" onclick = "B()" > Back< / button > < button type = "submit" > Save & Connect< / button > < hr >
2021-03-05 08:50:59 +00:00
< / div >
2019-11-27 21:28:13 +00:00
< h2 > WiFi setup< / h2 >
< h3 > Connect to existing network< / h3 >
2022-11-24 01:50:24 +00:00
< button type = "button" id = "scan" onclick = "N()" > Scan< / button > < br >
2024-01-20 23:30:15 +00:00
< div id = "wifi" >
Wireless networks
< div id = "wifi_entries" > < / div >
< hr class = "sml" >
< button type = "button" id = "wifi_add" onclick = "addWiFi()" > +< / button >
< button type = "button" id = "wifi_rem" onclick = "remWiFi()" > -< / button > < br >
< / div >
DNS server address:< br >
< input name = "D0" type = "number" class = "s" min = "0" max = "255" required > .< input name = "D1" type = "number" class = "s" min = "0" max = "255" required > .< input name = "D2" type = "number" class = "s" min = "0" max = "255" required > .< input name = "D3" type = "number" class = "s" min = "0" max = "255" required > < br >
< br >
2022-11-24 01:50:24 +00:00
mDNS address (leave empty for no mDNS):< br >
2021-12-08 21:05:51 +00:00
http:// < input type = "text" name = "CM" maxlength = "32" > .local< br >
2019-11-27 21:28:13 +00:00
Client IP: < span class = "sip" > Not connected < / span > < br >
< h3 > Configure Access Point< / h3 >
2021-12-08 21:05:51 +00:00
AP SSID (leave empty for no AP):< br > < input type = "text" name = "AS" maxlength = "32" > < br >
2019-11-27 21:28:13 +00:00
Hide AP name: < input type = "checkbox" name = "AH" > < br >
2020-12-19 16:09:39 +00:00
AP password (leave empty for open):< br > < input type = "password" name = "AP" maxlength = "63" pattern = "(.{8,63})|()" title = "Empty or min. 8 characters" > < br >
2021-06-30 22:01:27 +00:00
Access Point WiFi channel: < input name = "AC" type = "number" class = "xs" min = "1" max = "13" required > < br >
2021-06-20 13:13:38 +00:00
AP opens:
< select name = "AB" >
< option value = "0" > No connection after boot< / option >
< option value = "1" > Disconnected< / option >
< option value = "2" > Always< / option >
< option value = "3" > Never (not recommended)< / option > < / select > < br >
2020-06-10 10:45:44 +00:00
AP IP: < span class = "sip" > Not active < / span > < br >
2020-05-17 19:39:57 +00:00
< h3 > Experimental< / h3 >
2023-12-23 20:05:01 +00:00
Force 802.11g mode (ESP8266 only): < input type = "checkbox" name = "FG" > < br >
2020-05-17 19:39:57 +00:00
Disable WiFi sleep: < input type = "checkbox" name = "WS" > < br >
< i > Can help with connectivity issues.< br >
2021-06-20 13:13:38 +00:00
Do not enable if WiFi is working correctly, increases power consumption.< / i >
2023-06-22 08:06:19 +00:00
2023-09-10 16:52:14 +00:00
< h3 > ESP-NOW Wireless< / h3 >
< div id = "NoESPNOW" class = "hide" >
< i class = "warn" > This firmware build does not include ESP-NOW support.< br > < / i >
< / div >
< div id = "ESPNOW" >
Enable ESP-NOW: < input type = "checkbox" name = "RE" > < br >
2023-06-22 08:06:19 +00:00
< i > Listen for events over ESP-NOW< br >
2023-09-10 16:52:14 +00:00
Keep disabled if not using a remote or wireless sync, increases power consumption.< br > < / i >
Paired Remote MAC: < input type = "text" name = "RMAC" minlength = "12" maxlength = "12" > < br >
Last device seen: < span class = "rlid" onclick = "d.Sf.RMAC.value=this.textContent;" style = "cursor:pointer;" > None< / span > < br >
2023-06-22 08:06:19 +00:00
< / div >
2021-06-20 13:13:38 +00:00
< div id = "ethd" >
2022-04-04 18:52:42 +00:00
< h3 > Ethernet Type< / h3 >
< select name = "ETH" >
< option value = "0" > None< / option >
2023-06-02 08:51:37 +00:00
< option value = "9" > ABC! WLED V43 & compatible< / option >
2022-04-04 18:52:42 +00:00
< option value = "2" > ESP32-POE< / option >
< option value = "6" > ESP32Deux< / option >
< option value = "7" > KIT-VE< / option >
2023-06-02 08:51:37 +00:00
< option value = "8" > QuinLED-Dig-Octa & T-ETH-POE< / option >
2022-04-04 18:52:42 +00:00
< option value = "4" > QuinLED-ESP32< / option >
2023-05-08 06:48:52 +00:00
< option value = "10" > Serg74-ETH32< / option >
2022-04-04 18:52:42 +00:00
< option value = "5" > TwilightLord-ESP32< / option >
< option value = "3" > WESP32< / option >
< option value = "1" > WT32-ETH01< / option >
< / select > < br > < br >
2021-06-20 13:13:38 +00:00
< / div >
2020-05-17 19:39:57 +00:00
< hr >
2020-06-10 10:45:44 +00:00
< button type = "button" onclick = "B()" > Back< / button > < button type = "submit" > Save & Connect< / button >
2019-11-27 21:28:13 +00:00
< / form >
< / body >
2022-11-24 01:50:24 +00:00
< / html >