Multi button implementation.

This commit is contained in:
Blaz Kristan 2021-05-19 18:39:16 +02:00
parent a5a25f02e3
commit 95df91a03b
13 changed files with 1736 additions and 1606 deletions

View File

@ -6,20 +6,20 @@
#define WLED_DEBOUNCE_THRESHOLD 50 //only consider button input of at least 50ms as valid (debouncing) #define WLED_DEBOUNCE_THRESHOLD 50 //only consider button input of at least 50ms as valid (debouncing)
void shortPressAction() void shortPressAction(uint8_t b)
{ {
if (!macroButton) if (!macroButton[b])
{ {
toggleOnOff(); toggleOnOff();
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
} else { } else {
applyPreset(macroButton); applyPreset(macroButton[b]);
} }
} }
bool isButtonPressed() bool isButtonPressed(uint8_t i)
{ {
if (btnPin>=0 && digitalRead(btnPin) == LOW) return true; if (btnPin[i]>=0 && digitalRead(btnPin[i]) == LOW) return true;
#ifdef TOUCHPIN #ifdef TOUCHPIN
if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true; if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true;
#endif #endif
@ -27,84 +27,86 @@ bool isButtonPressed()
} }
void handleSwitch() void handleSwitch(uint8_t b)
{ {
if (buttonPressedBefore != isButtonPressed()) { if (buttonPressedBefore[b] != isButtonPressed(b)) {
buttonPressedTime = millis(); buttonPressedTime[b] = millis();
buttonPressedBefore = !buttonPressedBefore; buttonPressedBefore[b] = !buttonPressedBefore[b];
} }
if (buttonLongPressed == buttonPressedBefore) return; if (buttonLongPressed[b] == buttonPressedBefore[b]) return;
if (millis() - buttonPressedTime > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce) if (millis() - buttonPressedTime[b] > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
if (buttonPressedBefore) { //LOW, falling edge, switch closed if (buttonPressedBefore[b]) { //LOW, falling edge, switch closed
if (macroButton) applyPreset(macroButton); if (macroButton[b]) applyPreset(macroButton[b]);
else { //turn on else { //turn on
if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);} if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
} }
} else { //HIGH, rising edge, switch opened } else { //HIGH, rising edge, switch opened
if (macroLongPress) applyPreset(macroLongPress); if (macroLongPress[b]) applyPreset(macroLongPress[b]);
else { //turn off else { //turn off
if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);} if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
} }
} }
buttonLongPressed = buttonPressedBefore; //save the last "long term" switch state buttonLongPressed[b] = buttonPressedBefore[b]; //save the last "long term" switch state
} }
} }
void handleButton() void handleButton()
{ {
if (btnPin<0 || buttonType < BTN_TYPE_PUSH) return; for (uint8_t b=0; b<WLED_MAX_BUTTONS; b++) {
if (btnPin[b]<0 || !(buttonType[b] > BTN_TYPE_NONE)) continue;
if (buttonType == BTN_TYPE_SWITCH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NO gpio0) if (buttonType[b] == BTN_TYPE_SWITCH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NOT gpio0)
handleSwitch(); return; handleSwitch(b); continue;
} }
//momentary button logic //momentary button logic
if (isButtonPressed()) //pressed if (isButtonPressed(b)) //pressed
{
if (!buttonPressedBefore) buttonPressedTime = millis();
buttonPressedBefore = true;
if (millis() - buttonPressedTime > 600) //long press
{ {
if (!buttonLongPressed) if (!buttonPressedBefore[b]) buttonPressedTime[b] = millis();
{ buttonPressedBefore[b] = true;
if (macroLongPress) {applyPreset(macroLongPress);}
else _setRandomColor(false,true);
buttonLongPressed = true; if (millis() - buttonPressedTime[b] > 600) //long press
{
if (!buttonLongPressed[b])
{
if (macroLongPress[b]) {applyPreset(macroLongPress[b]);}
else _setRandomColor(false,true);
buttonLongPressed[b] = true;
}
} }
} }
} else if (!isButtonPressed(b) && buttonPressedBefore[b]) //released
else if (!isButtonPressed() && buttonPressedBefore) //released
{
long dur = millis() - buttonPressedTime;
if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore = false; return;} //too short "press", debounce
bool doublePress = buttonWaitTime;
buttonWaitTime = 0;
if (dur > 6000) //long press
{ {
WLED::instance().initAP(true); long dur = millis() - buttonPressedTime[b];
} if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore[b] = false; continue;} //too short "press", debounce
else if (!buttonLongPressed) { //short press bool doublePress = buttonWaitTime[b];
if (macroDoublePress) buttonWaitTime[b] = 0;
{
if (doublePress) applyPreset(macroDoublePress);
else buttonWaitTime = millis();
} else shortPressAction();
}
buttonPressedBefore = false;
buttonLongPressed = false;
}
if (buttonWaitTime && millis() - buttonWaitTime > 450 && !buttonPressedBefore) if (dur > 6000 && b==0) //long press on button 0
{ {
buttonWaitTime = 0; WLED::instance().initAP(true);
shortPressAction(); }
else if (!buttonLongPressed[b]) { //short press
if (macroDoublePress[b])
{
if (doublePress) applyPreset(macroDoublePress[b]);
else buttonWaitTime[b] = millis();
} else shortPressAction(b);
}
buttonPressedBefore[b] = false;
buttonLongPressed[b] = false;
}
if (buttonWaitTime[b] && millis() - buttonWaitTime[b] > 450 && !buttonPressedBefore[b])
{
buttonWaitTime[b] = 0;
shortPressAction(b);
}
} }
} }

View File

@ -131,10 +131,41 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (lC > ledCount) ledCount = lC; // fix incorrect total length (honour analog setup) if (lC > ledCount) ledCount = lC; // fix incorrect total length (honour analog setup)
DEBUG_PRINTLN(F(" Done LEDs.")); DEBUG_PRINTLN(F(" Done LEDs."));
// read multiple button configuration
JsonArray hw_btn_ins = hw[F("btn")][F("ins")];
if (!hw_btn_ins.isNull()) {
uint8_t s = 0;
for (JsonObject btn : hw_btn_ins) {
CJSON(buttonType[s], btn["type"]);
int8_t pin = btn[F("pin")][0] | -1;
if (pin > -1) {
if (pinManager.allocatePin(pin,false)) {
btnPin[s] = pin;
pinMode(btnPin[s], INPUT_PULLUP);
} else {
btnPin[s] = -1;
}
}
JsonArray hw_btn_ins_0_macros = btn[F("macros")];
CJSON(macroButton[s], hw_btn_ins_0_macros[0]);
CJSON(macroLongPress[s],hw_btn_ins_0_macros[1]);
CJSON(macroDoublePress[s], hw_btn_ins_0_macros[2]);
if (++s >= WLED_MAX_BUTTONS) break; // max buttons reached
}
// clear remaining buttons
for (; s<WLED_MAX_BUTTONS; s++) {
btnPin[s] = -1;
buttonType[s] = BTN_TYPE_NONE;
macroButton[s] = 0;
macroLongPress[s] = 0;
macroDoublePress[s] = 0;
}
}
/*
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0]; JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
CJSON(buttonType, hw_btn_ins_0["type"]); CJSON(buttonType, hw_btn_ins_0["type"]);
int hw_btn_pin = hw_btn_ins_0[F("pin")][0] | -2; //-2 = not present in doc, keep current. -1 = disable int hw_btn_pin = hw_btn_ins_0[F("pin")][0] | -2; //-2 = not present in doc, keep current. -1 = disable
if (hw_btn_pin > -2) { if (hw_btn_pin > -1) {
if (pinManager.allocatePin(hw_btn_pin,false)) { if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin; btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP); pinMode(btnPin, INPUT_PULLUP);
@ -147,7 +178,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(macroButton, hw_btn_ins_0_macros[0]); CJSON(macroButton, hw_btn_ins_0_macros[0]);
CJSON(macroLongPress,hw_btn_ins_0_macros[1]); CJSON(macroLongPress,hw_btn_ins_0_macros[1]);
CJSON(macroDoublePress, hw_btn_ins_0_macros[2]); CJSON(macroDoublePress, hw_btn_ins_0_macros[2]);
*/
#ifndef WLED_DISABLE_INFRARED #ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4 int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
if (hw_ir_pin > -2) { if (hw_ir_pin > -2) {
@ -509,21 +540,28 @@ void serializeConfig() {
ins[F("rgbw")] = bus->isRgbw(); ins[F("rgbw")] = bus->isRgbw();
} }
// button(s)
JsonObject hw_btn = hw.createNestedObject("btn"); JsonObject hw_btn = hw.createNestedObject("btn");
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins"); JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
// button BTNPIN
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject(); JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
hw_btn_ins_0["type"] = buttonType; hw_btn_ins_0["type"] = buttonType[0];
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin"); JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
hw_btn_ins_0_pin.add(btnPin); hw_btn_ins_0_pin.add(btnPin[0]);
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros"); // additional buttons
hw_btn_ins_0_macros.add(macroButton); for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) {
hw_btn_ins_0_macros.add(macroLongPress); if (btnPin[i]<0) continue;
hw_btn_ins_0_macros.add(macroDoublePress); JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
hw_btn_ins_0["type"] = buttonType[i];
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
hw_btn_ins_0_pin.add(btnPin[i]);
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
hw_btn_ins_0_macros.add(macroButton[i]);
hw_btn_ins_0_macros.add(macroLongPress[i]);
hw_btn_ins_0_macros.add(macroDoublePress[i]);
}
JsonObject hw_ir = hw.createNestedObject("ir"); JsonObject hw_ir = hw.createNestedObject("ir");
hw_ir["pin"] = irPin; hw_ir["pin"] = irPin;

View File

@ -31,6 +31,14 @@
#endif #endif
#endif #endif
#ifndef WLED_MAX_BUTTONS
#ifdef ESP8266
#define WLED_MAX_BUTTONS 2
#else
#define WLED_MAX_BUTTONS 4
#endif
#endif
//Usermod IDs //Usermod IDs
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID

View File

@ -14,6 +14,7 @@
{ {
window.open("/settings","_self"); window.open("/settings","_self");
} }
function gId(n){return d.getElementById(n);}
function off(n){ function off(n){
d.getElementsByName(n)[0].value = -1; d.getElementsByName(n)[0].value = -1;
} }
@ -48,32 +49,32 @@
function S(){GetV();setABL();} function S(){GetV();setABL();}
function enABL() function enABL()
{ {
var en = d.getElementById('able').checked; var en = gId('able').checked;
d.Sf.LA.value = (en) ? laprev:0; d.Sf.LA.value = (en) ? laprev:0;
d.getElementById('abl').style.display = (en) ? 'inline':'none'; gId('abl').style.display = (en) ? 'inline':'none';
d.getElementById('psu2').style.display = (en) ? 'inline':'none'; gId('psu2').style.display = (en) ? 'inline':'none';
if (d.Sf.LA.value > 0) setABL(); if (d.Sf.LA.value > 0) setABL();
} }
function enLA() function enLA()
{ {
var val = d.Sf.LAsel.value; var val = d.Sf.LAsel.value;
d.Sf.LA.value = val; d.Sf.LA.value = val;
d.getElementById('LAdis').style.display = (val == 50) ? 'inline':'none'; gId('LAdis').style.display = (val == 50) ? 'inline':'none';
UI(); UI();
} }
function setABL() function setABL()
{ {
d.getElementById('able').checked = true; gId('able').checked = true;
d.Sf.LAsel.value = 50; d.Sf.LAsel.value = 50;
switch (parseInt(d.Sf.LA.value)) { switch (parseInt(d.Sf.LA.value)) {
case 0: d.getElementById('able').checked = false; enABL(); break; case 0: gId('able').checked = false; enABL(); break;
case 30: d.Sf.LAsel.value = 30; break; case 30: d.Sf.LAsel.value = 30; break;
case 35: d.Sf.LAsel.value = 35; break; case 35: d.Sf.LAsel.value = 35; break;
case 55: d.Sf.LAsel.value = 55; break; case 55: d.Sf.LAsel.value = 55; break;
case 255: d.Sf.LAsel.value = 255; break; case 255: d.Sf.LAsel.value = 255; break;
default: d.getElementById('LAdis').style.display = 'inline'; default: gId('LAdis').style.display = 'inline';
} }
d.getElementById('m1').innerHTML = maxM; gId('m1').innerHTML = maxM;
d.getElementsByName("Sf")[0].addEventListener("submit", trySubmit); d.getElementsByName("Sf")[0].addEventListener("submit", trySubmit);
UI(); UI();
} }
@ -100,7 +101,7 @@
{ {
var isRGBW = false, memu = 0; var isRGBW = false, memu = 0;
d.getElementById('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none'; gId('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none';
if (d.Sf.LA.value == 255) laprev = 12; if (d.Sf.LA.value == 255) laprev = 12;
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value; else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
@ -110,8 +111,8 @@
if (s[i].name.substring(0,2)=="LT") { if (s[i].name.substring(0,2)=="LT") {
n=s[i].name.substring(2); n=s[i].name.substring(2);
var type = parseInt(s[i].value,10); var type = parseInt(s[i].value,10);
d.getElementById("p0d"+n).innerHTML = (type > 49) ? "Data:" : (type >41) ? "Pins:" : "Pin:"; gId("p0d"+n).innerHTML = (type > 49) ? "Data:" : (type >41) ? "Pins:" : "Pin:";
d.getElementById("p1d"+n).innerHTML = (type > 49) ? "Clk:" : ""; gId("p1d"+n).innerHTML = (type > 49) ? "Clk:" : "";
var LK = d.getElementsByName("L1"+n)[0]; var LK = d.getElementsByName("L1"+n)[0];
memu += getMem(type, d.getElementsByName("LC"+n)[0].value, d.getElementsByName("L0"+n)[0].value); memu += getMem(type, d.getElementsByName("LC"+n)[0].value, d.getElementsByName("L0"+n)[0].value);
@ -129,17 +130,17 @@
LK.value=""; LK.value="";
} }
} }
d.getElementById("ls"+n).readOnly = !(type > 31 && type < 48); // not analog gId("ls"+n).readOnly = !(type > 31 && type < 48); // not analog
d.getElementById("LC").readOnly = !(type > 31 && type < 48); // not analog gId("LC").readOnly = !(type > 31 && type < 48); // not analog
if (change) { if (change) {
// d.getElementById("ew"+n).checked = (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h // gId("ew"+n).checked = (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h
d.getElementById("ls"+n).value = n+1; gId("ls"+n).value = n+1;
} }
// d.getElementById("ew"+n).onclick = (type > 31 && type < 48) ? (function(){return false}) : (function(){}); // prevent change for analog // gId("ew"+n).onclick = (type > 31 && type < 48) ? (function(){return false}) : (function(){}); // prevent change for analog
// isRGBW |= d.getElementById("ew"+n).checked; // isRGBW |= gId("ew"+n).checked;
isRGBW |= (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h isRGBW |= (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h
d.getElementById("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline"; gId("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline";
d.getElementById("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:"; gId("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:";
} }
} }
@ -156,7 +157,7 @@
if (nm=="LC" && LCs[i].name !== "LC") { if (nm=="LC" && LCs[i].name !== "LC") {
var n=LCs[i].name.substring(2); var n=LCs[i].name.substring(2);
var c=parseInt(LCs[i].value,10); var c=parseInt(LCs[i].value,10);
if(d.getElementById("ls"+n).readOnly) d.getElementById("ls"+n).value=sLC; if(gId("ls"+n).readOnly) gId("ls"+n).value=sLC;
if(c){sLC+=c;if(c>maxLC)maxLC=c;} if(c){sLC+=c;if(c>maxLC)maxLC=c;}
continue; continue;
} }
@ -178,18 +179,18 @@
} }
} }
if (d.getElementById("LC").readOnly) d.getElementsByName("LC")[0].value = sLC; if (gId("LC").readOnly) d.getElementsByName("LC")[0].value = sLC;
if (d.activeElement == d.getElementsByName("LC")[0]) { if (d.activeElement == d.getElementsByName("LC")[0]) {
var o = d.getElementsByClassName("iST"); var o = d.getElementsByClassName("iST");
var i = o.length; var i = o.length;
if (i == 1) d.getElementsByName("LC0")[0].value = d.getElementsByName("LC")[0].value; if (i == 1) d.getElementsByName("LC0")[0].value = d.getElementsByName("LC")[0].value;
} }
d.getElementById('m0').innerHTML = memu; gId('m0').innerHTML = memu;
bquot = memu / maxM * 100; bquot = memu / maxM * 100;
d.getElementById('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? (bquot > 90 ? "red":"orange"):"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`; gId('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? (bquot > 90 ? "red":"orange"):"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`;
d.getElementById('ledwarning').style.display = (sLC > maxPB || maxLC > 800 || bquot > 80) ? 'inline':'none'; gId('ledwarning').style.display = (sLC > maxPB || maxLC > 800 || bquot > 80) ? 'inline':'none';
d.getElementById('ledwarning').style.color = (sLC > maxPB || maxLC > maxPB || bquot > 100) ? 'red':'orange'; gId('ledwarning').style.color = (sLC > maxPB || maxLC > maxPB || bquot > 100) ? 'red':'orange';
d.getElementById('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>WARNING: Using over ${maxM}B!</b>)` : "") : "800 LEDs per pin"; gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>WARNING: Using over ${maxM}B!</b>)` : "") : "800 LEDs per pin";
var val = Math.ceil((100 + sLC * laprev)/500)/2; var val = Math.ceil((100 + sLC * laprev)/500)/2;
val = (val > 5) ? Math.ceil(val) : val; val = (val > 5) ? Math.ceil(val) : val;
@ -210,8 +211,8 @@
var s2 = "(for most effects, ~"; var s2 = "(for most effects, ~";
s2 += val2; s2 += val2;
s2 += "A is enough)<br>"; s2 += "A is enough)<br>";
d.getElementById('psu').innerHTML = s; gId('psu').innerHTML = s;
d.getElementById('psu2').innerHTML = isWS2815 ? "" : s2; gId('psu2').innerHTML = isWS2815 ? "" : s2;
} }
function lastEnd(i) { function lastEnd(i) {
if (i<1) return 0; if (i<1) return 0;
@ -221,14 +222,14 @@
} }
function addLEDs(n) function addLEDs(n)
{ {
if (n>1) {maxB=n; d.getElementById("+").style.display="inline"; return;} if (n>1) {maxB=n; gId("+").style.display="inline"; return;}
var o = d.getElementsByClassName("iST"); var o = d.getElementsByClassName("iST");
var i = o.length; var i = o.length;
if ((n==1 && i>=maxB) || (n==-1 && i==0)) return; if ((n==1 && i>=maxB) || (n==-1 && i==0)) return;
var f = d.getElementById("mLC"); var f = gId("mLC");
if (n==1) { if (n==1) {
// npm run build has trouble minimizing spaces inside string // npm run build has trouble minimizing spaces inside string
var cn = `<div class="iST"> var cn = `<div class="iST">
@ -277,15 +278,28 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
o[--i].remove();--i; o[--i].remove();--i;
} }
d.getElementById("+").style.display = (i<maxB-1) ? "inline":"none"; gId("+").style.display = (i<maxB-1) ? "inline":"none";
d.getElementById("-").style.display = (i>0) ? "inline":"none"; gId("-").style.display = (i>0) ? "inline":"none";
UI(); UI();
}
function addBtn(i,p,t) {
var c = gId("btns").innerHTML;
var bt = "BT" + i;
var be = "BE" + i;
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" value="${p}">`;
c += `<select name="${bt}">`
c += `<option name="${be}" value="0" ${t==0?"selected":""}>Disabled</option>`;
c += `<option name="${be}" value="2" ${t==2?"selected":""}>Pushbutton</option>`;
c += `<option name="${be}" value="4" ${t==4?"selected":""}>Switch</option>`;
c += `</select>`;
c += `<span style="cursor: pointer;" onclick="off('${bt}')">&nbsp;&#215;</span><br>`;
gId("btns").innerHTML = c;
} }
function GetV() function GetV()
{ {
//values injected by server while sending HTML //values injected by server while sending HTML
//maxM=5000;maxPB=1536;d.um_p=[1,6,7,8,9,10,11];addLEDs(3);d.Sf.LC.value=250;addLEDs(1);d.Sf.L00.value=2;d.Sf.L10.value=0;d.Sf.LC0.value=250;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=0;d.Sf.LS0.checked=0;d.Sf.MA.value=5400;d.Sf.LA.value=55;d.getElementsByClassName("pow")[0].innerHTML="350mA";d.Sf.CA.value=40;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=3;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=64;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.SL.checked=0;d.Sf.RL.value=12;d.Sf.RM.checked=0;d.Sf.BT.value=-1;d.Sf.IR.value=-1;d.Sf.AX.value=-1; //maxM=5000;maxPB=1536;d.um_p=[1,6,7,8,9,10,11];addLEDs(3);d.Sf.LC.value=250;addLEDs(1);d.Sf.L00.value=2;d.Sf.L10.value=0;d.Sf.LC0.value=250;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=0;d.Sf.LS0.checked=0;d.Sf.MA.value=5400;d.Sf.LA.value=55;d.getElementsByClassName("pow")[0].innerHTML="350mA";d.Sf.CA.value=40;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=3;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=64;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=12;d.Sf.RM.checked=0;addBtn(0,0,2);addBtn(1,3,4);addBtn(2,-1,0);d.Sf.IR.value=-1;
} }
</script> </script>
<style> <style>
@ -338,10 +352,20 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
&#9888; You might run into stability or lag issues.<br> &#9888; You might run into stability or lag issues.<br>
Use less than <span id="wreason">800 LEDs per pin</span> for the best experience!<br> Use less than <span id="wreason">800 LEDs per pin</span> for the best experience!<br>
</div><hr style="width:260px"> </div><hr style="width:260px">
Button pin: <input type="number" min="-1" max="40" name="BT" onchange="UI()"><span style="cursor: pointer;" onclick="off('BT')">&nbsp;&#215;</span><br> <div id="btns"></div>
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()"><span style="cursor: pointer;" onclick="off('IR')">&nbsp;&#215;</span><br> IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()"><select name="IT">
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()"><span style="cursor: pointer;" onclick="off('RL')">&nbsp;&#215;</span><br> <option value="0">Remote disabled</option>
Active high <input type="checkbox" name="RM"> <option value="1">24-key RGB</option>
<option value="2">24-key with CT</option>
<option value="3">40-key blue</option>
<option value="4">44-key RGB</option>
<option value="5">21-key RGB</option>
<option value="6">6-key black</option>
<option value="7">9-key red</option>
<option value="8">JSON remote</option>
</select><span style="cursor: pointer;" onclick="off('IR')">&nbsp;&#215;</span><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br>
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')">&nbsp;&#215;</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>
@ -374,7 +398,6 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
<option value="2">Linear (never wrap)</option> <option value="2">Linear (never wrap)</option>
<option value="3">None (not recommended)</option> <option value="3">None (not recommended)</option>
</select><br> </select><br>
<!--Skip first LED: <input type="checkbox" name="SL"><br-->
<span class="wc"> <span class="wc">
Auto-calculate white channel from RGB:<br> Auto-calculate white channel from RGB:<br>
<select name="AW"> <select name="AW">

View File

@ -17,6 +17,7 @@ function GetV(){var d=document;}
<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><hr>
</div> </div>
<h2>Sync setup</h2> <h2>Sync setup</h2>
<!--
<h3>Button setup</h3> <h3>Button setup</h3>
Button type: Button type:
<select name=BT> <select name=BT>
@ -37,6 +38,7 @@ Infrared remote:
<option value=8>JSON remote</option> <option value=8>JSON remote</option>
</select><br> </select><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a> <a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
-->
<h3>WLED Broadcast</h3> <h3>WLED Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br> UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br> 2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br>

View File

@ -75,9 +75,25 @@
gId("W"+i).value=a[i]; gId("W"+i).value=a[i];
} }
} }
function addRow(i,p,l,d) {
var t = gId("macros"); // table
var rCnt = t.rows.length; // get the number of rows.
var tr = t.insertRow(rCnt); // table row.
var td = document.createElement('td'); // TABLE DEFINITION.
td = tr.insertCell(0);
td.innerHTML = `Button ${i}:`;
td = tr.insertCell(1);
td.innerHTML = `<input name="MP${i}" type="number" min="0" max="250" value="${p}" required>`;
td = tr.insertCell(2);
td.innerHTML = `<input name="ML${i}" type="number" min="0" max="250" value="${l}" required>`;
td = tr.insertCell(3);
td.innerHTML = `<input name="MD${i}" type="number" min="0" max="250" value="${d}" required>`;
}
function GetV() function GetV()
{ {
//values injected by server while sending HTML //values injected by server while sending HTML
addRow(0,23,4,0);
} }
</script> </script>
<style> <style>
@ -109,12 +125,12 @@
<option value="10">JST(KST)</option> <option value="10">JST(KST)</option>
<option value="11">AEST/AEDT</option> <option value="11">AEST/AEDT</option>
<option value="12">NZST/NZDT</option> <option value="12">NZST/NZDT</option>
<option value="13">North Korea</option> <option value="13">North Korea</option>
<option value="14">IST (India)</option> <option value="14">IST (India)</option>
<option value="15">CA-Saskatchewan</option> <option value="15">CA-Saskatchewan</option>
<option value="16">ACST</option> <option value="16">ACST</option>
<option value="17">ACST/ACDT</option> <option value="17">ACST/ACDT</option>
<option value="18">HST (Hawaii)</option> <option value="18">HST (Hawaii)</option>
</select><br> </select><br>
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br> UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
Current local time is <span class="times">unknown</span>.<br> Current local time is <span class="times">unknown</span>.<br>
@ -145,15 +161,26 @@
Year: 20 <input name="CY" class="small" type="number" min="0" max="99" required> Month: <input name="CI" class="small" type="number" min="1" max="12" required> Day: <input name="CD" class="small" type="number" min="1" max="31" required><br> Year: 20 <input name="CY" class="small" type="number" min="0" max="99" required> Month: <input name="CI" class="small" type="number" min="1" max="12" required> Day: <input name="CD" class="small" type="number" min="1" max="31" required><br>
Hour: <input name="CH" class="small" type="number" min="0" max="23" required> Minute: <input name="CM" class="small" type="number" min="0" max="59" required> Second: <input name="CS" class="small" type="number" min="0" max="59" required><br> Hour: <input name="CH" class="small" type="number" min="0" max="23" required> Minute: <input name="CM" class="small" type="number" min="0" max="59" required> Second: <input name="CS" class="small" type="number" min="0" max="59" required><br>
<h3>Macro presets</h3> <h3>Macro presets</h3>
<b>Macros have moved!</b><br> <b>Macros have moved!</b><br>
<i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br> <i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br>
Just enter the preset id below!</i> Just enter the preset id below!</i>
<i>Use 0 for the default action instead of a preset</i><br> <i>Use 0 for the default action instead of a preset</i><br>
Alexa On/Off Preset: <input name="A0" type="number" min="0" max="250" required> <input name="A1" type="number" min="0" max="250" required><br> Alexa On/Off Preset: <input name="A0" type="number" min="0" max="250" required> <input name="A1" type="number" min="0" max="250" required><br>
Button short press Preset: <input name="MP" type="number" min="0" max="250" required><br>
Long Press: <input name="ML" type="number" min="0" max="250" required> Double press: <input name="MD" type="number" min="0" max="250" required><br>
Countdown-Over Preset: <input name="MC" type="number" min="0" max="250" required><br> Countdown-Over Preset: <input name="MC" type="number" min="0" max="250" required><br>
Timed-Light-Over Presets: <input name="MN" type="number" min="0" max="250" required><br> Timed-Light-Over Presets: <input name="MN" type="number" min="0" max="250" required><br>
<h3>Button actions</h3>
<table style="margin: 0 auto;" id="macros">
<thead>
<tr>
<td></td>
<td>short<br>on-&gt;off</td>
<td>long<br>off-&gt;on</td>
<td>double</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<h3>Time-controlled presets</h3> <h3>Time-controlled presets</h3>
<div style="display: inline-block"> <div style="display: inline-block">
<table id="TMT"> <table id="TMT">

View File

@ -20,8 +20,8 @@ void handleBlynk();
void updateBlynk(); void updateBlynk();
//button.cpp //button.cpp
void shortPressAction(); void shortPressAction(uint8_t b=0);
bool isButtonPressed(); bool isButtonPressed(uint8_t b=0);
void handleButton(); void handleButton();
void handleIO(); void handleIO();

File diff suppressed because one or more lines are too long

View File

@ -81,7 +81,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
#ifndef WLED_DISABLE_INFRARED #ifndef WLED_DISABLE_INFRARED
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin); if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
#endif #endif
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin); for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++)
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s]))
pinManager.deallocatePin(btnPin[s]);
strip.isRgbw = false; strip.isRgbw = false;
uint8_t colorOrder, type, skip; uint8_t colorOrder, type, skip;
@ -135,6 +137,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
} else { } else {
irPin = -1; irPin = -1;
} }
irEnabled = request->arg(F("IT")).toInt();
#endif #endif
int hw_rly_pin = request->arg(F("RL")).toInt(); int hw_rly_pin = request->arg(F("RL")).toInt();
@ -145,12 +148,20 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
} }
rlyMde = (bool)request->hasArg(F("RM")); rlyMde = (bool)request->hasArg(F("RM"));
int hw_btn_pin = request->arg(F("BT")).toInt(); for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
if (pinManager.allocatePin(hw_btn_pin,false)) { char bt[4] = "BT"; bt[2] = 48+i; bt[3] = 0; // button pin
btnPin = hw_btn_pin; char be[4] = "BE"; be[2] = 48+i; be[3] = 0; // button type
pinMode(btnPin, INPUT_PULLUP); //if (request->hasArg(bt)) {
} else { int hw_btn_pin = request->arg(bt).toInt();
btnPin = -1; if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin[i] = hw_btn_pin;
pinMode(btnPin[i], INPUT_PULLUP);
buttonType[i] = request->arg(be).toInt();
} else {
btnPin[i] = -1;
buttonType[i] = BTN_TYPE_NONE;
}
//}
} }
strip.ablMilliampsMax = request->arg(F("MA")).toInt(); strip.ablMilliampsMax = request->arg(F("MA")).toInt();
@ -195,8 +206,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//SYNC //SYNC
if (subPage == 4) if (subPage == 4)
{ {
buttonType = request->arg(F("BT")).toInt(); //buttonType = request->arg(F("BT")).toInt();
irEnabled = request->arg(F("IR")).toInt(); //irEnabled = request->arg(F("IR")).toInt();
int t = request->arg(F("UP")).toInt(); int t = request->arg(F("UP")).toInt();
if (t > 0) udpPort = t; if (t > 0) udpPort = t;
t = request->arg(F("U2")).toInt(); t = request->arg(F("U2")).toInt();
@ -324,11 +335,16 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
macroAlexaOn = request->arg(F("A0")).toInt(); macroAlexaOn = request->arg(F("A0")).toInt();
macroAlexaOff = request->arg(F("A1")).toInt(); macroAlexaOff = request->arg(F("A1")).toInt();
macroButton = request->arg(F("MP")).toInt();
macroLongPress = request->arg(F("ML")).toInt();
macroCountdown = request->arg(F("MC")).toInt(); macroCountdown = request->arg(F("MC")).toInt();
macroNl = request->arg(F("MN")).toInt(); macroNl = request->arg(F("MN")).toInt();
macroDoublePress = request->arg(F("MD")).toInt(); for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
char mp[4] = "MP"; mp[2] = 48+i; mp[3] = 0; // short
char ml[4] = "ML"; ml[2] = 48+i; ml[3] = 0; // long
char md[4] = "MD"; md[2] = 48+i; md[3] = 0; // double
macroButton[i] = request->arg(mp).toInt();
macroLongPress[i] = request->arg(ml).toInt();
macroDoublePress[i] = request->arg(md).toInt();
}
char k[3]; k[2] = 0; char k[3]; k[2] = 0;
for (int i = 0; i<10; i++) for (int i = 0; i<10; i++)

View File

@ -470,8 +470,8 @@ void WLED::beginStrip()
if (rlyPin>=0) digitalWrite(rlyPin, (bri ? rlyMde : !rlyMde)); if (rlyPin>=0) digitalWrite(rlyPin, (bri ? rlyMde : !rlyMde));
// disable button if it is "pressed" unintentionally // disable button if it is "pressed" unintentionally
if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed()) //if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed())
buttonType = BTN_TYPE_NONE; // buttonType = BTN_TYPE_NONE;
} }
void WLED::initAP(bool resetAP) void WLED::initAP(bool resetAP)

View File

@ -3,12 +3,12 @@
/* /*
Main sketch, global variable declarations Main sketch, global variable declarations
@title WLED project sketch @title WLED project sketch
@version 0.12.1-a1 @version 0.12.2-bl2
@author Christian Schwinne @author Christian Schwinne
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2105181 #define VERSION 2105191
//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
@ -208,9 +208,9 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
// Hardware CONFIG (only changeble HERE, not at runtime) // Hardware CONFIG (only changeble HERE, not at runtime)
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h! // LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
#ifndef BTNPIN #ifndef BTNPIN
WLED_GLOBAL int8_t btnPin _INIT(0); WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({0});
#else #else
WLED_GLOBAL int8_t btnPin _INIT(BTNPIN); WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({BTNPIN});
#endif #endif
#ifndef RLYPIN #ifndef RLYPIN
WLED_GLOBAL int8_t rlyPin _INIT(12); WLED_GLOBAL int8_t rlyPin _INIT(12);
@ -279,7 +279,7 @@ WLED_GLOBAL NodesMap Nodes;
WLED_GLOBAL bool nodeListEnabled _INIT(true); WLED_GLOBAL bool nodeListEnabled _INIT(true);
WLED_GLOBAL bool nodeBroadcastEnabled _INIT(true); WLED_GLOBAL bool nodeBroadcastEnabled _INIT(true);
WLED_GLOBAL byte buttonType _INIT(BTN_TYPE_PUSH); WLED_GLOBAL byte buttonType[WLED_MAX_BUTTONS] _INIT({BTN_TYPE_PUSH});
WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver
WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port
@ -370,7 +370,9 @@ WLED_GLOBAL byte countdownMin _INIT(0) , countdownSec _INIT(0);
WLED_GLOBAL byte macroNl _INIT(0); // after nightlight delay over WLED_GLOBAL byte macroNl _INIT(0); // after nightlight delay over
WLED_GLOBAL byte macroCountdown _INIT(0); WLED_GLOBAL byte macroCountdown _INIT(0);
WLED_GLOBAL byte macroAlexaOn _INIT(0), macroAlexaOff _INIT(0); WLED_GLOBAL byte macroAlexaOn _INIT(0), macroAlexaOff _INIT(0);
WLED_GLOBAL byte macroButton _INIT(0), macroLongPress _INIT(0), macroDoublePress _INIT(0); WLED_GLOBAL byte macroButton[WLED_MAX_BUTTONS] _INIT({0});
WLED_GLOBAL byte macroLongPress[WLED_MAX_BUTTONS] _INIT({0});
WLED_GLOBAL byte macroDoublePress[WLED_MAX_BUTTONS] _INIT({0});
// Security CONFIG // Security CONFIG
WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
@ -431,10 +433,10 @@ WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. U
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
// button // button
WLED_GLOBAL bool buttonPressedBefore _INIT(false); WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
WLED_GLOBAL bool buttonLongPressed _INIT(false); WLED_GLOBAL bool buttonLongPressed[WLED_MAX_BUTTONS] _INIT({false});
WLED_GLOBAL unsigned long buttonPressedTime _INIT(0); WLED_GLOBAL unsigned long buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
WLED_GLOBAL unsigned long buttonWaitTime _INIT(0); WLED_GLOBAL unsigned long buttonWaitTime[WLED_MAX_BUTTONS] _INIT({0});
// notifications // notifications
WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect); WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect);

View File

@ -93,7 +93,7 @@ void loadSettingsFromEEPROM()
notifyButton = EEPROM.read(230); notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231); notifyTwice = EEPROM.read(231);
buttonType = EEPROM.read(232) ? BTN_TYPE_PUSH : BTN_TYPE_NONE; buttonType[0] = EEPROM.read(232) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
staticIP[0] = EEPROM.read(234); staticIP[0] = EEPROM.read(234);
staticIP[1] = EEPROM.read(235); staticIP[1] = EEPROM.read(235);
@ -198,12 +198,12 @@ void loadSettingsFromEEPROM()
//macroBoot = EEPROM.read(2175); //macroBoot = EEPROM.read(2175);
macroAlexaOn = EEPROM.read(2176); macroAlexaOn = EEPROM.read(2176);
macroAlexaOff = EEPROM.read(2177); macroAlexaOff = EEPROM.read(2177);
macroButton = EEPROM.read(2178); macroButton[0] = EEPROM.read(2178);
macroLongPress = EEPROM.read(2179); macroLongPress[0] = EEPROM.read(2179);
macroCountdown = EEPROM.read(2180); macroCountdown = EEPROM.read(2180);
macroNl = EEPROM.read(2181); macroNl = EEPROM.read(2181);
macroDoublePress = EEPROM.read(2182); macroDoublePress[0] = EEPROM.read(2182);
if (macroDoublePress > 16) macroDoublePress = 0; if (macroDoublePress[0] > 16) macroDoublePress[0] = 0;
} }
if (lastEEPROMversion > 6) if (lastEEPROMversion > 6)

View File

@ -392,8 +392,15 @@ void getSettingsJS(byte subPage, char* dest)
sappend('i',SET_F("PB"),strip.paletteBlend); sappend('i',SET_F("PB"),strip.paletteBlend);
sappend('v',SET_F("RL"),rlyPin); sappend('v',SET_F("RL"),rlyPin);
sappend('c',SET_F("RM"),rlyMde); sappend('c',SET_F("RM"),rlyMde);
sappend('v',SET_F("BT"),btnPin); for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
oappend(SET_F("addBtn("));
oappend(itoa(i,nS,10)); oappend(",");
oappend(itoa(btnPin[i],nS,10)); oappend(",");
oappend(itoa(buttonType[i],nS,10));
oappend(SET_F(");"));
}
sappend('v',SET_F("IR"),irPin); sappend('v',SET_F("IR"),irPin);
sappend('v',SET_F("IT"),irEnabled);
} }
if (subPage == 3) if (subPage == 3)
@ -404,8 +411,8 @@ void getSettingsJS(byte subPage, char* dest)
if (subPage == 4) if (subPage == 4)
{ {
sappend('v',SET_F("BT"),buttonType); //sappend('v',SET_F("BT"),buttonType);
sappend('v',SET_F("IR"),irEnabled); //sappend('v',SET_F("IR"),irEnabled);
sappend('v',SET_F("UP"),udpPort); sappend('v',SET_F("UP"),udpPort);
sappend('v',SET_F("U2"),udpPort2); sappend('v',SET_F("U2"),udpPort2);
sappend('c',SET_F("RB"),receiveNotificationBrightness); sappend('c',SET_F("RB"),receiveNotificationBrightness);
@ -521,11 +528,19 @@ void getSettingsJS(byte subPage, char* dest)
sappend('v',SET_F("A0"),macroAlexaOn); sappend('v',SET_F("A0"),macroAlexaOn);
sappend('v',SET_F("A1"),macroAlexaOff); sappend('v',SET_F("A1"),macroAlexaOff);
sappend('v',SET_F("MP"),macroButton);
sappend('v',SET_F("ML"),macroLongPress);
sappend('v',SET_F("MC"),macroCountdown); sappend('v',SET_F("MC"),macroCountdown);
sappend('v',SET_F("MN"),macroNl); sappend('v',SET_F("MN"),macroNl);
sappend('v',SET_F("MD"),macroDoublePress); //sappend('v',SET_F("MP"),macroButton);
//sappend('v',SET_F("ML"),macroLongPress);
//sappend('v',SET_F("MD"),macroDoublePress);
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
oappend(SET_F("addRow("));
oappend(itoa(i,tm,10)); oappend(",");
oappend(itoa(macroButton[i],tm,10)); oappend(",");
oappend(itoa(macroLongPress[i],tm,10)); oappend(",");
oappend(itoa(macroDoublePress[i],tm,10));
oappend(SET_F(");"));
}
char k[4]; char k[4];
k[2] = 0; //Time macros k[2] = 0; //Time macros