S2, S3 & C3 support for settings.
This commit is contained in:
parent
2cd40c7552
commit
4f8ffaee5b
@ -23,7 +23,12 @@
|
|||||||
// success event
|
// success event
|
||||||
scE.addEventListener("load", () => {
|
scE.addEventListener("load", () => {
|
||||||
//console.log("File loaded");
|
//console.log("File loaded");
|
||||||
|
d.um_p = [];
|
||||||
|
d.rsvd = [];
|
||||||
|
d.ro_pins = [];
|
||||||
|
d.max_gpio = 39;
|
||||||
GetV();checkSi();setABL();
|
GetV();checkSi();setABL();
|
||||||
|
if (d.um_p[0]==-1) d.um_p.shift();
|
||||||
});
|
});
|
||||||
// error event
|
// error event
|
||||||
scE.addEventListener("error", (ev) => {
|
scE.addEventListener("error", (ev) => {
|
||||||
@ -58,8 +63,8 @@
|
|||||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||||
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.um_p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.um_p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||||
else if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].value="";LCs[i].focus();return false;}
|
//else if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].value="";LCs[i].focus();return false;}
|
||||||
else if (!(nm == "IR" || nm=="BT") && LCs[i].value > 33) {alert("Sorry, pins >33 are input only.");LCs[i].value="";LCs[i].focus();return false;}
|
else if (!(nm == "IR" || nm=="BT") && d.ro_pins.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.ro_gpio)} are input only.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||||
for (j=i+1; j<LCs.length; j++)
|
for (j=i+1; j<LCs.length; j++)
|
||||||
{
|
{
|
||||||
var n2 = LCs[j].name.substring(0,2);
|
var n2 = LCs[j].name.substring(0,2);
|
||||||
@ -230,7 +235,7 @@
|
|||||||
LCs[i].style.color="#fff";
|
LCs[i].style.color="#fff";
|
||||||
continue; // do not check conflicts
|
continue; // do not check conflicts
|
||||||
} else {
|
} else {
|
||||||
LCs[i].max = 33;
|
LCs[i].max = d.max_gpio;
|
||||||
LCs[i].min = -1;
|
LCs[i].min = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +243,8 @@
|
|||||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||||
var p = []; // used pin array
|
var p = []; // used pin array
|
||||||
if (d.um_p && Array.isArray(d.um_p)) for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with reservations
|
for (k=0;k<d.rsvd.length;k++) p.push(d.rsvd[k]); // fill with reservations
|
||||||
|
for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]); // fill with usermod pins
|
||||||
for (j=0; j<LCs.length; j++) {
|
for (j=0; j<LCs.length; j++) {
|
||||||
if (i==j) continue;
|
if (i==j) continue;
|
||||||
var n2 = LCs[j].name.substring(0,2);
|
var n2 = LCs[j].name.substring(0,2);
|
||||||
@ -252,8 +258,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// now check for conflicts
|
// now check for conflicts
|
||||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color=parseInt(LCs[i].value,10)>33?"orange":"#fff";
|
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color=d.ro_gpio.some((e)=>e==parseInt(LCs[i].value,10))?"orange":"#fff";
|
||||||
}
|
}
|
||||||
|
// check buttons, IR & relay
|
||||||
|
if (nm=="IR" || nm=="BT" || nm=="RL") {
|
||||||
|
LCs[i].max = d.max_gpio;
|
||||||
|
LCs[i].min = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// update total led count
|
// update total led count
|
||||||
gId("lc").textContent = sLC;
|
gId("lc").textContent = sLC;
|
||||||
@ -605,7 +616,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
<hr style="width:260px">
|
<hr style="width:260px">
|
||||||
<div id="btns"></div>
|
<div id="btns"></div>
|
||||||
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
|
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
|
||||||
IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()">
|
IR GPIO: <input type="number" min="-1" max="39" name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()">
|
||||||
<option value=0>Remote disabled</option>
|
<option value=0>Remote disabled</option>
|
||||||
<option value=1>24-key RGB</option>
|
<option value=1>24-key RGB</option>
|
||||||
<option value=2>24-key with CT</option>
|
<option value=2>24-key with CT</option>
|
||||||
@ -619,7 +630,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
|
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
|
||||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
|
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
|
||||||
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
|
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
|
||||||
Relay GPIO: <input type="number" min="-1" max="33" name="RL" onchange="UI()" class="xs"> Invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
Relay GPIO: <input type="number" min="-1" max="39" name="RL" onchange="UI()" class="xs"> Invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ✕</span><br>
|
||||||
<hr style="width:260px">
|
<hr style="width:260px">
|
||||||
<h3>Defaults</h3>
|
<h3>Defaults</h3>
|
||||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head lang="en">
|
<head lang="en">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=500">
|
<meta name="viewport" content="width=500">
|
||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>Usermod Settings</title>
|
<title>Usermod Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
var umCfg = {};
|
var umCfg = {};
|
||||||
var pins = [6,7,8,9,10,11];
|
var pins = [], pinO = [], owner;
|
||||||
var pinO = ["rsvd","rsvd","rsvd","rsvd","rsvd","rsvd"], owner;
|
var loc = false, locip;
|
||||||
var loc = false, locip;
|
var urows;
|
||||||
var urows;
|
var numM = 0;
|
||||||
var numM = 0;
|
function gId(s) { return d.getElementById(s); }
|
||||||
function gId(s) { return d.getElementById(s); }
|
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
||||||
function isO(i) { return (i && typeof i === 'object' && !Array.isArray(i)); }
|
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
||||||
function H() { window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings"); }
|
function B() { window.open("/settings","_self"); }
|
||||||
function B() { window.open("/settings","_self"); }
|
|
||||||
// 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 = d.createElement("script");
|
let scE = d.createElement("script");
|
||||||
@ -27,7 +26,13 @@
|
|||||||
// success event
|
// success event
|
||||||
scE.addEventListener("load", () => {
|
scE.addEventListener("load", () => {
|
||||||
//console.log("File loaded");
|
//console.log("File loaded");
|
||||||
|
d.um_p = [];
|
||||||
|
d.rsvd = [];
|
||||||
|
d.ro_pins = [];
|
||||||
|
d.max_gpio = 39;
|
||||||
GetV();
|
GetV();
|
||||||
|
for (let k=0; k<d.rsvd.length; k++) { pins.push(d.rsvd[k]); pinO.push("rsvd"); }
|
||||||
|
if (d.um_p[0]==-1) d.um_p.shift();
|
||||||
});
|
});
|
||||||
// error event
|
// error event
|
||||||
scE.addEventListener("error", (ev) => {
|
scE.addEventListener("error", (ev) => {
|
||||||
@ -35,182 +40,182 @@
|
|||||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function S() {
|
function S() {
|
||||||
if (window.location.protocol == "file:") {
|
if (window.location.protocol == "file:") {
|
||||||
loc = true;
|
loc = true;
|
||||||
locip = localStorage.getItem('locIp');
|
locip = localStorage.getItem('locIp');
|
||||||
if (!locip) {
|
if (!locip) {
|
||||||
locip = prompt("File Mode. Please enter WLED IP!");
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
localStorage.setItem('locIp', locip);
|
localStorage.setItem('locIp', locip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ldS();
|
ldS();
|
||||||
if (!numM) gId("um").innerHTML = "No Usermods installed.";
|
if (!numM) gId("um").innerHTML = "No Usermods installed.";
|
||||||
}
|
}
|
||||||
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
// https://stackoverflow.com/questions/3885817/how-do-i-check-that-a-number-is-float-or-integer
|
||||||
function isF(n) { return n === +n && n !== (n|0); }
|
function isF(n) { return n === +n && n !== (n|0); }
|
||||||
function isI(n) { return n === +n && n === (n|0); }
|
function isI(n) { return n === +n && n === (n|0); }
|
||||||
function check(o,k) { // input object, pin owner key
|
function check(o,k) { // input object, pin owner key
|
||||||
var n = o.name.replace("[]","").substr(-3);
|
var n = o.name.replace("[]","").substr(-3);
|
||||||
if (o.type=="number" && n.substr(0,3)=="pin") {
|
if (o.type=="number" && n.substr(0,3)=="pin") {
|
||||||
for (var i=0; i<pins.length; i++) {
|
for (var i=0; i<pins.length; i++) {
|
||||||
if (k==pinO[i]) continue;
|
if (k==pinO[i]) continue;
|
||||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
||||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
if (o.value==pins[i] || o.value<-1 || o.value>d.max_gpio) { o.style.color="red"; break; } else o.style.color=d.ro_gpio.some((e)=>e==parseInt(o.value,10))?"orange":"#fff";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (o.name) {
|
switch (o.name) {
|
||||||
case "SDA": break;
|
case "SDA": break;
|
||||||
case "SCL": break;
|
case "SCL": break;
|
||||||
case "MOSI": break;
|
case "MOSI": break;
|
||||||
case "SCLK": break;
|
case "SCLK": break;
|
||||||
case "CS": break;
|
case "MISO": break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
for (var i=0; i<pins.length; i++) {
|
for (var i=0; i<pins.length; i++) {
|
||||||
if (k==pinO[i]) continue;
|
//if (k==pinO[i]) continue; // same owner
|
||||||
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="lime"; break; }
|
if (o.value==pins[i] && pinO[i]==="if") { o.style.color="tomato"; break; }
|
||||||
if (o.value==pins[i] || o.value<-1 || o.value>39) { o.style.color="red"; break; } else o.style.color=o.value>33?"orange":"#fff";
|
if (o.value==pins[i] || o.value<-1 || o.value>d.max_gpio) { o.style.color="red"; break; } else o.style.color=d.ro_gpio.some((e)=>e==parseInt(o.value,10))?"orange":"#fff";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getPins(o) {
|
function getPins(o) {
|
||||||
if (isO(o)) {
|
if (isO(o)) {
|
||||||
for (const [k,v] of Object.entries(o)) {
|
for (const [k,v] of Object.entries(o)) {
|
||||||
if (isO(v)) {
|
if (isO(v)) {
|
||||||
owner = k;
|
owner = k;
|
||||||
getPins(v);
|
getPins(v);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (k.replace("[]","").substr(-3)=="pin") {
|
if (k.replace("[]","").substr(-3)=="pin") {
|
||||||
if (Array.isArray(v)) {
|
if (Array.isArray(v)) {
|
||||||
for (var i=0; i<v.length; i++) if (v[i]>=0) { pins.push(v[i]); pinO.push(owner); }
|
for (var i=0; i<v.length; i++) if (v[i]>=0) { pins.push(v[i]); pinO.push(owner); }
|
||||||
} else {
|
} else {
|
||||||
if (v>=0) { pins.push(v); pinO.push(owner); }
|
if (v>=0) { pins.push(v); pinO.push(owner); }
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(v)) {
|
} else if (Array.isArray(v)) {
|
||||||
for (var i=0; i<v.length; i++) getPins(v[i]);
|
for (var i=0; i<v.length; i++) getPins(v[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||||
if (isO(o)) {
|
if (isO(o)) {
|
||||||
urows += '<hr style="width:260px">';
|
urows += '<hr style="width:260px">';
|
||||||
for (const [s,v] of Object.entries(o)) {
|
for (const [s,v] of Object.entries(o)) {
|
||||||
// possibility to nest objects (only 1 level)
|
// possibility to nest objects (only 1 level)
|
||||||
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
||||||
else addField(k,s,v);
|
else addField(k,s,v);
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(o)) {
|
} else if (Array.isArray(o)) {
|
||||||
for (var j=0; j<o.length; j++) {
|
for (var j=0; j<o.length; j++) {
|
||||||
addField(k,f,o[j],true);
|
addField(k,f,o[j],true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var c, t = typeof o;
|
var c, t = typeof o;
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
t = "checkbox"; c = 'value="true"' + (o ? ' checked' : '');
|
t = "checkbox"; c = 'value="true"' + (o ? ' checked' : '');
|
||||||
break;
|
break;
|
||||||
case "number":
|
case "number":
|
||||||
c = `value="${o}"`;
|
c = `value="${o}"`;
|
||||||
if (f.substr(-3)==="pin") {
|
if (f.substr(-3)==="pin") {
|
||||||
c += ' max="39" min="-1" class="s"';
|
c += ` max="${d.max_gpio}" min="-1" class="s"`;
|
||||||
t = "int";
|
t = "int";
|
||||||
} else {
|
} else {
|
||||||
c += ' step="any" class="xxl"';
|
c += ' step="any" class="xxl"';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
t = "text"; c = `value="${o}" style="width:250px;"`;
|
t = "text"; c = `value="${o}" style="width:250px;"`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (k.includes(":")) urows += k.substr(k.indexOf(":")+1);
|
if (k.includes(":")) urows += k.substr(k.indexOf(":")+1);
|
||||||
urows += ` ${f}: `;
|
urows += ` ${f}: `;
|
||||||
// https://stackoverflow.com/questions/11657123/posting-both-checked-and-unchecked-checkboxes
|
// https://stackoverflow.com/questions/11657123/posting-both-checked-and-unchecked-checkboxes
|
||||||
if (t=="checkbox") urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="false">`;
|
if (t=="checkbox") urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="false">`;
|
||||||
else if (!a) urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="${t}">`;
|
else if (!a) urows += `<input type="hidden" name="${k}:${f}${a?"[]":""}" value="${t}">`;
|
||||||
urows += `<input type="${t==="int"?"number":t}" name="${k}:${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf(":")+1)}')"><br>`;
|
urows += `<input type="${t==="int"?"number":t}" name="${k}:${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf(":")+1)}')"><br>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
|
||||||
function addDropdown(um,fld) {
|
function addDropdown(um,fld) {
|
||||||
let sel = d.createElement('select');
|
let sel = d.createElement('select');
|
||||||
let arr = d.getElementsByName(um+":"+fld);
|
let arr = d.getElementsByName(um+":"+fld);
|
||||||
let inp = arr[1]; // assume 1st field to be hidden (type)
|
let inp = arr[1]; // assume 1st field to be hidden (type)
|
||||||
if (inp && inp.tagName === "INPUT" && (inp.type === "text" || inp.type === "number")) { // may also use nodeName
|
if (inp && inp.tagName === "INPUT" && (inp.type === "text" || inp.type === "number")) { // may also use nodeName
|
||||||
let v = inp.value;
|
let v = inp.value;
|
||||||
let n = inp.name;
|
let n = inp.name;
|
||||||
// copy the existing input element's attributes to the new select element
|
// copy the existing input element's attributes to the new select element
|
||||||
for (var i = 0; i < inp.attributes.length; ++ i) {
|
for (var i = 0; i < inp.attributes.length; ++ i) {
|
||||||
var att = inp.attributes[i];
|
var att = inp.attributes[i];
|
||||||
// type and value don't apply, so skip them
|
// type and value don't apply, so skip them
|
||||||
// ** you might also want to skip style, or others -- modify as needed **
|
// ** you might also want to skip style, or others -- modify as needed **
|
||||||
if (att.name != 'type' && att.name != 'value' && att.name != 'class' && att.name != 'style') {
|
if (att.name != 'type' && att.name != 'value' && att.name != 'class' && att.name != 'style') {
|
||||||
sel.setAttribute(att.name, att.value);
|
sel.setAttribute(att.name, att.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sel.setAttribute("data-val", v);
|
sel.setAttribute("data-val", v);
|
||||||
// finally, replace the old input element with the new select element
|
// finally, replace the old input element with the new select element
|
||||||
inp.parentElement.replaceChild(sel, inp);
|
inp.parentElement.replaceChild(sel, inp);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
function addOption(sel,txt,val) {
|
function addOption(sel,txt,val) {
|
||||||
if (sel===null) return; // select object missing
|
if (sel===null) return; // select object missing
|
||||||
let opt = d.createElement("option");
|
let opt = d.createElement("option");
|
||||||
opt.value = val;
|
opt.value = val;
|
||||||
opt.text = txt;
|
opt.text = txt;
|
||||||
sel.appendChild(opt);
|
sel.appendChild(opt);
|
||||||
for (let i=0; i<sel.childNodes.length; i++) {
|
for (let i=0; i<sel.childNodes.length; i++) {
|
||||||
let c = sel.childNodes[i];
|
let c = sel.childNodes[i];
|
||||||
if (c.value == sel.dataset.val) sel.selectedIndex = i;
|
if (c.value == sel.dataset.val) sel.selectedIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
|
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
|
||||||
function addInfo(name,el,txt) {
|
function addInfo(name,el,txt) {
|
||||||
let obj = d.getElementsByName(name);
|
let obj = d.getElementsByName(name);
|
||||||
if (!obj.length) return;
|
if (!obj.length) return;
|
||||||
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
|
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
|
||||||
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
else if (obj[el]) obj[el].insertAdjacentHTML('afterend', ' '+txt);
|
||||||
}
|
}
|
||||||
// load settings and insert values into DOM
|
// load settings and insert values into DOM
|
||||||
function ldS() {
|
function ldS() {
|
||||||
var url = (loc?`http://${locip}`:'') + '/cfg.json';
|
var url = (loc?`http://${locip}`:'') + '/cfg.json';
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (!res.ok) gId('lserr').style.display = "inline";
|
if (!res.ok) gId('lserr').style.display = "inline";
|
||||||
return res.json();
|
return res.json();
|
||||||
})
|
})
|
||||||
.then(json => {
|
.then(json => {
|
||||||
umCfg = json.um;
|
umCfg = json.um;
|
||||||
getPins(json);
|
getPins(json);
|
||||||
urows="";
|
urows="";
|
||||||
if (isO(umCfg)) {
|
if (isO(umCfg)) {
|
||||||
for (const [k,o] of Object.entries(umCfg)) {
|
for (const [k,o] of Object.entries(umCfg)) {
|
||||||
urows += `<hr><h3>${k}</h3>`;
|
urows += `<hr><h3>${k}</h3>`;
|
||||||
addField(k,'unknown',o);
|
addField(k,'unknown',o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
if (urows==="") urows = "Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults.";
|
||||||
gId("um").innerHTML = urows;
|
gId("um").innerHTML = urows;
|
||||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=8';
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=8';
|
||||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
})
|
})
|
||||||
.catch((error)=>{
|
.catch((error)=>{
|
||||||
gId('lserr').style.display = "inline";
|
gId('lserr').style.display = "inline";
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function svS(e) {
|
function svS(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body onload="S()">
|
<body onload="S()">
|
||||||
@ -222,17 +227,17 @@
|
|||||||
<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span><hr>
|
<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span><hr>
|
||||||
</div>
|
</div>
|
||||||
<h2>Usermod Setup</h2>
|
<h2>Usermod Setup</h2>
|
||||||
Global I<sup>2</sup>C GPIOs (HW)<br>
|
Global I<sup>2</sup>C GPIOs (HW)<br>
|
||||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||||
SDA:<input type="number" min="-1" max="33" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
|
SDA:<input type="number" min="-1" max="33" name="SDA" onchange="check(this,'if')" class="s" placeholder="SDA">
|
||||||
SCL:<input type="number" min="-1" max="33" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
|
SCL:<input type="number" min="-1" max="33" name="SCL" onchange="check(this,'if')" class="s" placeholder="SCL">
|
||||||
<hr style="width:260px">
|
<hr style="width:260px">
|
||||||
Global SPI GPIOs (HW)<br>
|
Global SPI GPIOs (HW)<br>
|
||||||
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
<i style="color: orange;">(only changable on ESP32, change requires reboot!)</i><br>
|
||||||
MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
|
MOSI:<input type="number" min="-1" max="33" name="MOSI" onchange="check(this,'if')" class="s" placeholder="MOSI">
|
||||||
MISO:<input type="number" min="-1" max="33" name="MISO" onchange="check(this,'if')" class="s" placeholder="MISO">
|
MISO:<input type="number" min="-1" max="33" name="MISO" onchange="check(this,'if')" class="s" placeholder="MISO">
|
||||||
SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
|
SCLK:<input type="number" min="-1" max="33" name="SCLK" onchange="check(this,'if')" class="s" placeholder="SCLK">
|
||||||
<div id="um">Loading settings...</div>
|
<div id="um">Loading settings...</div>
|
||||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
|
File diff suppressed because it is too large
Load Diff
173
wled00/xml.cpp
173
wled00/xml.cpp
@ -167,6 +167,104 @@ void fillUMPins(JsonObject &mods)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void appendGPIOinfo() {
|
||||||
|
char nS[8];
|
||||||
|
|
||||||
|
oappend(SET_F("d.um_p=[-1")); // has to have 1 element
|
||||||
|
if (i2c_sda > -1 && i2c_scl > -1) {
|
||||||
|
oappend(","); oappend(itoa(i2c_sda,nS,10));
|
||||||
|
oappend(","); oappend(itoa(i2c_scl,nS,10));
|
||||||
|
}
|
||||||
|
if (spi_mosi > -1 && spi_sclk > -1) {
|
||||||
|
oappend(","); oappend(itoa(spi_mosi,nS,10));
|
||||||
|
oappend(","); oappend(itoa(spi_sclk,nS,10));
|
||||||
|
}
|
||||||
|
// usermod pin reservations will become unnecessary when settings pages will read cfg.json directly
|
||||||
|
if (requestJSONBufferLock(6)) {
|
||||||
|
// if we can't allocate JSON buffer ignore usermod pins
|
||||||
|
JsonObject mods = doc.createNestedObject(F("um"));
|
||||||
|
usermods.addToConfig(mods);
|
||||||
|
if (!mods.isNull()) fillUMPins(mods);
|
||||||
|
releaseJSONBufferLock();
|
||||||
|
}
|
||||||
|
oappend(SET_F("];"));
|
||||||
|
|
||||||
|
// add reserved and usermod pins as d.um_p array
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
oappend(SET_F("d.rsvd=[22,23,24,25,26,27,28,29,30,31,32"));
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
oappend(SET_F("d.rsvd=[11,12,13,14,15,16,17"));
|
||||||
|
#elif defined(ESP32)
|
||||||
|
oappend(SET_F("d.rsvd=[6,7,8,9,10,11,24,28,29,30,31,37,38"));
|
||||||
|
#else
|
||||||
|
oappend(SET_F("d.rsvd=[6,7,8,9,10,11"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLED_ENABLE_DMX
|
||||||
|
oappend(SET_F(",2")); // DMX hardcoded pin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG
|
||||||
|
oappend(SET_F(",")); oappend(itoa(TX,nS,10));// debug output (TX) pin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||||
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM on ESP32 (not on S2, S3 or C3)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WLED_USE_ETHERNET
|
||||||
|
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||||
|
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
|
||||||
|
if (ethernetBoards[ethernetType].eth_power>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); }
|
||||||
|
if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); }
|
||||||
|
if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); }
|
||||||
|
switch (ethernetBoards[ethernetType].eth_clk_mode) {
|
||||||
|
case ETH_CLOCK_GPIO0_IN:
|
||||||
|
case ETH_CLOCK_GPIO0_OUT:
|
||||||
|
oappend(SET_F(",0"));
|
||||||
|
break;
|
||||||
|
case ETH_CLOCK_GPIO16_OUT:
|
||||||
|
oappend(SET_F(",16"));
|
||||||
|
break;
|
||||||
|
case ETH_CLOCK_GPIO17_OUT:
|
||||||
|
oappend(SET_F(",17"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oappend(SET_F("];"));
|
||||||
|
|
||||||
|
// add info for read-only GPIO
|
||||||
|
oappend(SET_F("d.ro_gpio=["));
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
oappendi(46);
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
// none for C3
|
||||||
|
#elif defined(ESP32)
|
||||||
|
oappend(SET_F("34,35,36,39"));
|
||||||
|
#else
|
||||||
|
// none for ESP8266
|
||||||
|
#endif
|
||||||
|
oappend(SET_F("];"));
|
||||||
|
|
||||||
|
// add info about max. # of pins
|
||||||
|
oappend(SET_F("d.max_gpio="));
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
oappendi(46);
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
oappendi(21);
|
||||||
|
#elif defined(ESP32)
|
||||||
|
oappendi(39);
|
||||||
|
#else
|
||||||
|
oappendi(16);
|
||||||
|
#endif
|
||||||
|
oappend(SET_F(";"));
|
||||||
|
}
|
||||||
|
|
||||||
//get values for settings form in javascript
|
//get values for settings form in javascript
|
||||||
void getSettingsJS(byte subPage, char* dest)
|
void getSettingsJS(byte subPage, char* dest)
|
||||||
@ -257,63 +355,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
{
|
{
|
||||||
char nS[8];
|
char nS[8];
|
||||||
|
|
||||||
// Pin reservations will become unnecessary when settings pages will read cfg.json directly
|
appendGPIOinfo();
|
||||||
// add reserved and usermod pins as d.um_p array
|
|
||||||
oappend(SET_F("d.um_p=[6,7,8,9,10,11"));
|
|
||||||
|
|
||||||
if (i2c_sda > -1 && i2c_scl > -1) {
|
|
||||||
oappend(","); oappend(itoa(i2c_sda,nS,10));
|
|
||||||
oappend(","); oappend(itoa(i2c_scl,nS,10));
|
|
||||||
}
|
|
||||||
if (spi_mosi > -1 && spi_sclk > -1) {
|
|
||||||
oappend(","); oappend(itoa(spi_mosi,nS,10));
|
|
||||||
oappend(","); oappend(itoa(spi_sclk,nS,10));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestJSONBufferLock(6)) {
|
|
||||||
// if we can't allocate JSON buffer ignore usermod pins
|
|
||||||
JsonObject mods = doc.createNestedObject(F("um"));
|
|
||||||
usermods.addToConfig(mods);
|
|
||||||
if (!mods.isNull()) fillUMPins(mods);
|
|
||||||
releaseJSONBufferLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_DMX
|
|
||||||
oappend(SET_F(",2")); // DMX hardcoded pin
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
|
||||||
oappend(SET_F(",1")); // debug output (TX) pin
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//Note: Using pin 3 (RX) disables Adalight / Serial JSON
|
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
|
||||||
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
|
||||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
|
||||||
for (uint8_t p=0; p<WLED_ETH_RSVD_PINS_COUNT; p++) { oappend(","); oappend(itoa(esp32_nonconfigurable_ethernet_pins[p].pin,nS,10)); }
|
|
||||||
if (ethernetBoards[ethernetType].eth_power>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); }
|
|
||||||
if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); }
|
|
||||||
if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); }
|
|
||||||
switch (ethernetBoards[ethernetType].eth_clk_mode) {
|
|
||||||
case ETH_CLOCK_GPIO0_IN:
|
|
||||||
case ETH_CLOCK_GPIO0_OUT:
|
|
||||||
oappend(SET_F(",0"));
|
|
||||||
break;
|
|
||||||
case ETH_CLOCK_GPIO16_OUT:
|
|
||||||
oappend(SET_F(",16"));
|
|
||||||
break;
|
|
||||||
case ETH_CLOCK_GPIO17_OUT:
|
|
||||||
oappend(SET_F(",17"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
oappend(SET_F("];"));
|
|
||||||
|
|
||||||
// set limits
|
// set limits
|
||||||
oappend(SET_F("bLimits("));
|
oappend(SET_F("bLimits("));
|
||||||
@ -500,14 +542,14 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
char hueErrorString[25];
|
char hueErrorString[25];
|
||||||
switch (hueError)
|
switch (hueError)
|
||||||
{
|
{
|
||||||
case HUE_ERROR_INACTIVE : strcpy(hueErrorString,(char*)F("Inactive")); break;
|
case HUE_ERROR_INACTIVE : strcpy_P(hueErrorString,PSTR("Inactive")); break;
|
||||||
case HUE_ERROR_ACTIVE : strcpy(hueErrorString,(char*)F("Active")); break;
|
case HUE_ERROR_ACTIVE : strcpy_P(hueErrorString,PSTR("Active")); break;
|
||||||
case HUE_ERROR_UNAUTHORIZED : strcpy(hueErrorString,(char*)F("Unauthorized")); break;
|
case HUE_ERROR_UNAUTHORIZED : strcpy_P(hueErrorString,PSTR("Unauthorized")); break;
|
||||||
case HUE_ERROR_LIGHTID : strcpy(hueErrorString,(char*)F("Invalid light ID")); break;
|
case HUE_ERROR_LIGHTID : strcpy_P(hueErrorString,PSTR("Invalid light ID")); break;
|
||||||
case HUE_ERROR_PUSHLINK : strcpy(hueErrorString,(char*)F("Link button not pressed")); break;
|
case HUE_ERROR_PUSHLINK : strcpy_P(hueErrorString,PSTR("Link button not pressed")); break;
|
||||||
case HUE_ERROR_JSON_PARSING : strcpy(hueErrorString,(char*)F("JSON parsing error")); break;
|
case HUE_ERROR_JSON_PARSING : strcpy_P(hueErrorString,PSTR("JSON parsing error")); break;
|
||||||
case HUE_ERROR_TIMEOUT : strcpy(hueErrorString,(char*)F("Timeout")); break;
|
case HUE_ERROR_TIMEOUT : strcpy_P(hueErrorString,PSTR("Timeout")); break;
|
||||||
default: sprintf(hueErrorString,(char*)F("Bridge Error %i"),hueError);
|
default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError);
|
||||||
}
|
}
|
||||||
|
|
||||||
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
|
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
|
||||||
@ -630,6 +672,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == 8) //usermods
|
if (subPage == 8) //usermods
|
||||||
{
|
{
|
||||||
|
appendGPIOinfo();
|
||||||
oappend(SET_F("numM="));
|
oappend(SET_F("numM="));
|
||||||
oappendi(usermods.getModCount());
|
oappendi(usermods.getModCount());
|
||||||
oappend(";");
|
oappend(";");
|
||||||
|
Loading…
Reference in New Issue
Block a user