Skip to content

Commit 1103c91

Browse files
benjamwDedeHai
authored andcommitted
Analog button fix (#5659)
* add analog button options * fix issues with duplicate options for digital vs analog * dynamic button type options
1 parent 6f849fd commit 1103c91

2 files changed

Lines changed: 91 additions & 26 deletions

File tree

wled00/data/settings_time.htm

Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@
190190
}
191191
}
192192
function pMP() { // populateMacroPresets
193-
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
193+
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
194194
var fields = ['A0','A1','MC','MN'];
195195
for (var f of fields) {
196196
var inp = gN(f);
@@ -219,13 +219,38 @@
219219
rPS(sel, presetOpts, "data-preset");
220220
}
221221
}
222+
function bAO() { // buildAnalogOptions: analog functions + per-segment opacity (segment 0 included; MD=0 => segment 0)
223+
var o = '<optgroup label="Analog Functions"><option value="250">Global brightness (250)</option><option value="249">Effect speed (249)</option><option value="248">Effect intensity (248)</option><option value="247">Palette (247)</option><option value="200">Primary color hue (200)</option></optgroup><optgroup label="Analog Segment Opacity">';
224+
for (var j=0; j<=32; j++) o += `<option value="${j}">Segment ${j} opacity</option>`;
225+
o += '</optgroup>';
226+
return o;
227+
}
228+
function isAnalogBtn(t) { return t==7 || t==8; } // BTN_TYPE_ANALOG / BTN_TYPE_ANALOG_INVERTED
229+
function isSwitchBtn(t) { return t==4 || t==5 || t==9; } // BTN_TYPE_SWITCH / BTN_TYPE_PIR_SENSOR / BTN_TYPE_TOUCH_SWITCH
230+
function btnTypeName(t) { // mirrors the button type dropdown on the LED settings page
231+
switch (+t) {
232+
case 2: return 'Pushbutton';
233+
case 3: return 'Push inverted';
234+
case 4: return 'Switch';
235+
case 5: return 'PIR sensor';
236+
case 6: return 'Touch';
237+
case 7: return 'Analog';
238+
case 8: return 'Analog inverted';
239+
case 9: return 'Touch (switch)';
240+
default: return 'Disabled';
241+
}
242+
}
222243
function rBPO() { // refreshButtonPresetOptions
223-
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
244+
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
245+
var analogOpts = bAO();
224246
var container = gId("macros");
225247
if (!container) return;
248+
// analog buttons only have an MD select (MP/ML are hidden 0 inputs); MD uses analog options, never presets
226249
var sels = container.querySelectorAll('select[name^="MP"],select[name^="ML"],select[name^="MD"]');
227250
for (var sel of sels) {
228-
rPS(sel, presetOpts, "data-preset");
251+
var bb = sel.closest ? sel.closest(".bb") : null;
252+
var t = bb ? parseInt(bb.getAttribute("data-btype")||"0",10) : 0;
253+
rPS(sel, isAnalogBtn(t) ? analogOpts : presetOpts, "data-preset");
229254
}
230255
}
231256
function Wd()
@@ -246,33 +271,73 @@
246271
if (d.Sf.LTR.value==="S") { d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); }
247272
if (d.Sf.LNR.value==="W") { d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); }
248273
}
249-
function addRow(i,p,l,d) {
274+
function addRow(i,p,l,d,t) {
275+
if (t===undefined) t = 0;
250276
var b = String.fromCharCode((i<10?48:55)+i);
251-
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
277+
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
278+
var typeName = btnTypeName(t);
252279
var buttonBlock = document.createElement('div');
253280
buttonBlock.className = 'bb';
254-
buttonBlock.innerHTML = `
255-
<div class="bh">Button (switch) ${i}</div>
256-
<div class="bs">
257-
<div class="ba">
258-
<label>Short (on → off)</label>
259-
<select name="MP${b}" class="s" required>${presetOpts}</select>
281+
buttonBlock.setAttribute('data-btype', t); // read back by rBPO() to rebuild selects correctly
282+
if (isAnalogBtn(t)) {
283+
// analog buttons: MD holds the function/segment; short/long press are unused (firmware defaults missing MP/ML to 0)
284+
buttonBlock.innerHTML = `
285+
<div class="bh">Analog ${i} - ${typeName}</div>
286+
<div class="bs">
287+
<div class="ba">
288+
<label>Analog function</label>
289+
<select name="MD${b}" class="s" required>${bAO()}</select>
290+
</div>
260291
</div>
261-
<div class="ba">
262-
<label>Long (off → on)</label>
263-
<select name="ML${b}" class="s" required>${presetOpts}</select>
292+
<hr style="width:100%;margin:8px 0 0 0;">
293+
`;
294+
sPSV(buttonBlock.querySelector('select[name="MD'+b+'"]'), String(d), "data-preset");
295+
} else if (isSwitchBtn(t)) {
296+
// switches: MP fires on On->Off, ML on Off->On; double press (MD) is unused (firmware defaults missing MD to 0)
297+
buttonBlock.innerHTML = `
298+
<div class="bh">Switch ${i} - ${typeName}</div>
299+
<div class="bs">
300+
<div class="ba">
301+
<label>On → Off</label>
302+
<select name="MP${b}" class="s" required>${presetOpts}</select>
303+
</div>
304+
<div class="ba">
305+
<label>Off → On</label>
306+
<select name="ML${b}" class="s" required>${presetOpts}</select>
307+
</div>
264308
</div>
265-
<div class="ba">
266-
<label>Double press (n/a)</label>
267-
<select name="MD${b}" class="s" required>${presetOpts}</select>
309+
<hr style="width:100%;margin:8px 0 0 0;">
310+
`;
311+
var switchSels = buttonBlock.querySelectorAll("select");
312+
var switchVals = [String(p), String(l)];
313+
for (var si=0; si<switchSels.length; si++) {
314+
sPSV(switchSels[si], switchVals[si], "data-preset");
315+
}
316+
} else {
317+
// pushbuttons: short (MP), long (ML) and double (MD) press
318+
buttonBlock.innerHTML = `
319+
<div class="bh">Button ${i} - ${typeName}</div>
320+
<div class="bs">
321+
<div class="ba">
322+
<label>Short press</label>
323+
<select name="MP${b}" class="s" required>${presetOpts}</select>
324+
</div>
325+
<div class="ba">
326+
<label>Long press</label>
327+
<select name="ML${b}" class="s" required>${presetOpts}</select>
328+
</div>
329+
<div class="ba">
330+
<label>Double press</label>
331+
<select name="MD${b}" class="s" required>${presetOpts}</select>
332+
</div>
268333
</div>
269-
</div>
270-
<hr style="width:100%;margin:8px 0 0 0;">
271-
`;
272-
var buttonSels = buttonBlock.querySelectorAll("select");
273-
var buttonVals = [String(p), String(l), String(d)];
274-
for (var si=0; si<buttonSels.length; si++) {
275-
sPSV(buttonSels[si], buttonVals[si], "data-preset");
334+
<hr style="width:100%;margin:8px 0 0 0;">
335+
`;
336+
var buttonSels = buttonBlock.querySelectorAll("select");
337+
var buttonVals = [String(p), String(l), String(d)];
338+
for (var si=0; si<buttonSels.length; si++) {
339+
sPSV(buttonSels[si], buttonVals[si], "data-preset");
340+
}
276341
}
277342
gId("macros").appendChild(buttonBlock);
278343
}
@@ -372,7 +437,7 @@ <h3>Timer & Alexa Presets</h3>
372437
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>
373438
</div>
374439
<div class="sec">
375-
<h3>Button (switch) Action Presets</h3>
440+
<h3>Button Action Presets</h3>
376441
<div id="macros"></div>
377442
<a href="https://kno.wled.ge/features/macros/#analog-button" target="_blank">Analog Button setup</a>
378443
</div>

wled00/xml.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
628628
printSetFormValue(settingsScript,PSTR("MN"),macroNl);
629629
int ii = 0;
630630
for (const auto &button : buttons) {
631-
settingsScript.printf_P(PSTR("addRow(%d,%d,%d,%d);"), ii++, button.macroButton, button.macroLongPress, button.macroDoublePress);
631+
settingsScript.printf_P(PSTR("addRow(%d,%d,%d,%d,%d);"), ii++, button.macroButton, button.macroLongPress, button.macroDoublePress, button.type);
632632
}
633633

634634
settingsScript.printf_P(PSTR("maxTimers=%d;"), WLED_MAX_TIMERS);

0 commit comments

Comments
 (0)