mirror of
https://github.com/wled/WLED.git
synced 2025-07-09 20:06:33 +00:00
Implement multiple WiFi
- similar to #3705 - solves #2845, #2974, #852, #1228
This commit is contained in:
parent
5dd8f0a0b7
commit
bfb217c203
102
wled00/cfg.cpp
102
wled00/cfg.cpp
@ -40,21 +40,39 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
linked_remote[12] = '\0';
|
linked_remote[12] = '\0';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject nw_ins_0 = nw["ins"][0];
|
size_t n = 0;
|
||||||
getStringFromJson(clientSSID, nw_ins_0[F("ssid")], 33);
|
JsonArray nw_ins = nw["ins"];
|
||||||
//int nw_ins_0_pskl = nw_ins_0[F("pskl")];
|
if (!nw_ins.isNull()) {
|
||||||
//The WiFi PSK is normally not contained in the regular file for security reasons.
|
// as password are stored separately in wsec.json when reading configuration vector resize happens there, but for dynamic config we need to resize if necessary
|
||||||
//If it is present however, we will use it
|
if (nw_ins.size() > 1 && nw_ins.size() > multiWiFi.size()) multiWiFi.resize(nw_ins.size()); // resize constructs objects while resizing
|
||||||
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
|
for (JsonObject wifi : nw_ins) {
|
||||||
|
JsonArray ip = wifi["ip"];
|
||||||
|
JsonArray gw = wifi["gw"];
|
||||||
|
JsonArray sn = wifi["sn"];
|
||||||
|
char ssid[33] = "";
|
||||||
|
char pass[65] = "";
|
||||||
|
IPAddress nIP = (uint32_t)0U, nGW = (uint32_t)0U, nSN = (uint32_t)0x00FFFFFF; // little endian
|
||||||
|
getStringFromJson(ssid, wifi[F("ssid")], 33);
|
||||||
|
getStringFromJson(pass, wifi["psk"], 65); // password is not normally present but if it is, use it
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
CJSON(nIP[i], ip[i]);
|
||||||
|
CJSON(nGW[i], gw[i]);
|
||||||
|
CJSON(nSN[i], sn[i]);
|
||||||
|
}
|
||||||
|
if (strlen(ssid) > 0) strlcpy(multiWiFi[n].clientSSID, ssid, 33); // this will keep old SSID intact if not present in JSON
|
||||||
|
if (strlen(pass) > 0) strlcpy(multiWiFi[n].clientPass, pass, 65); // this will keep old password intact if not present in JSON
|
||||||
|
multiWiFi[n].staticIP = nIP;
|
||||||
|
multiWiFi[n].staticGW = nGW;
|
||||||
|
multiWiFi[n].staticSN = nSN;
|
||||||
|
if (++n >= WLED_MAX_WIFI_COUNT) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonArray nw_ins_0_ip = nw_ins_0["ip"];
|
JsonArray dns = nw[F("dns")];
|
||||||
JsonArray nw_ins_0_gw = nw_ins_0["gw"];
|
if (!dns.isNull()) {
|
||||||
JsonArray nw_ins_0_sn = nw_ins_0["sn"];
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
CJSON(dnsAddress[i], dns[i]);
|
||||||
for (byte i = 0; i < 4; i++) {
|
}
|
||||||
CJSON(staticIP[i], nw_ins_0_ip[i]);
|
|
||||||
CJSON(staticGateway[i], nw_ins_0_gw[i]);
|
|
||||||
CJSON(staticSubnet[i], nw_ins_0_sn[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject ap = doc["ap"];
|
JsonObject ap = doc["ap"];
|
||||||
@ -212,7 +230,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
JsonObject btn_obj = hw["btn"];
|
JsonObject btn_obj = hw["btn"];
|
||||||
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
|
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
|
||||||
disablePullUp = !pull;
|
disablePullUp = !pull;
|
||||||
JsonArray hw_btn_ins = btn_obj[F("ins")];
|
JsonArray hw_btn_ins = btn_obj["ins"];
|
||||||
if (!hw_btn_ins.isNull()) {
|
if (!hw_btn_ins.isNull()) {
|
||||||
for (uint8_t b = 0; b < WLED_MAX_BUTTONS; b++) { // deallocate existing button pins
|
for (uint8_t b = 0; b < WLED_MAX_BUTTONS; b++) { // deallocate existing button pins
|
||||||
pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
||||||
@ -433,7 +451,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
||||||
CJSON(e131Multicast, if_live[F("mc")]);
|
CJSON(e131Multicast, if_live[F("mc")]);
|
||||||
|
|
||||||
JsonObject if_live_dmx = if_live[F("dmx")];
|
JsonObject if_live_dmx = if_live["dmx"];
|
||||||
CJSON(e131Universe, if_live_dmx[F("uni")]);
|
CJSON(e131Universe, if_live_dmx[F("uni")]);
|
||||||
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
|
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
|
||||||
CJSON(DMXAddress, if_live_dmx[F("addr")]);
|
CJSON(DMXAddress, if_live_dmx[F("addr")]);
|
||||||
@ -665,19 +683,23 @@ void serializeConfig() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonArray nw_ins = nw.createNestedArray("ins");
|
JsonArray nw_ins = nw.createNestedArray("ins");
|
||||||
|
for (size_t n = 0; n < multiWiFi.size(); n++) {
|
||||||
|
JsonObject wifi = nw_ins.createNestedObject();
|
||||||
|
wifi[F("ssid")] = multiWiFi[n].clientSSID;
|
||||||
|
wifi[F("pskl")] = strlen(multiWiFi[n].clientPass);
|
||||||
|
JsonArray wifi_ip = wifi.createNestedArray("ip");
|
||||||
|
JsonArray wifi_gw = wifi.createNestedArray("gw");
|
||||||
|
JsonArray wifi_sn = wifi.createNestedArray("sn");
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
wifi_ip.add(multiWiFi[n].staticIP[i]);
|
||||||
|
wifi_gw.add(multiWiFi[n].staticGW[i]);
|
||||||
|
wifi_sn.add(multiWiFi[n].staticSN[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject nw_ins_0 = nw_ins.createNestedObject();
|
JsonArray dns = nw.createNestedArray(F("dns"));
|
||||||
nw_ins_0[F("ssid")] = clientSSID;
|
for (size_t i = 0; i < 4; i++) {
|
||||||
nw_ins_0[F("pskl")] = strlen(clientPass);
|
dns.add(dnsAddress[i]);
|
||||||
|
|
||||||
JsonArray nw_ins_0_ip = nw_ins_0.createNestedArray("ip");
|
|
||||||
JsonArray nw_ins_0_gw = nw_ins_0.createNestedArray("gw");
|
|
||||||
JsonArray nw_ins_0_sn = nw_ins_0.createNestedArray("sn");
|
|
||||||
|
|
||||||
for (byte i = 0; i < 4; i++) {
|
|
||||||
nw_ins_0_ip.add(staticIP[i]);
|
|
||||||
nw_ins_0_gw.add(staticGateway[i]);
|
|
||||||
nw_ins_0_sn.add(staticSubnet[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject ap = root.createNestedObject("ap");
|
JsonObject ap = root.createNestedObject("ap");
|
||||||
@ -693,7 +715,7 @@ void serializeConfig() {
|
|||||||
ap_ip.add(2);
|
ap_ip.add(2);
|
||||||
ap_ip.add(1);
|
ap_ip.add(1);
|
||||||
|
|
||||||
JsonObject wifi = root.createNestedObject("wifi");
|
JsonObject wifi = root.createNestedObject(F("wifi"));
|
||||||
wifi[F("sleep")] = !noWifiSleep;
|
wifi[F("sleep")] = !noWifiSleep;
|
||||||
wifi[F("phy")] = force802_3g;
|
wifi[F("phy")] = force802_3g;
|
||||||
|
|
||||||
@ -721,7 +743,7 @@ void serializeConfig() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject hw = root.createNestedObject("hw");
|
JsonObject hw = root.createNestedObject(F("hw"));
|
||||||
|
|
||||||
JsonObject hw_led = hw.createNestedObject("led");
|
JsonObject hw_led = hw.createNestedObject("led");
|
||||||
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
||||||
@ -1048,8 +1070,17 @@ bool deserializeConfigSec() {
|
|||||||
|
|
||||||
JsonObject root = pDoc->as<JsonObject>();
|
JsonObject root = pDoc->as<JsonObject>();
|
||||||
|
|
||||||
JsonObject nw_ins_0 = root["nw"]["ins"][0];
|
size_t n = 0;
|
||||||
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
|
JsonArray nw_ins = root["nw"]["ins"];
|
||||||
|
if (!nw_ins.isNull()) {
|
||||||
|
if (nw_ins.size() > 1 && nw_ins.size() > multiWiFi.size()) multiWiFi.resize(nw_ins.size()); // resize constructs objects while resizing
|
||||||
|
for (JsonObject wifi : nw_ins) {
|
||||||
|
char pw[65] = "";
|
||||||
|
getStringFromJson(pw, wifi["psk"], 65);
|
||||||
|
strlcpy(multiWiFi[n].clientPass, pw, 65);
|
||||||
|
if (++n >= WLED_MAX_WIFI_COUNT) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject ap = root["ap"];
|
JsonObject ap = root["ap"];
|
||||||
getStringFromJson(apPass, ap["psk"] , 65);
|
getStringFromJson(apPass, ap["psk"] , 65);
|
||||||
@ -1088,9 +1119,10 @@ void serializeConfigSec() {
|
|||||||
JsonObject nw = root.createNestedObject("nw");
|
JsonObject nw = root.createNestedObject("nw");
|
||||||
|
|
||||||
JsonArray nw_ins = nw.createNestedArray("ins");
|
JsonArray nw_ins = nw.createNestedArray("ins");
|
||||||
|
for (size_t i = 0; i < multiWiFi.size(); i++) {
|
||||||
JsonObject nw_ins_0 = nw_ins.createNestedObject();
|
JsonObject wifi = nw_ins.createNestedObject();
|
||||||
nw_ins_0["psk"] = clientPass;
|
wifi[F("psk")] = multiWiFi[i].clientPass;
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject ap = root.createNestedObject("ap");
|
JsonObject ap = root.createNestedObject("ap");
|
||||||
ap["psk"] = apPass;
|
ap["psk"] = apPass;
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#define DEFAULT_MDNS_NAME "x"
|
#define DEFAULT_MDNS_NAME "x"
|
||||||
|
|
||||||
//increase if you need more
|
//increase if you need more
|
||||||
|
#ifndef WLED_MAX_WIFI_COUNT
|
||||||
|
#define WLED_MAX_WIFI_COUNT 3
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_MAX_USERMODS
|
#ifndef WLED_MAX_USERMODS
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#define WLED_MAX_USERMODS 4
|
#define WLED_MAX_USERMODS 4
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
var d = document;
|
var d = document;
|
||||||
var loc = false, locip, locproto = "http:";
|
var loc = false, locip, locproto = "http:";
|
||||||
var scanLoops = 0, preScanSSID = "";
|
var scanLoops = 0, preScanSSID = "";
|
||||||
|
var maxNetworks = 3;
|
||||||
function gId(e) { return d.getElementById(e); }
|
function gId(e) { return d.getElementById(e); }
|
||||||
function cE(e) { return d.createElement(e); }
|
function cE(e) { return d.createElement(e); }
|
||||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||||
@ -52,13 +52,13 @@
|
|||||||
}
|
}
|
||||||
scanLoops = 0;
|
scanLoops = 0;
|
||||||
|
|
||||||
let cs = gId("CS");
|
let cs = d.querySelectorAll("#wifi_entries input[type=text]#CS0");
|
||||||
if (cs) {
|
for (let input of (cs||[])) {
|
||||||
let select = cE("select");
|
let select = cE("select");
|
||||||
select.setAttribute("id", "CS");
|
select.id = input.id;
|
||||||
select.setAttribute("name", "CS");
|
select.name = input.name;
|
||||||
select.setAttribute("onchange", "T()");
|
select.setAttribute("onchange", "T(this)");
|
||||||
preScanSSID = cs.value;
|
preScanSSID = input.value;
|
||||||
|
|
||||||
for (let i = 0; i < select.children.length; i++) {
|
for (let i = 0; i < select.children.length; i++) {
|
||||||
select.removeChild(select.children[i]);
|
select.removeChild(select.children[i]);
|
||||||
@ -70,7 +70,7 @@
|
|||||||
option.setAttribute("value", networks[i].ssid);
|
option.setAttribute("value", networks[i].ssid);
|
||||||
option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`;
|
option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`;
|
||||||
|
|
||||||
if (networks[i].ssid === cs.value) {
|
if (networks[i].ssid === input.value) {
|
||||||
option.setAttribute("selected", "selected");
|
option.setAttribute("selected", "selected");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +79,10 @@
|
|||||||
const option = cE("option");
|
const option = cE("option");
|
||||||
|
|
||||||
option.setAttribute("value", "!Cs");
|
option.setAttribute("value", "!Cs");
|
||||||
option.textContent = `Other network...`;
|
option.textContent = "Other network...";
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
|
|
||||||
cs.replaceWith(select);
|
input.replaceWith(select);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
@ -90,17 +90,48 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// replace WiFi select with custom SSID input field again
|
// replace WiFi select with custom SSID input field again
|
||||||
function T() {
|
function T(cs) {
|
||||||
let cs = gId("CS");
|
|
||||||
if (!cs || cs.value != "!Cs") return;
|
if (!cs || cs.value != "!Cs") return;
|
||||||
let input = cE("input");
|
let input = cE("input");
|
||||||
input.type = "text";
|
input.type = "text";
|
||||||
input.id = "CS";
|
input.id = cs.id;
|
||||||
input.name ="CS";
|
input.name = cs.name;
|
||||||
input.setAttribute("maxlength",32);
|
input.setAttribute("maxlength",32);
|
||||||
input.value = preScanSSID;
|
input.value = preScanSSID;
|
||||||
cs.replaceWith(input);
|
cs.replaceWith(input);
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
function loadJS(FILE_URL, async = true) {
|
function loadJS(FILE_URL, async = true) {
|
||||||
let scE = cE("script");
|
let scE = cE("script");
|
||||||
@ -158,24 +189,16 @@
|
|||||||
<h2>WiFi setup</h2>
|
<h2>WiFi setup</h2>
|
||||||
<h3>Connect to existing network</h3>
|
<h3>Connect to existing network</h3>
|
||||||
<button type="button" id="scan" onclick="N()">Scan</button><br>
|
<button type="button" id="scan" onclick="N()">Scan</button><br>
|
||||||
Network name (SSID, empty to not connect):<br>
|
<div id="wifi">
|
||||||
<input type="text" id="CS" name="CS" maxlength="32"><br>
|
Wireless networks
|
||||||
Network password: <br> <input type="password" name="CP" maxlength="63"><br>
|
<div id="wifi_entries"></div>
|
||||||
Static IP (leave at 0.0.0.0 for DHCP):<br>
|
<hr class="sml">
|
||||||
<input name="I0" type="number" class="s" min="0" max="255" required> .
|
<button type="button" id="wifi_add" onclick="addWiFi()">+</button>
|
||||||
<input name="I1" type="number" class="s" min="0" max="255" required> .
|
<button type="button" id="wifi_rem" onclick="remWiFi()">-</button><br>
|
||||||
<input name="I2" type="number" class="s" min="0" max="255" required> .
|
</div>
|
||||||
<input name="I3" type="number" class="s" min="0" max="255" required><br>
|
DNS server address:<br>
|
||||||
Static gateway:<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>
|
||||||
<input name="G0" type="number" class="s" min="0" max="255" required> .
|
<br>
|
||||||
<input name="G1" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="G2" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="G3" type="number" class="s" min="0" max="255" required><br>
|
|
||||||
Static subnet mask:<br>
|
|
||||||
<input name="S0" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S1" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S2" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S3" type="number" class="s" min="0" max="255" required><br>
|
|
||||||
mDNS address (leave empty for no mDNS):<br>
|
mDNS address (leave empty for no mDNS):<br>
|
||||||
http:// <input type="text" name="CM" maxlength="32"> .local<br>
|
http:// <input type="text" name="CM" maxlength="32"> .local<br>
|
||||||
Client IP: <span class="sip"> Not connected </span> <br>
|
Client IP: <span class="sip"> Not connected </span> <br>
|
||||||
|
@ -490,7 +490,7 @@ void prepareArtnetPollReply(ArtPollReply *reply) {
|
|||||||
// Node is DHCP capable
|
// Node is DHCP capable
|
||||||
// Node supports 15 bit Port-Address (Art-Net 3 or 4)
|
// Node supports 15 bit Port-Address (Art-Net 3 or 4)
|
||||||
// Node is able to switch between ArtNet and sACN
|
// Node is able to switch between ArtNet and sACN
|
||||||
reply->reply_status_2 = (staticIP[0] == 0) ? 0x1F : 0x1D;
|
reply->reply_status_2 = (multiWiFi[0].staticIP[0] == 0) ? 0x1F : 0x1D;
|
||||||
|
|
||||||
// RDM is disabled
|
// RDM is disabled
|
||||||
// Output style is continuous
|
// Output style is continuous
|
||||||
|
@ -48,6 +48,21 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct WiFiConfig {
|
||||||
|
char clientSSID[33];
|
||||||
|
char clientPass[65];
|
||||||
|
IPAddress staticIP;
|
||||||
|
IPAddress staticGW;
|
||||||
|
IPAddress staticSN;
|
||||||
|
WiFiConfig(const char *ssid="", const char *pass="", uint32_t ip=0, uint32_t gw=0, uint32_t subnet=0x00FFFFFF) // little endian
|
||||||
|
: staticIP(ip)
|
||||||
|
, staticGW(gw)
|
||||||
|
, staticSN(subnet)
|
||||||
|
{
|
||||||
|
strncpy(clientSSID, ssid, 32); clientSSID[32] = 0;
|
||||||
|
strncpy(clientPass, pass, 64); clientPass[64] = 0;
|
||||||
|
}
|
||||||
|
} wifi_config;
|
||||||
|
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
// similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod)
|
// similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod)
|
||||||
|
@ -259,14 +259,14 @@ void parseWiFiCommand(char* rpcData) {
|
|||||||
|
|
||||||
uint8_t ssidLen = rpcData[1];
|
uint8_t ssidLen = rpcData[1];
|
||||||
if (ssidLen > len -1 || ssidLen > 32) return;
|
if (ssidLen > len -1 || ssidLen > 32) return;
|
||||||
memset(clientSSID, 0, 32);
|
memset(multiWiFi[0].clientSSID, 0, 32);
|
||||||
memcpy(clientSSID, rpcData+2, ssidLen);
|
memcpy(multiWiFi[0].clientSSID, rpcData+2, ssidLen);
|
||||||
|
|
||||||
memset(clientPass, 0, 64);
|
memset(multiWiFi[0].clientPass, 0, 64);
|
||||||
if (len > ssidLen +1) {
|
if (len > ssidLen +1) {
|
||||||
uint8_t passLen = rpcData[2+ssidLen];
|
uint8_t passLen = rpcData[2+ssidLen];
|
||||||
memset(clientPass, 0, 64);
|
memset(multiWiFi[0].clientPass, 0, 64);
|
||||||
memcpy(clientPass, rpcData+3+ssidLen, passLen);
|
memcpy(multiWiFi[0].clientPass, rpcData+3+ssidLen, passLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendImprovStateResponse(0x03); //provisioning
|
sendImprovStateResponse(0x03); //provisioning
|
||||||
|
@ -163,8 +163,8 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
if (!apActive) {
|
if (!apActive) {
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
}
|
}
|
||||||
if (staticIP != (uint32_t)0x00000000 && staticGateway != (uint32_t)0x00000000) {
|
if (multiWiFi[0].staticIP != (uint32_t)0x00000000 && multiWiFi[0].staticGW != (uint32_t)0x00000000) {
|
||||||
ETH.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
|
ETH.config(multiWiFi[0].staticIP, multiWiFi[0].staticGW, multiWiFi[0].staticSN, dnsAddress);
|
||||||
} else {
|
} else {
|
||||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,40 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
//WIFI SETTINGS
|
//WIFI SETTINGS
|
||||||
if (subPage == SUBPAGE_WIFI)
|
if (subPage == SUBPAGE_WIFI)
|
||||||
{
|
{
|
||||||
char oldSSID[sizeof(clientSSID)];
|
char oldSSID[33];
|
||||||
|
strlcpy(oldSSID, multiWiFi[0].clientSSID, 33);
|
||||||
|
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
|
||||||
|
char ip[5] = "IP"; ip[2] = 48+n; ip[4] = 0; //IP 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
|
||||||
|
if (request->hasArg(cs)) {
|
||||||
|
if (n >= multiWiFi.size()) multiWiFi.push_back(WiFiConfig());
|
||||||
|
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)) {
|
||||||
|
strlcpy(multiWiFi[n].clientSSID, request->arg(cs).c_str(), 33);
|
||||||
|
forceReconnect = true;
|
||||||
|
}
|
||||||
|
if (!isAsterisksOnly(request->arg(pw).c_str(), 65)) {
|
||||||
|
strlcpy(multiWiFi[n].clientPass, request->arg(pw).c_str(), 65);
|
||||||
|
forceReconnect = true;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
ip[3] = 48+i;
|
||||||
|
gw[3] = 48+i;
|
||||||
|
sn[3] = 48+i;
|
||||||
|
multiWiFi[n].staticIP[i] = request->arg(ip).toInt();
|
||||||
|
multiWiFi[n].staticGW[i] = request->arg(gw).toInt();
|
||||||
|
multiWiFi[n].staticSN[i] = request->arg(sn).toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
strcpy(oldSSID, clientSSID);
|
if (request->hasArg(F("D0"))) {
|
||||||
strlcpy(clientSSID,request->arg(F("CS")).c_str(), 33);
|
dnsAddress = IPAddress(request->arg(F("D0")).toInt(),request->arg(F("D1")).toInt(),request->arg(F("D2")).toInt(),request->arg(F("D3")).toInt());
|
||||||
if (!strcmp(oldSSID, clientSSID)) forceReconnect = true;
|
DEBUG_PRINTLN(dnsAddress);
|
||||||
|
|
||||||
if (!isAsterisksOnly(request->arg(F("CP")).c_str(), 65)) {
|
|
||||||
strlcpy(clientPass, request->arg(F("CP")).c_str(), 65);
|
|
||||||
forceReconnect = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
||||||
@ -61,21 +86,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
ethernetType = request->arg(F("ETH")).toInt();
|
ethernetType = request->arg(F("ETH")).toInt();
|
||||||
WLED::instance().initEthernet();
|
WLED::instance().initEthernet();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char k[3]; k[2] = 0;
|
|
||||||
for (int i = 0; i<4; i++)
|
|
||||||
{
|
|
||||||
k[1] = i+48;//ascii 0,1,2,3
|
|
||||||
|
|
||||||
k[0] = 'I'; //static IP
|
|
||||||
staticIP[i] = request->arg(k).toInt();
|
|
||||||
|
|
||||||
k[0] = 'G'; //gateway
|
|
||||||
staticGateway[i] = request->arg(k).toInt();
|
|
||||||
|
|
||||||
k[0] = 'S'; //subnet
|
|
||||||
staticSubnet[i] = request->arg(k).toInt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//LED SETTINGS
|
//LED SETTINGS
|
||||||
|
@ -424,6 +424,7 @@ void WLED::setup()
|
|||||||
escapedMac.toLowerCase();
|
escapedMac.toLowerCase();
|
||||||
|
|
||||||
WLED_SET_AP_SSID(); // otherwise it is empty on first boot until config is saved
|
WLED_SET_AP_SSID(); // otherwise it is empty on first boot until config is saved
|
||||||
|
multiWiFi.push_back(WiFiConfig(CLIENT_SSID,CLIENT_PASS)); // initialise vector with default WiFi
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading config"));
|
DEBUG_PRINTLN(F("Reading config"));
|
||||||
deserializeConfigFromFS();
|
deserializeConfigFromFS();
|
||||||
@ -445,7 +446,7 @@ void WLED::setup()
|
|||||||
usermods.setup();
|
usermods.setup();
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
|
|
||||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||||
showWelcomePage = true;
|
showWelcomePage = true;
|
||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
@ -719,8 +720,8 @@ void WLED::initConnection()
|
|||||||
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
|
||||||
|
|
||||||
if (staticIP[0] != 0 && staticGateway[0] != 0) {
|
if (multiWiFi[selectedWiFi].staticIP != 0U && multiWiFi[selectedWiFi].staticGW != 0U) {
|
||||||
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(1, 1, 1, 1));
|
WiFi.config(multiWiFi[selectedWiFi].staticIP, multiWiFi[selectedWiFi].staticGW, multiWiFi[selectedWiFi].staticSN, dnsAddress);
|
||||||
} else {
|
} else {
|
||||||
WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
|
WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
|
||||||
}
|
}
|
||||||
@ -745,13 +746,13 @@ void WLED::initConnection()
|
|||||||
showWelcomePage = false;
|
showWelcomePage = false;
|
||||||
|
|
||||||
DEBUG_PRINT(F("Connecting to "));
|
DEBUG_PRINT(F("Connecting to "));
|
||||||
DEBUG_PRINT(clientSSID);
|
DEBUG_PRINT(multiWiFi[selectedWiFi].clientSSID);
|
||||||
DEBUG_PRINTLN("...");
|
DEBUG_PRINTLN("...");
|
||||||
|
|
||||||
// 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(clientSSID, clientPass);
|
WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass);
|
||||||
#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);
|
||||||
@ -851,8 +852,9 @@ void WLED::handleConnection()
|
|||||||
if (now < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
|
if (now < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (lastReconnectAttempt == 0) {
|
if (lastReconnectAttempt == 0 || forceReconnect) {
|
||||||
DEBUG_PRINTLN(F("lastReconnectAttempt == 0"));
|
DEBUG_PRINTLN(F("Initial connect or forced reconnect."));
|
||||||
|
if (forceReconnect) selectedWiFi = 0;
|
||||||
initConnection();
|
initConnection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -915,6 +917,7 @@ 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();
|
||||||
}
|
}
|
||||||
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
|
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
|
||||||
|
@ -304,22 +304,21 @@ WLED_GLOBAL int8_t irPin _INIT(IRPIN);
|
|||||||
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
|
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
|
||||||
|
|
||||||
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
||||||
WLED_GLOBAL char clientSSID[33] _INIT(CLIENT_SSID);
|
WLED_GLOBAL uint8_t selectedWiFi _INIT(0);
|
||||||
WLED_GLOBAL char clientPass[65] _INIT(CLIENT_PASS);
|
WLED_GLOBAL std::vector<WiFiConfig> multiWiFi;
|
||||||
WLED_GLOBAL char cmDNS[33] _INIT(MDNS_NAME); // mDNS address (*.local, replaced by wledXXXXXX if default is used)
|
WLED_GLOBAL IPAddress dnsAddress _INIT_N((( 8, 8, 8, 8))); // Google's DNS
|
||||||
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup)
|
WLED_GLOBAL char cmDNS[33] _INIT(MDNS_NAME); // mDNS address (*.local, replaced by wledXXXXXX if default is used)
|
||||||
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
|
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup)
|
||||||
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
|
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
|
||||||
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
|
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
|
||||||
WLED_GLOBAL IPAddress staticIP _INIT_N((( 0, 0, 0, 0))); // static IP of ESP
|
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
|
||||||
WLED_GLOBAL IPAddress staticGateway _INIT_N((( 0, 0, 0, 0))); // gateway (router) IP
|
|
||||||
WLED_GLOBAL IPAddress staticSubnet _INIT_N(((255, 255, 255, 0))); // most common subnet in home networks
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
||||||
#else
|
#else
|
||||||
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
||||||
#endif
|
#endif
|
||||||
WLED_GLOBAL bool force802_3g _INIT(false);
|
WLED_GLOBAL bool force802_3g _INIT(false);
|
||||||
|
#define WLED_WIFI_CONFIGURED (strlen(multiWiFi[0].clientSSID) >= 1 && strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
||||||
@ -833,7 +832,6 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
|
|||||||
#else
|
#else
|
||||||
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
||||||
#endif
|
#endif
|
||||||
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
|
||||||
|
|
||||||
#ifndef WLED_AP_SSID_UNIQUE
|
#ifndef WLED_AP_SSID_UNIQUE
|
||||||
#define WLED_SET_AP_SSID() do { \
|
#define WLED_SET_AP_SSID() do { \
|
||||||
|
@ -74,11 +74,11 @@ void loadSettingsFromEEPROM()
|
|||||||
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
|
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
|
||||||
|
|
||||||
|
|
||||||
readStringFromEEPROM( 0, clientSSID, 32);
|
readStringFromEEPROM( 0, multiWiFi[0].clientSSID, 32);
|
||||||
readStringFromEEPROM( 32, clientPass, 64);
|
readStringFromEEPROM( 32, multiWiFi[0].clientPass, 64);
|
||||||
readStringFromEEPROM( 96, cmDNS, 32);
|
readStringFromEEPROM( 96, cmDNS, 32);
|
||||||
readStringFromEEPROM(128, apSSID, 32);
|
readStringFromEEPROM(128, apSSID, 32);
|
||||||
readStringFromEEPROM(160, apPass, 64);
|
readStringFromEEPROM(160, apPass, 64);
|
||||||
|
|
||||||
nightlightDelayMinsDefault = EEPROM.read(224);
|
nightlightDelayMinsDefault = EEPROM.read(224);
|
||||||
nightlightDelayMins = nightlightDelayMinsDefault;
|
nightlightDelayMins = nightlightDelayMinsDefault;
|
||||||
|
@ -248,23 +248,34 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == SUBPAGE_WIFI)
|
if (subPage == SUBPAGE_WIFI)
|
||||||
{
|
{
|
||||||
sappends('s',SET_F("CS"),clientSSID);
|
char nS[10];
|
||||||
|
size_t l;
|
||||||
byte l = strlen(clientPass);
|
oappend(SET_F("resetWiFi("));
|
||||||
char fpass[l+1]; //fill password field with ***
|
oappend(itoa(WLED_MAX_WIFI_COUNT,nS,10));
|
||||||
fpass[l] = 0;
|
oappend(SET_F(");"));
|
||||||
memset(fpass,'*',l);
|
for (size_t n = 0; n < multiWiFi.size(); n++) {
|
||||||
sappends('s',SET_F("CP"),fpass);
|
l = strlen(multiWiFi[n].clientPass);
|
||||||
|
char fpass[l+1]; //fill password field with ***
|
||||||
char k[3]; k[2] = 0; //IP addresses
|
fpass[l] = 0;
|
||||||
for (int i = 0; i<4; i++)
|
memset(fpass,'*',l);
|
||||||
{
|
oappend(SET_F("addWiFi(\""));
|
||||||
k[1] = 48+i; //ascii 0,1,2,3
|
oappend(multiWiFi[n].clientSSID);
|
||||||
k[0] = 'I'; sappend('v',k,staticIP[i]);
|
oappend(SET_F("\",\""));
|
||||||
k[0] = 'G'; sappend('v',k,staticGateway[i]);
|
oappend(fpass);
|
||||||
k[0] = 'S'; sappend('v',k,staticSubnet[i]);
|
oappend(SET_F("\",0x"));
|
||||||
|
oappend(itoa(multiWiFi[n].staticIP,nS,16));
|
||||||
|
oappend(SET_F(",0x"));
|
||||||
|
oappend(itoa(multiWiFi[n].staticGW,nS,16));
|
||||||
|
oappend(SET_F(",0x"));
|
||||||
|
oappend(itoa(multiWiFi[n].staticSN,nS,16));
|
||||||
|
oappend(SET_F(");"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sappend('v',SET_F("D0"),dnsAddress[0]);
|
||||||
|
sappend('v',SET_F("D1"),dnsAddress[1]);
|
||||||
|
sappend('v',SET_F("D2"),dnsAddress[2]);
|
||||||
|
sappend('v',SET_F("D3"),dnsAddress[3]);
|
||||||
|
|
||||||
sappends('s',SET_F("CM"),cmDNS);
|
sappends('s',SET_F("CM"),cmDNS);
|
||||||
sappend('i',SET_F("AB"),apBehavior);
|
sappend('i',SET_F("AB"),apBehavior);
|
||||||
sappends('s',SET_F("AS"),apSSID);
|
sappends('s',SET_F("AS"),apSSID);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user