Merge branch 'master' into dev

This commit is contained in:
Blaz Kristan 2022-01-01 16:36:06 +01:00
commit 1e947a34a8
12 changed files with 732 additions and 705 deletions

View File

@ -65,7 +65,8 @@ private:
{ 1, 0, 1, 1, 1, 1, 1 }, // 6
{ 1, 1, 1, 0, 0, 0, 0 }, // 7
{ 1, 1, 1, 1, 1, 1, 1 }, // 8
{ 1, 1, 1, 1, 0, 1, 1 } // 9
{ 1, 1, 1, 1, 0, 1, 1 }, // 9
{ 0, 0, 0, 0, 0, 0, 0 } // blank
};
//String to reduce flash memory usage
@ -100,39 +101,39 @@ private:
switch (umSSDRDisplayMask[index]) {
case 'h':
timeVar = hourFormat12(localTime);
_showElements(&umSSDRHours, timeVar, 0);
_showElements(&umSSDRHours, timeVar, 0, 1);
break;
case 'H':
timeVar = hour(localTime);
_showElements(&umSSDRHours, timeVar, 0);
_showElements(&umSSDRHours, timeVar, 0, 1);
break;
case 'k':
timeVar = hour(localTime) + 1;
_showElements(&umSSDRHours, timeVar, 0);
_showElements(&umSSDRHours, timeVar, 0, 0);
break;
case 'm':
timeVar = minute(localTime);
_showElements(&umSSDRMinutes, timeVar, 0);
_showElements(&umSSDRMinutes, timeVar, 0, 0);
break;
case 's':
timeVar = second(localTime);
_showElements(&umSSDRSeconds, timeVar, 0);
_showElements(&umSSDRSeconds, timeVar, 0, 0);
break;
case 'd':
timeVar = day(localTime);
_showElements(&umSSDRDays, timeVar, 0);
_showElements(&umSSDRDays, timeVar, 0, 0);
break;
case 'M':
timeVar = month(localTime);
_showElements(&umSSDRMonths, timeVar, 0);
_showElements(&umSSDRMonths, timeVar, 0, 0);
break;
case 'y':
timeVar = second(localTime);
_showElements(&umSSDRYears, timeVar, 0);
_showElements(&umSSDRYears, timeVar, 0, 0);
break;
case 'Y':
timeVar = year(localTime);
_showElements(&umSSDRYears, timeVar, 0);
_showElements(&umSSDRYears, timeVar, 0, 0);
break;
case ':':
if (!colonsDone) { // only call _setColons once as all colons are printed when the first colon is found
@ -148,14 +149,16 @@ private:
void _setColons() {
if ( umSSDRColonblink ) {
if ( second(localTime) % 2 == 0 ) {
_showElements(&umSSDRColons, 0, 1);
_showElements(&umSSDRColons, 0, 1, 0);
}
} else {
_showElements(&umSSDRColons, 0, 1);
_showElements(&umSSDRColons, 0, 1, 0);
}
}
void _showElements(String *map, int timevar, bool isColon) {
void _showElements(String *map, int timevar, bool isColon, bool removeZero
) {
if (!(*map).equals("") && !(*map) == NULL) {
int length = String(timevar).length();
bool addZero = false;
@ -165,8 +168,16 @@ private:
}
int timeArr[length];
if(addZero) {
timeArr[1] = 0;
timeArr[0] = timevar;
if(removeZero)
{
timeArr[1] = 10;
timeArr[0] = timevar;
}
else
{
timeArr[1] = 0;
timeArr[0] = timevar;
}
} else {
int count = 0;
while (timevar) {

View File

@ -355,8 +355,7 @@ uint8_t WS2812FX::getTargetFps() {
}
void WS2812FX::setTargetFps(uint8_t fps) {
if (fps > 0 && fps <= 120) _targetFps = fps;
//_targetFps = min(max((int)fps,1),120);
if (fps > 0 && fps <= 120) _targetFps = fps;
_frametime = 1000 / _targetFps;
}

View File

@ -86,10 +86,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
Bus::setAutoWhiteMode(hw_led[F("rgbwm")] | Bus::getAutoWhiteMode());
CJSON(correctWB, hw_led["cct"]);
CJSON(cctFromRgb, hw_led[F("cr")]);
CJSON(strip.cctBlending, hw_led[F("cb")]);
Bus::setCCTBlend(strip.cctBlending);
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
//strip.setTargetFps(hw_led["fps"].isNull() ? WLED_FPS : hw_led["fps"].as<byte>());
CJSON(strip.cctBlending, hw_led[F("cb")]);
Bus::setCCTBlend(strip.cctBlending);
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
JsonArray ins = hw_led["ins"];
@ -371,7 +370,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(timerMinutes[it], timer["min"]);
CJSON(timerMacro[it], timer["macro"]);
byte dowPrev = timerWeekday[it];
byte dowPrev = timerWeekday[it];
//note: act is currently only 0 or 1.
//the reason we are not using bool is that the on-disk type in 0.11.0 was already int
int actPrev = timerWeekday[it] & 0x01;
@ -382,8 +381,15 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
if (act) timerWeekday[it]++;
}
if (it<8) {
CJSON(timerMonth[it], timer[F("mon")]);
CJSON(timerDay[it], timer[F("day")]);
JsonObject start = timer["start"];
byte startm = start["mon"];
if (startm) timerMonth[it] = (startm << 4);
CJSON(timerDay[it], start["day"]);
JsonObject end = timer["end"];
CJSON(timerDayEnd[it], end["day"]);
byte endm = end["mon"];
if (startm) timerMonth[it] += endm & 0x0F;
if (!(timerMonth[it] & 0x0F)) timerMonth[it] += 12; //default end month to 12
}
it++;
}
@ -745,8 +751,12 @@ void serializeConfig() {
timers_ins0["macro"] = timerMacro[i];
timers_ins0[F("dow")] = timerWeekday[i] >> 1;
if (i<8) {
timers_ins0[F("mon")] = timerMonth[i];
timers_ins0[F("day")] = timerDay[i];
JsonObject start = timers_ins0.createNestedObject("start");
start["mon"] = (timerMonth[i] >> 4) & 0xF;
start["day"] = timerDay[i];
JsonObject end = timers_ins0.createNestedObject("end");
end["mon"] = timerMonth[i] & 0xF;
end["day"] = timerDayEnd[i];
}
}

View File

@ -353,7 +353,7 @@ ${i+1}:
c += `<option value="7" ${t==7?"selected":""}>Analog</option>`;
c += `<option value="8" ${t==8?"selected":""}>Analog inverted</option>`;
c += `</select>`;
c += `<span style="cursor: pointer;" onclick="off('${bt}')">&nbsp;&#215;</span><br>`;
c += `<span style="cursor: pointer;" onclick="off('${bt}')">&nbsp;&#x2715;</span><br>`;
gId("btns").innerHTML = c;
}
function tglSi(cs) {
@ -515,10 +515,10 @@ ${i+1}:
<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>
</select><span style="cursor: pointer;" onclick="off('IR')">&nbsp;&#x2715;</span><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>
<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')">&nbsp;&#215;</span><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')">&nbsp;&#x2715;</span><br>
<hr style="width:260px">
<h3>Defaults</h3>
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>

View File

@ -7,6 +7,7 @@
<title>Time Settings</title>
<script>
var d=document;
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function H()
{
window.open("https://kno.wled.ge/features/settings/#time-settings");
@ -23,11 +24,14 @@
{
return d.getElementById(s);
}
function gN(s) {
return d.getElementsByName(s)[0];
}
function expand(o,i)
{
o.classList.toggle("exp");
var t = gId("WD"+i);
t.style.display = t.style.display!=="none" ? "none" : "";
o.innerHTML = t.style.display==="none" ? "&#128467;" : "&#x2715;";
}
function Cs()
{
@ -50,73 +54,52 @@
}
function BTa()
{
var ih="<tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr>";
var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>";
for (i=0;i<8;i++) {
ih+=`<tr><td><input name="W${i}" id="W${i}" type="hidden"><input id="W${i}0" type="checkbox"></td>
<td><input name="H${i}" class="xs" type="number" min="0" max="24"></td>
<td><input name="N${i}" class="xs" type="number" min="0" max="59"></td>
<td><input name="T${i}" class="s" type="number" min="0" max="250"></td>
<td><button type="button" class="sml" onclick="expand(this,${i})">&gt;</button></td></tr>`;
ih+=`<tr><td colspan=5><div id="WD${i}" style="display:none;">`;
ih+=`<input name="X${i}" id="TMX${i}" type="checkbox" onchange="tglDOW(${i},this.checked)"><label for="TMX${i}">Use DOW</label>`;
ih+=`<table id="TT${i}" style="width:100%;"><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`
<td><div id="CB${i}" onclick="expand(this,${i})" class="cal">&#128467;</div></td></tr>`;
ih+=`<tr><td colspan=5><div id="WD${i}" style="display:none;"><hr>Run on weekdays`;
ih+=`<table><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`
for (j=1;j<8;j++) ih+=`<td><input id="W${i}${j}" type="checkbox"></td>`;
ih+=`</tr></table><div id="TD${i}">Date:
<select id="TMM${i}" name="M${i}" onchange="chkMon(this,${i})">
<option value="0">Every month</option>
<option value="13">Odd month</option>
<option value="14">Even month</option>
<option value="1">Jan</option>
<option value="2">Feb</option>
<option value="3">Mar</option>
<option value="4">Apr</option>
<option value="5">May</option>
<option value="6">Jun</option>
<option value="7">Jul</option>
<option value="8">Aug</option>
<option value="9">Sep</option>
<option value="10">Oct</option>
<option value="11">Nov</option>
<option value="12">Dec</option>
</select><select id="TMD${i}" name="D${i}">`;
for (j=1;j<32;j++) ih+=`<option value="${j}">${j}</option>`;
ih+="</select></div><hr></div></td></tr>";
ih+=`</tr></table>from <select name="M${i}">`;
for (j=0;j<12;j++) ih+=`<option value="${j+1}">${ms[j]}</option>`;
ih+=`</select><input name="D${i}" class="xs" type="number" min="1" max="31"></input> to <select name="P${i}">`;
for (j=0;j<12;j++) ih+=`<option value="${j+1}">${ms[j]}</option>`;
ih+=`</select><input name="E${i}" class="xs" type="number" min="1" max="31"></input>
<hr></div></td></tr>`;
}
ih+=`<tr><td><input name="W8" id="W8" type="hidden"><input id="W80" type="checkbox"></td>
<td>Sunrise<input name="H8" value="255" type="hidden"></td>
<td><input name="N8" class="xs" type="number" min="-59" max="59"></td>
<td><input name="T8" class="s" type="number" min="0" max="250"></td>
<td><button type="button" class="sml" onclick="expand(this,8)">&gt;</button></td></tr><tr><td colspan=5>`;
ih+=`<div id="WD8"style="display:none;"><table style="width:100%;"><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`;
<td><div onclick="expand(this,8)" class="cal">&#128467;</div></td></tr><tr><td colspan=5>`;
ih+=`<div id="WD8" style="display:none;"><hr><table><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`;
for (j=1;j<8;j++) ih+=`<td><input id="W8${j}" type="checkbox"></td>`;
ih+="</tr></table><hr></div></td></tr>";
ih+=`<tr><td><input name="W9" id="W9" type="hidden"><input id="W90" type="checkbox"></td>
<td>Sunrise<input name="H9" value="255" type="hidden"></td>
<td>Sunset<input name="H9" value="255" type="hidden"></td>
<td><input name="N9" class="xs" type="number" min="-59" max="59"></td>
<td><input name="T9" class="s" type="number" min="0" max="250"></td>
<td><button type="button" class="sml" onclick="expand(this,9)">&gt;</button></td></tr><tr><td colspan=5>`;
ih+=`<div id="WD9" style="display:none;"><table style="width:100%;"><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`;
<td><div onclick="expand(this,9)" class="cal">&#128467;</div></td></tr><tr><td colspan=5>`;
ih+=`<div id="WD9" style="display:none;"><hr><table><tr><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr><tr>`;
for (j=1;j<8;j++) ih+=`<td><input id="W9${j}" type="checkbox"></td>`;
ih+="</tr></table><hr></div></td></tr>";
gId("TMT").innerHTML=ih;
}
function tglDOW(i,b)
{
gId("TT"+i).style.display = b ? "table" : "none";
gId("TD"+i).style.display = !b ? "block" : "none";
}
function chkMon(o,i)
{
const m31 = [1,3,5,7,8,10,12,0,13,14];
if (!m31.includes(parseInt(o.value)) && parseInt(gId("TMD"+i).value)>30) gId("TMD"+i).value="30";
if (parseInt(o.value)===2 && parseInt(gId("TMD"+i).value)>28) gId("TMD"+i).value="28";
}
function FC()
{
for(j=0;j<8;j++)
for(i=0;i<10;i++)
{
for(i=0;i<10;i++) gId("W"+i+j).checked=gId("W"+i).value>>j&1;
tglDOW(j,gId('TMX'+j).checked);
let wd = gId("W"+i).value;
for(j=0;j<8;j++) {
gId("W"+i+j).checked=wd>>j&1;
}
if ((wd&127) != 127 || (i<8 && (gN("M"+i).value != 1 || gN("D"+i).value != 1 || gN("P"+i).value != 12 || gN("E"+i).value != 31))) {
expand(gId("CB"+i),i); //expand macros with custom DOW or date range set
}
}
}
function Wd()
@ -154,7 +137,6 @@
//values injected by server while sending HTML
}
</script>
<!--script src="http://192.168.70.61/settings/settings.js?p=5"></script-->
<style>@import url("style.css");</style>
</head>
<body onload="S()">
@ -218,12 +200,12 @@
</div>
Countdown Mode: <input type="checkbox" name="CE"><br>
Countdown Goal:<br>
Date: <nowrap>20<input name="CY" class="xs" type="number" min="0" max="99" required>-<input name="CI" class="xs" type="number" min="1" max="12" required>-<input name="CD" class="xs" type="number" min="1" max="31" required></nowrap><br>
Time: <nowrap><input name="CH" class="xs" type="number" min="0" max="23" required>:<input name="CM" class="xs" type="number" min="0" max="59" required>:<input name="CS" class="xs" type="number" min="0" max="59" required></nowrap><br>
Date:&nbsp;<nowrap>20<input name="CY" class="xs" type="number" min="0" max="99" required>-<input name="CI" class="xs" type="number" min="1" max="12" required>-<input name="CD" class="xs" type="number" min="1" max="31" required></nowrap><br>
Time:&nbsp;<nowrap><input name="CH" class="xs" type="number" min="0" max="23" required>:<input name="CM" class="xs" type="number" min="0" max="59" required>:<input name="CS" class="xs" type="number" min="0" max="59" required></nowrap><br>
<h3>Macro presets</h3>
<b>Macros have moved!</b><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>
<b>Macros have moved!</b><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>
<i>Use 0 for the default action instead of a preset</i><br>
Alexa On/Off Preset: <input name="A0" class="m" type="number" min="0" max="250" required> <input name="A1" class="m" type="number" min="0" max="250" required><br>
Countdown-Over Preset: <input name="MC" class="m" type="number" min="0" max="250" required><br>

View File

@ -92,6 +92,9 @@ input[type="checkbox"] {
transform: scale(1.5);
margin-right: 10px;
}
td input[type="checkbox"] {
margin-right: revert;
}
select {
margin: 2px;
background: #333;
@ -108,8 +111,12 @@ td {
.d5 {
width: 4rem !important;
}
.exp {
transform: rotate(90deg);
.cal {
font-size:1.5rem;
cursor:pointer
}
#TMT table {
width: 100%;
}
#toast {
opacity: 0;

File diff suppressed because it is too large Load Diff

View File

@ -318,6 +318,32 @@ byte weekdayMondayFirst()
return wd;
}
bool isTodayInDateRange(byte monthStart, byte dayStart, byte monthEnd, byte dayEnd)
{
if (monthStart == 0 || dayStart == 0) return true;
if (monthEnd == 0) monthEnd = monthStart;
if (dayEnd == 0) dayEnd = 31;
byte d = day(localTime);
byte m = month(localTime);
if (monthStart < monthEnd) {
if (m > monthStart && m < monthEnd) return true;
if (m == monthStart) return (d >= dayStart);
if (m == monthEnd) return (d <= dayEnd);
return false;
}
if (monthEnd < monthStart) { //range spans change of year
if (m > monthStart || m < monthEnd) return true;
if (m == monthStart) return (d >= dayStart);
if (m == monthEnd) return (d <= dayEnd);
return false;
}
//start month and end month are the same
if (dayEnd < dayStart) return (m != monthStart || (d <= dayEnd || d >= dayStart)); //all year, except the designated days in this month
return (m == monthStart && d >= dayStart && d <= dayEnd); //just the designated days this month
}
void checkTimers()
{
if (lastTimerMinute != minute(localTime)) //only check once a new minute begins
@ -334,12 +360,9 @@ void checkTimers()
&& (timerWeekday[i] & 0x01) //timer is enabled
&& (timerHours[i] == hour(localTime) || timerHours[i] == 24) //if hour is set to 24, activate every hour
&& timerMinutes[i] == minute(localTime)
&& ( (timerDay[i] == 0 && ((timerWeekday[i] >> weekdayMondayFirst()) & 0x01)) //timer should activate at current day of week
|| (timerDay[i] > 0 && timerDay[i]==day(localTime) &&
(timerMonth[i] == 0 || timerMonth[i]==month(localTime) || (timerMonth[i]==13 && month(localTime)%2) || (timerMonth[i]==14 && !(month(localTime)%2)))
)
)
)
&& ((timerWeekday[i] >> weekdayMondayFirst()) & 0x01) //timer should activate at current day of week
&& isTodayInDateRange(((timerMonth[i] >> 4) & 0x0F), timerDay[i], timerMonth[i] & 0x0F, timerDayEnd[i])
)
{
unloadPlaylist();
applyPreset(timerMacro[i]);

View File

@ -107,7 +107,7 @@ int16_t loadPlaylist(JsonObject playlistObj, byte presetId) {
playlistRepeat = rep;
if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start
playlistEndPreset = playlistObj[F("end")] | 0;
playlistEndPreset = playlistObj["end"] | 0;
shuffle = shuffle || playlistObj["r"];
if (shuffle) playlistOptions += PL_OPTION_SHUFFLE;

View File

@ -339,7 +339,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
char k[3]; k[2] = 0;
for (int i = 0; i<10; i++) {
k[1] = i+48;//ascii 0,1,2,3
k[1] = i+48;//ascii 0,1,2,3,...
k[0] = 'H'; //timer hours
timerHours[i] = request->arg(k).toInt();
k[0] = 'N'; //minutes
@ -349,16 +349,15 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
k[0] = 'W'; //weekdays
timerWeekday[i] = request->arg(k).toInt();
if (i<8) {
k[0] = 'X'; //DOW
if (!request->hasArg(k)) {
k[0] = 'M'; //month
timerMonth[i] = request->arg(k).toInt();
k[0] = 'D'; //day
timerDay[i] = request->arg(k).toInt();
} else {
timerMonth[i] = 0;
timerDay[i] = 0;
}
k[0] = 'M'; //start month
timerMonth[i] = request->arg(k).toInt() & 0x0F;
timerMonth[i] <<= 4;
k[0] = 'P'; //end month
timerMonth[i] += (request->arg(k).toInt() & 0x0F);
k[0] = 'D'; //start day
timerDay[i] = request->arg(k).toInt();
k[0] = 'E'; //end day
timerDayEnd[i] = request->arg(k).toInt();
}
}
}

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2201011
#define VERSION 2201012
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -503,15 +503,17 @@ WLED_GLOBAL byte dP[] _INIT_N(({ 255, 255, 255, 255, 255, 255 }));
WLED_GLOBAL unsigned long countdownTime _INIT(1514764800L);
WLED_GLOBAL bool countdownOverTriggered _INIT(true);
// timer
//timer
WLED_GLOBAL byte lastTimerMinute _INIT(0);
WLED_GLOBAL byte timerHours[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL int8_t timerMinutes[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL byte timerMacro[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 })); // weekdays to activate on
// bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
WLED_GLOBAL byte timerMonth[] _INIT_N(({0,0,0,0,0,0,0,0}));
WLED_GLOBAL byte timerDay[] _INIT_N(({0,0,0,0,0,0,0,0}));
//weekdays to activate on, bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }));
//upper 4 bits start, lower 4 bits end month (default 28: start month 1 and end month 12)
WLED_GLOBAL byte timerMonth[] _INIT_N(({28,28,28,28,28,28,28,28}));
WLED_GLOBAL byte timerDay[] _INIT_N(({1,1,1,1,1,1,1,1}));
WLED_GLOBAL byte timerDayEnd[] _INIT_N(({31,31,31,31,31,31,31,31}));
// blynk
WLED_GLOBAL bool blynkEnabled _INIT(false);

View File

@ -458,7 +458,7 @@ void getSettingsJS(byte subPage, char* dest)
memset(fpass,'*',l);
sappends('s',SET_F("MQPASS"),fpass);
sappends('s',SET_F("MQCID"),mqttClientID);
sappends('s',SET_F("MD"),mqttDeviceTopic);
sappends('s',"MD",mqttDeviceTopic);
sappends('s',SET_F("MG"),mqttGroupTopic);
sappend('c',SET_F("BM"),buttonPublishMqtt);
#endif
@ -550,10 +550,10 @@ void getSettingsJS(byte subPage, char* dest)
k[0] = 'T'; sappend('v',k,timerMacro[i]);
k[0] = 'W'; sappend('v',k,timerWeekday[i]);
if (i<8) {
k[0] = 'X'; sappend('c',k,timerDay[i]==0);
k[0] = 'M'; sappend('v',k,timerMonth[i]);
k[0] = 'D'; sappend('v',k,timerDay[i]?timerDay[i]:1);
k[0] = 'M'; sappend('v',k,(timerMonth[i] >> 4) & 0x0F);
k[0] = 'P'; sappend('v',k,timerMonth[i] & 0x0F);
k[0] = 'D'; sappend('v',k,timerDay[i]);
k[0] = 'E'; sappend('v',k,timerDayEnd[i]);
}
}
}