Added parsing usermod settings parameters.
Added nested object handling in usermod settings parameters.
This commit is contained in:
parent
2424df0d18
commit
81182bb125
@ -29,7 +29,10 @@
|
|||||||
if (numM > 0 || locip) ldS();
|
if (numM > 0 || locip) ldS();
|
||||||
else gId("um").innerHTML = "No Usermods installed.";
|
else gId("um").innerHTML = "No Usermods installed.";
|
||||||
}
|
}
|
||||||
function check(o,k) {
|
// 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 isI(n) { return n === +n && n === (n|0); }
|
||||||
|
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++) {
|
||||||
@ -58,10 +61,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addField(k,f,o,a=false) {
|
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||||
if (isO(o)) {
|
if (isO(o)) {
|
||||||
for (const [s,v] of Object.entries(o)) {
|
for (const [s,v] of Object.entries(o)) {
|
||||||
addField(k,s,v);
|
// possibility to nest objects (only 1 level)
|
||||||
|
if (f!=='unknown' && !k.includes("_")) addField(k+"_"+f,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++) {
|
||||||
@ -73,15 +78,26 @@
|
|||||||
case "boolean":
|
case "boolean":
|
||||||
t = "checkbox"; c = o ? `checked value="on"` : ""; break;
|
t = "checkbox"; c = o ? `checked value="on"` : ""; break;
|
||||||
case "number":
|
case "number":
|
||||||
t = "number"; c = `value="${parseInt(o,10)}"`; break;
|
if (isF(o)) {
|
||||||
|
c = `value="${parseFloat(o)}" step="0.01"`;
|
||||||
|
t = "float";
|
||||||
|
} else {
|
||||||
|
c = `value="${parseInt(o,10)}"`;
|
||||||
|
if (f==="pin") c += ' max="39" min="-1"';
|
||||||
|
t = "int";
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
t = "text"; c = `value="${o}"`; break;
|
t = "text"; c = `value="${o}"`; break;
|
||||||
default:
|
default:
|
||||||
t = "text"; c = `value="${o}"`; break;
|
t = "text"; c = `value="${o}"`; break;
|
||||||
}
|
}
|
||||||
|
if (k.includes("_")) urows += k.substr(k.indexOf("_")+1);
|
||||||
|
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="off">`;
|
if (t=="checkbox") urows += `<input type="hidden" name="${k}_${f}${a?"[]":""}" value="off">`;
|
||||||
urows += `${f}: <input type="${t}" name="${k}_${f}${a?"[]":""}" ${c} oninput="check(this,'${k}')"><br>`;
|
else if (!a) urows += `<input type="hidden" name="${k}_${f}${a?"[]":""}" value="${t}">`;
|
||||||
|
urows += `<input type="${t==="float"||t==="int"?"number":t}" name="${k}_${f}${a?"[]":""}" ${c} oninput="check(this,'${k.substr(k.indexOf("_")+1)}')"><br>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function ldS() {
|
function ldS() {
|
||||||
|
@ -408,7 +408,7 @@ type="submit">Save & Reboot</button></form></body></html>)=====";
|
|||||||
// Autogenerated from wled00/data/settings_um.htm, do not edit!!
|
// Autogenerated from wled00/data/settings_um.htm, do not edit!!
|
||||||
const char PAGE_settings_um[] PROGMEM = R"=====(<!DOCTYPE html><html><head lang="en"><meta charset="utf-8"><meta
|
const char PAGE_settings_um[] PROGMEM = R"=====(<!DOCTYPE html><html><head lang="en"><meta charset="utf-8"><meta
|
||||||
name="viewport" content="width=500"><title>Usermod Settings</title><script>
|
name="viewport" content="width=500"><title>Usermod Settings</title><script>
|
||||||
var owner,locip,urows,d=document,umCfg={},pins=[6,7,8,9,10,11],pinO=["rsvd","rsvd","rsvd","rsvd","rsvd","rsvd"],loc=!1,numM=0;function gId(e){return d.getElementById(e)}function isO(e){return e&&"object"==typeof e&&!Array.isArray(e)}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings")}function B(){window.open("/settings","_self")}function S(){"file:"==window.location.protocol&&(loc=!0,(locip=localStorage.getItem("locIp"))||(locip=prompt("File Mode. Please enter WLED IP!"),localStorage.setItem("locIp",locip))),GetV(),numM>0||locip?ldS():gId("um").innerHTML="No Usermods installed."}function check(e,n){var o=e.name.replace("[]","").substr(-3);if("number"==e.type&&"pin"==o.substr(0,3))for(var i=0;i<pins.length;i++)if(n!=pinO[i]){if(e.value==pins[i]||e.value<-1||e.value>39){e.style.color="red";break}e.style.color=e.value>33?"orange":"#fff"}}function getPins(e){if(isO(e))for(const[o,i]of Object.entries(e))if(isO(i))owner=o,getPins(i);else if("pin"==o.replace("[]","").substr(-3))if(Array.isArray(i))for(var n=0;n<i.length;n++)i[n]>=0&&(pins.push(i[n]),pinO.push(owner));else i>=0&&(pins.push(i),pinO.push(owner));else if(Array.isArray(i))for(n=0;n<i.length;n++)getPins(i[n])}function addField(e,n,o,i=!1){if(isO(o))for(const[n,i]of Object.entries(o))addField(e,n,i);else if(Array.isArray(o))for(var t=0;t<o.length;t++)addField(e,n,o[t],!0);else{var r,s;switch(typeof o){case"boolean":r="checkbox",s=o?'checked value="on"':"";break;case"number":r="number",s=`value="${parseInt(o,10)}"`;break;case"string":default:r="text",s=`value="${o}"`}"checkbox"==r&&(urows+=`<input type="hidden" name="${e}_${n}${i?"[]":""}" value="off">`),urows+=`${n}: <input type="${r}" name="${e}_${n}${i?"[]":""}" ${s} oninput="check(this,'${e}')"><br>`}}function ldS(){fetch((loc?"http://"+locip:"")+"/cfg.json",{method:"get"}).then(e=>(e.ok||(gId("lserr").style.display="inline"),e.json())).then(e=>{if(umCfg=e.um,getPins(e),urows="",isO(umCfg))for(const[e,n]of Object.entries(umCfg))urows+=`<hr><h3>${e}</h3>`,addField(e,"unknown",n);""===urows&&(urows="Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults."),gId("um").innerHTML=urows}).catch((function(e){gId("lserr").style.display="inline",console.log(e)}))}function svS(e){e.preventDefault(),console.log(d.Sf),d.Sf.checkValidity()&&d.Sf.submit()}function GetV() {var d=document;
|
var owner,locip,urows,d=document,umCfg={},pins=[6,7,8,9,10,11],pinO=["rsvd","rsvd","rsvd","rsvd","rsvd","rsvd"],loc=!1,numM=0;function gId(e){return d.getElementById(e)}function isO(e){return e&&"object"==typeof e&&!Array.isArray(e)}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#usermod-settings")}function B(){window.open("/settings","_self")}function S(){"file:"==window.location.protocol&&(loc=!0,(locip=localStorage.getItem("locIp"))||(locip=prompt("File Mode. Please enter WLED IP!"),localStorage.setItem("locIp",locip))),GetV(),numM>0||locip?ldS():gId("um").innerHTML="No Usermods installed."}function isF(e){return e===+e&&e!==(0|e)}function isI(e){return e===+e&&e===(0|e)}function check(e,n){var i=e.name.replace("[]","").substr(-3);if("number"==e.type&&"pin"==i.substr(0,3))for(var o=0;o<pins.length;o++)if(n!=pinO[o]){if(e.value==pins[o]||e.value<-1||e.value>39){e.style.color="red";break}e.style.color=e.value>33?"orange":"#fff"}}function getPins(e){if(isO(e))for(const[i,o]of Object.entries(e))if(isO(o))owner=i,getPins(o);else if("pin"==i.replace("[]","").substr(-3))if(Array.isArray(o))for(var n=0;n<o.length;n++)o[n]>=0&&(pins.push(o[n]),pinO.push(owner));else o>=0&&(pins.push(o),pinO.push(owner));else if(Array.isArray(o))for(n=0;n<o.length;n++)getPins(o[n])}function addField(e,n,i,o=!1){if(isO(i))for(const[o,t]of Object.entries(i))"unknown"===n||e.includes("_")?addField(e,o,t):addField(e+"_"+n,o,t);else if(Array.isArray(i))for(var t=0;t<i.length;t++)addField(e,n,i[t],!0);else{var s,r;switch(typeof i){case"boolean":s="checkbox",r=i?'checked value="on"':"";break;case"number":isF(i)?(r=`value="${parseFloat(i)}" step="0.01"`,s="float"):(r=`value="${parseInt(i,10)}"`,"pin"===n&&(r+=' max="39" min="-1"'),s="int");break;case"string":default:s="text",r=`value="${i}"`}e.includes("_")&&(urows+=e.substr(e.indexOf("_")+1)),urows+=` ${n}: `,"checkbox"==s?urows+=`<input type="hidden" name="${e}_${n}${o?"[]":""}" value="off">`:o||(urows+=`<input type="hidden" name="${e}_${n}${o?"[]":""}" value="${s}">`),urows+=`<input type="${"float"===s||"int"===s?"number":s}" name="${e}_${n}${o?"[]":""}" ${r} oninput="check(this,'${e.substr(e.indexOf("_")+1)}')"><br>`}}function ldS(){fetch((loc?"http://"+locip:"")+"/cfg.json",{method:"get"}).then(e=>(e.ok||(gId("lserr").style.display="inline"),e.json())).then(e=>{if(umCfg=e.um,getPins(e),urows="",isO(umCfg))for(const[e,n]of Object.entries(umCfg))urows+=`<hr><h3>${e}</h3>`,addField(e,"unknown",n);""===urows&&(urows="Usermods configuration not found.<br>Press <i>Save</i> to initialize defaults."),gId("um").innerHTML=urows}).catch((function(e){gId("lserr").style.display="inline",console.log(e)}))}function svS(e){e.preventDefault(),console.log(d.Sf),d.Sf.checkValidity()&&d.Sf.submit()}function GetV() {var d=document;
|
||||||
%CSS%%SCSS%<link href="/skin.css"
|
%CSS%%SCSS%<link href="/skin.css"
|
||||||
rel="stylesheet"></head><body onload="S()"><form id="form_s" name="Sf"
|
rel="stylesheet"></head><body onload="S()"><form id="form_s" name="Sf"
|
||||||
method="post" onsubmit="svS(event)"><div class="toprow"><div class="helpB">
|
method="post" onsubmit="svS(event)"><div class="toprow"><div class="helpB">
|
||||||
|
@ -431,7 +431,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
|
|
||||||
// POST request parameters are combined as <usermodname>_<usermodparameter>
|
// POST request parameters are combined as <usermodname>_<usermodparameter>
|
||||||
uint8_t umNameEnd = name.indexOf("_");
|
uint8_t umNameEnd = name.indexOf("_");
|
||||||
if (!umNameEnd) break; // parameter does not contain "_" -> wrong
|
if (umNameEnd<1) break; // parameter does not contain "_" or on 1st place -> wrong
|
||||||
|
|
||||||
JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object
|
JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object
|
||||||
if (mod.isNull()) {
|
if (mod.isNull()) {
|
||||||
@ -441,15 +441,27 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
DEBUG_PRINT(":");
|
DEBUG_PRINT(":");
|
||||||
name = name.substring(umNameEnd+1); // remove mod name from string
|
name = name.substring(umNameEnd+1); // remove mod name from string
|
||||||
|
|
||||||
|
// if the resulting name still contains "_" this means nested object
|
||||||
|
JsonObject subObj;
|
||||||
|
uint8_t umSubObj = name.indexOf("_");
|
||||||
|
if (umSubObj>0) {
|
||||||
|
subObj = mod[name.substring(0,umSubObj-1)];
|
||||||
|
if (subObj.isNull())
|
||||||
|
subObj = mod.createNestedObject(name.substring(0,umSubObj-1));
|
||||||
|
name = name.substring(umSubObj+1); // remove nested object name from string
|
||||||
|
} else {
|
||||||
|
subObj = mod;
|
||||||
|
}
|
||||||
|
|
||||||
// check if parameters represent array
|
// check if parameters represent array
|
||||||
if (name.endsWith("[]")) {
|
if (name.endsWith("[]")) {
|
||||||
name.replace("[]","");
|
name.replace("[]","");
|
||||||
if (!mod[name].is<JsonArray>()) {
|
if (!subObj[name].is<JsonArray>()) {
|
||||||
JsonArray ar = mod.createNestedArray(name);
|
JsonArray ar = subObj.createNestedArray(name);
|
||||||
ar.add(value);
|
ar.add(value.toInt());
|
||||||
j=0;
|
j=0;
|
||||||
} else {
|
} else {
|
||||||
mod[name].add(value);
|
subObj[name].add(value.toInt());
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
DEBUG_PRINT(name);
|
DEBUG_PRINT(name);
|
||||||
@ -458,8 +470,20 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
DEBUG_PRINT("] = ");
|
DEBUG_PRINT("] = ");
|
||||||
DEBUG_PRINTLN(value);
|
DEBUG_PRINTLN(value);
|
||||||
} else {
|
} else {
|
||||||
mod.remove(name); // checkboxes get two fields (first is always "off", existence of second depends on checkmark and may be "on")
|
// we are using a hidden field with the same name as our parameter (!before the actual parameter!)
|
||||||
mod[name] = value;
|
// to describe the type of parameter (text,float,int), for boolean patameters the first field contains "off"
|
||||||
|
// so checkboxes have one or two fields (first is always "off", existence of second depends on checkmark and may be "on")
|
||||||
|
if (subObj[name].isNull()) {
|
||||||
|
// the first occurence of the field describes the parameter type (used in next loop)
|
||||||
|
if (value == "off") subObj[name] = false; // checkboxes may have only one field
|
||||||
|
else subObj[name] = value;
|
||||||
|
} else {
|
||||||
|
String type = subObj[name].as<String>(); // get previously stored value as a type
|
||||||
|
if (subObj[name].is<bool>()) subObj[name] = true; // checkbox/boolean
|
||||||
|
else if (type == "float") subObj[name] = value.toDouble();
|
||||||
|
else if (type == "int") subObj[name] = value.toInt();
|
||||||
|
else subObj[name] = value; // text fields
|
||||||
|
}
|
||||||
DEBUG_PRINT(name);
|
DEBUG_PRINT(name);
|
||||||
DEBUG_PRINT(" = ");
|
DEBUG_PRINT(" = ");
|
||||||
DEBUG_PRINTLN(value);
|
DEBUG_PRINTLN(value);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2106251
|
#define VERSION 2106260
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
Loading…
Reference in New Issue
Block a user