Merge branch 'master' of https://github.com/aircoookie/WLED into dev
Conflicts: tools/cdata.js usermods/PIR_sensor_switch/readme.md usermods/Temperature/readme.md wled00/FX.h wled00/FX_fcn.cpp wled00/bus_manager.h wled00/bus_wrapper.h wled00/cfg.cpp wled00/const.h wled00/data/settings.htm wled00/data/settings_leds.htm wled00/data/settings_um.htm wled00/html_settings.h wled00/json.cpp wled00/mqtt.cpp wled00/set.cpp wled00/wled.cpp wled00/wled.h wled00/wled_eeprom.cpp wled00/wled_server.cpp wled00/xml.cpp
This commit is contained in:
commit
bfd7be543a
30
CHANGELOG.md
30
CHANGELOG.md
@ -2,6 +2,36 @@
|
|||||||
|
|
||||||
### Builds after release 0.12.0
|
### Builds after release 0.12.0
|
||||||
|
|
||||||
|
#### Build 2105171
|
||||||
|
|
||||||
|
- Always copy MQTT payloads to prevent non-0-terminated strings
|
||||||
|
- Updated ArduinoJson to 6.18.0
|
||||||
|
- Added experimental support for `{"on":"t"}` to toggle on/off state via JSON
|
||||||
|
|
||||||
|
#### Build 2105120
|
||||||
|
|
||||||
|
- Fixed possibility of non-0-terminated MQTT payloads
|
||||||
|
- Fixed two warnings regarding integer comparison
|
||||||
|
|
||||||
|
#### Build 2105112
|
||||||
|
|
||||||
|
- Usermod settings page no usermods message
|
||||||
|
- Lowered min speed for Drip effect
|
||||||
|
|
||||||
|
#### Build 2105111
|
||||||
|
|
||||||
|
- Fixed various Codacy code style and logic issues
|
||||||
|
|
||||||
|
#### Build 2105110
|
||||||
|
|
||||||
|
- Added Usermod settings page and configurable usermods (PR #1951)
|
||||||
|
- Added experimental `/json/cfg` endpoint for changing settings from JSON (see #1944, not part of official API)
|
||||||
|
|
||||||
|
#### Build 2105070
|
||||||
|
|
||||||
|
- Fixed not turning on after pressing "Off" on IR remote twice (#1950)
|
||||||
|
- Fixed OTA update file selection from Android app (TODO: file type verification in JS, since android can't deal with accept='.bin' attribute)
|
||||||
|
|
||||||
#### Build 2104220
|
#### Build 2104220
|
||||||
|
|
||||||
- Version bump to 0.12.1-b1 "Hikari"
|
- Version bump to 0.12.1-b1 "Hikari"
|
||||||
|
@ -114,9 +114,6 @@ build_unflags =
|
|||||||
|
|
||||||
# enables all features for travis CI
|
# enables all features for travis CI
|
||||||
build_flags_all_features =
|
build_flags_all_features =
|
||||||
-D WLED_USE_ANALOG_LED
|
|
||||||
-D WLED_USE_H801
|
|
||||||
-D WLED_ENABLE_5CH_LEDS
|
|
||||||
-D WLED_ENABLE_ADALIGHT
|
-D WLED_ENABLE_ADALIGHT
|
||||||
-D WLED_ENABLE_DMX
|
-D WLED_ENABLE_DMX
|
||||||
-D WLED_ENABLE_MQTT
|
-D WLED_ENABLE_MQTT
|
||||||
@ -289,7 +286,7 @@ platform = ${common.platform_wled_default}
|
|||||||
platform_packages = ${common.platform_packages}
|
platform_packages = ${common.platform_packages}
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_USE_ANALOG_LEDS
|
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||||
|
|
||||||
[env:esp8285_4CH_H801]
|
[env:esp8285_4CH_H801]
|
||||||
board = esp8285
|
board = esp8285
|
||||||
@ -297,7 +294,7 @@ platform = ${common.platform_wled_default}
|
|||||||
platform_packages = ${common.platform_packages}
|
platform_packages = ${common.platform_packages}
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801
|
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||||
|
|
||||||
[env:esp8285_5CH_H801]
|
[env:esp8285_5CH_H801]
|
||||||
board = esp8285
|
board = esp8285
|
||||||
@ -305,7 +302,7 @@ platform = ${common.platform_wled_default}
|
|||||||
platform_packages = ${common.platform_packages}
|
platform_packages = ${common.platform_packages}
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 -D WLED_ENABLE_5CH_LEDS
|
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||||
|
|
||||||
[env:d1_mini_5CH_Shojo_PCB]
|
[env:d1_mini_5CH_Shojo_PCB]
|
||||||
board = d1_mini
|
board = d1_mini
|
||||||
@ -313,7 +310,7 @@ platform = ${common.platform_wled_default}
|
|||||||
platform_packages = ${common.platform_packages}
|
platform_packages = ${common.platform_packages}
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D WLED_USE_SHOJO_PCB -D WLED_ENABLE_5CH_LEDS
|
build_flags = ${common.build_flags_esp8266} -D WLED_USE_SHOJO_PCB
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# DEVELOPMENT BOARDS
|
# DEVELOPMENT BOARDS
|
||||||
@ -405,6 +402,7 @@ build_flags = ${common.build_flags_esp32} ${common.debug_flags} ${common.build_f
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# codm pixel controller board configurations
|
# codm pixel controller board configurations
|
||||||
|
# codm-controller-0.6 can also be used for the TYWE3S controller
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
[env:codm-controller-0.6]
|
[env:codm-controller-0.6]
|
||||||
|
@ -39,12 +39,8 @@ build_flags = ${common.build_flags_esp8266}
|
|||||||
; PIN defines for 2 wire LEDs
|
; PIN defines for 2 wire LEDs
|
||||||
-D CLKPIN=0
|
-D CLKPIN=0
|
||||||
-D DATAPIN=2
|
-D DATAPIN=2
|
||||||
; to drive analog LED strips (aka 5050), uncomment the following
|
; to drive analog LED strips (aka 5050) hardware configuration is no longer necessary
|
||||||
; PWM pins 5,12,13,15 are used with Magic Home LED Controller (default)
|
; configure the settings in the UI as follows (hard):
|
||||||
-D WLED_USE_ANALOG_LEDS
|
; for the Magic Home LED Controller use PWM pins 5,12,13,15
|
||||||
; for the H801 controller (PINs 15,13,12,14 (W2 = 04)) uncomment this
|
; for the H801 controller use PINs 15,13,12,14 (W2 = 04)
|
||||||
; -D WLED_USE_H801
|
; for the BW-LT11 controller use PINs 12,4,14,5
|
||||||
; for the BW-LT11 controller (PINs 12,4,14,5 ) uncomment this
|
|
||||||
; -D WLED_USE_BWLT11
|
|
||||||
; and to enable channel 5 for RGBW-CT led strips this
|
|
||||||
; -D WLED_USE_5CH_LEDS
|
|
||||||
|
@ -344,6 +344,10 @@ const char PAGE_settings_dmx[] PROGMEM = R"=====()=====";
|
|||||||
str
|
str
|
||||||
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
.replace(/\<link rel="stylesheet".*\>/gms, "")
|
||||||
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
.replace(/\<style\>.*\<\/style\>/gms, "%CSS%%SCSS%")
|
||||||
|
.replace(
|
||||||
|
/function GetV().*\<\/script\>/gms,
|
||||||
|
"function GetV() {var d=document;\n"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"wled00/html_settings.h"
|
"wled00/html_settings.h"
|
||||||
|
232
tools/fps_test.htm
Normal file
232
tools/fps_test.htm
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>WLED frame rate test tool</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #222;
|
||||||
|
color: #fff;
|
||||||
|
font-family: Helvetica, Verdana, sans-serif;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#ip {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
#secs {
|
||||||
|
width: 36px;
|
||||||
|
}
|
||||||
|
#csva {
|
||||||
|
position: absolute;
|
||||||
|
top: -100px; /*gtfo*/
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-collapse: collapse;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
color: #d20;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var gotfx = false, running = false;
|
||||||
|
var pos = 0, prev = 0, min = 999, max = 0, fpslist = [], names = [], names_checked = [];
|
||||||
|
var to;
|
||||||
|
function S() {
|
||||||
|
document.getElementById('ip').value = localStorage.getItem('locIpFps');
|
||||||
|
if (document.getElementById('ip').value) req(false);
|
||||||
|
}
|
||||||
|
function loadC() {
|
||||||
|
hide(false);
|
||||||
|
var list = localStorage.getItem('fpsFxSelection');
|
||||||
|
if (!list) return;
|
||||||
|
list = JSON.parse(list);
|
||||||
|
var chks = document.querySelectorAll('.fxcheck');
|
||||||
|
for (let i = 0; i < chks.length; i++) {
|
||||||
|
if (i < list.length) chks[i].checked = list[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function saveC() {
|
||||||
|
var list = [];
|
||||||
|
var chks = document.querySelectorAll('.fxcheck');
|
||||||
|
for (let i = 0; i < chks.length; i++) {
|
||||||
|
list.push(chks[i].checked);
|
||||||
|
}
|
||||||
|
localStorage.setItem('fpsFxSelection', JSON.stringify(list));
|
||||||
|
}
|
||||||
|
function setC(c) {
|
||||||
|
hide(false);
|
||||||
|
var chks = document.querySelectorAll('.fxcheck');
|
||||||
|
for (let i = 0; i < chks.length; i++) {
|
||||||
|
chks[i].checked = (c == 255);
|
||||||
|
}
|
||||||
|
if (c == 1 && chks.length > 100) {
|
||||||
|
chks[1].checked = true; //Blink
|
||||||
|
chks[15].checked = true; //Running
|
||||||
|
chks[16].checked = true; //Saw
|
||||||
|
chks[37].checked = true; //Running 2
|
||||||
|
chks[44].checked = true; //Tetrix
|
||||||
|
chks[63].checked = true; //Pride 2015
|
||||||
|
chks[74].checked = true; //Colortwinkles
|
||||||
|
chks[101].checked = true;//Pacifica
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function hide(h) {
|
||||||
|
var trs = document.querySelectorAll('.trs');
|
||||||
|
var chks = document.querySelectorAll('.fxcheck');
|
||||||
|
for (let i = 0; i < trs.length; i++) {
|
||||||
|
trs[i].style.display = (h && !chks[i].checked) ? "none":"table-row";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function run(init) {
|
||||||
|
if (init) {
|
||||||
|
running = !running;
|
||||||
|
document.getElementById('runbtn').innerText = running ? 'Stop':'Run';
|
||||||
|
if (running) {pos = 0; prev = -1; min = 999; max = 0; fpslist = []; names_checked = []; hide(true);}
|
||||||
|
clearTimeout(to);
|
||||||
|
if (!running) {req({seg:{fx:0},v:true,stop:true}); return;}
|
||||||
|
}
|
||||||
|
if (!gotfx) {req(false); return;}
|
||||||
|
var chks = document.querySelectorAll('.fxcheck');
|
||||||
|
var fpsb = document.querySelectorAll('.fps');
|
||||||
|
if (prev >= 0) {pos++};
|
||||||
|
if (pos >= chks.length) {run(true); return;} //end
|
||||||
|
while (!chks[pos].checked) {
|
||||||
|
fpsb[pos].innerText = "-";
|
||||||
|
pos++;
|
||||||
|
if (pos >= chks.length) {run(true); return;} //end
|
||||||
|
}
|
||||||
|
names_checked.push(names[pos]);
|
||||||
|
var extra = {};
|
||||||
|
try {
|
||||||
|
extra = JSON.parse(document.getElementById('ej').value);
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
var cmd = {seg:{fx:pos},v:true};
|
||||||
|
Object.assign(cmd, extra);
|
||||||
|
req(cmd);
|
||||||
|
}
|
||||||
|
function req(command) {
|
||||||
|
var ip = document.getElementById('ip').value;
|
||||||
|
if (!ip) {alert("Please enter WLED IP"); return;}
|
||||||
|
if (ip != localStorage.getItem('locIpFps')) localStorage.setItem('locIpFps', document.getElementById('ip').value);
|
||||||
|
var url = command ? `http://${ip}/json/si` : `http://${ip}/json/effects`;
|
||||||
|
var type = command ? 'post':'get';
|
||||||
|
var req = undefined;
|
||||||
|
if (command)
|
||||||
|
{
|
||||||
|
req = JSON.stringify(command);
|
||||||
|
}
|
||||||
|
fetch
|
||||||
|
(url, {
|
||||||
|
method: type,
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json; charset=UTF-8"
|
||||||
|
},
|
||||||
|
body: req
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (!res.ok) {
|
||||||
|
alert('Data malfunction');
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then(json => {
|
||||||
|
if (!json) {
|
||||||
|
alert('Empty response'); return;
|
||||||
|
}
|
||||||
|
if (!command) {
|
||||||
|
names = json;
|
||||||
|
var tblc = '';
|
||||||
|
for (let i = 0; i < json.length; i++) {
|
||||||
|
tblc += `<tr class="trs"><td><input type="checkbox" class="fxcheck" /></td><td>${i}</td><td>${json[i]}</td><td class="fps"></td></tr>`
|
||||||
|
}
|
||||||
|
var tbl = `<table>
|
||||||
|
<tr>
|
||||||
|
<th>Test?</th><th>ID</th><th>Effect Name</th><th>FPS</th>
|
||||||
|
</tr>
|
||||||
|
${tblc}
|
||||||
|
</table>`;
|
||||||
|
document.getElementById('tablecon').innerHTML = tbl;
|
||||||
|
setC(1);
|
||||||
|
loadC();
|
||||||
|
gotfx = true;
|
||||||
|
document.getElementById('runbtn').innerText = "Run";
|
||||||
|
} else {
|
||||||
|
if (!json.info) return;
|
||||||
|
document.getElementById('leds').innerText = json.info.leds.count;
|
||||||
|
document.getElementById('seg').innerText = json.state.seg[0].len;
|
||||||
|
document.getElementById('bri').innerText = json.state.bri;
|
||||||
|
if (prev >= 0) {
|
||||||
|
var lastfps = parseInt(json.info.leds.fps); //previous FX
|
||||||
|
if (lastfps < min) min = lastfps;
|
||||||
|
if (lastfps > max) max = lastfps;
|
||||||
|
fpslist.push(lastfps);
|
||||||
|
var sum = 0;
|
||||||
|
for (let i = 0; i < fpslist.length; i++) {
|
||||||
|
sum += fpslist[i];
|
||||||
|
}
|
||||||
|
sum /= fpslist.length;
|
||||||
|
document.getElementById('fps_min').innerText = min;
|
||||||
|
document.getElementById('fps_max').innerText = max;
|
||||||
|
document.getElementById('fps_avg').innerText = Math.round(sum*10)/10;
|
||||||
|
var fpsb = document.querySelectorAll('.fps');
|
||||||
|
fpsb[prev].innerHTML = lastfps;
|
||||||
|
}
|
||||||
|
prev = pos;
|
||||||
|
var delay = parseInt(document.getElementById('secs').value)*1000;
|
||||||
|
delay = Math.min(Math.max(delay, 2000), 15000)
|
||||||
|
if (!command.stop) to = setTimeout(run,delay);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
alert('Comms malfunction');
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function csv(n) {
|
||||||
|
var txt = "";
|
||||||
|
for (let i = 0; i < fpslist.length; i++) {
|
||||||
|
if (!n) txt += names_checked[i] + ',';
|
||||||
|
txt += fpslist[i]; txt += "\n";
|
||||||
|
}
|
||||||
|
document.getElementById('csva').value = txt;
|
||||||
|
var copyText = document.getElementById('csva');
|
||||||
|
|
||||||
|
copyText.select();
|
||||||
|
copyText.setSelectionRange(0, 999999);
|
||||||
|
document.execCommand("copy");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="S()">
|
||||||
|
<h2>Starship monitoring dashboard</h2>
|
||||||
|
(or rather just a WLED frame rate tester lol)<br><br>
|
||||||
|
IP: <input id="ip" /><br>
|
||||||
|
Time per effect: <input type=number id=secs value=5 max=15 min=2 />s<br>
|
||||||
|
Effects to test:
|
||||||
|
<button type="button" onclick="setC(255)">All</button>
|
||||||
|
<button type="button" onclick="setC(1)">Selection 1</button>
|
||||||
|
<button type="button" onclick="setC(0)">None</button>
|
||||||
|
<button type="button" onclick="loadC()">Get LS</button>
|
||||||
|
<button type="button" class="red" onclick="saveC()">Save to LS</button><br>
|
||||||
|
Extra JSON: <input id="ej" /><br>
|
||||||
|
|
||||||
|
<button type="button" onclick="run(true)" id="runbtn">Fetch FX list</button><br>
|
||||||
|
LEDs: <span id="leds">-</span>, Seg: <span id="seg">-</span>, Bri: <span id="bri">-</span><br>
|
||||||
|
FPS min: <span id="fps_min">-</span>, max: <span id="fps_max">-</span>, avg: <span id="fps_avg">-</span><br><br>
|
||||||
|
<div id="tablecon">
|
||||||
|
</div><br>
|
||||||
|
<button type="button" onclick="csv(false)">Copy csv to clipboard</button>
|
||||||
|
<button type="button" onclick="csv(true)">Copy csv (FPS only)</button>
|
||||||
|
<textarea id=csva></textarea>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -9,9 +9,7 @@ The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wik
|
|||||||
|
|
||||||
## Webinterface
|
## Webinterface
|
||||||
|
|
||||||
The info page in the web interface shows the items below
|
The info page in the web interface shows the remaining time of the off timer.
|
||||||
- the remaining time of the off timer.
|
|
||||||
**I recommend to deactivate the sensor before an OTA update and activate it again afterwards**.
|
|
||||||
|
|
||||||
## Sensor connection
|
## Sensor connection
|
||||||
|
|
||||||
@ -65,6 +63,9 @@ void registerUsermods()
|
|||||||
|
|
||||||
To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` and `void EnablePIRsensor(bool enable)` are available.
|
To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` and `void EnablePIRsensor(bool enable)` are available.
|
||||||
|
|
||||||
|
When the PIR sensor state changes an MQTT message is broadcasted with topic `wled/deviceMAC/motion` and message `on` or `off`.
|
||||||
|
Usermod can also be configured to just send MQTT message and not change WLED state using settings page as well as responding to motion only during nighttime (assuming NTP and lattitude/longitude are set to determine sunrise/sunset times).
|
||||||
|
|
||||||
### There are two options to get access to the usermod instance:
|
### There are two options to get access to the usermod instance:
|
||||||
|
|
||||||
1. Include `usermod_PIR_sensor_switch.h` **before** you include the other usermod in `usermods_list.cpp'
|
1. Include `usermod_PIR_sensor_switch.h` **before** you include the other usermod in `usermods_list.cpp'
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Based on the excellent `QuinLED_Dig_Uno_Temp_MQTT` by srg74 and 400killer!
|
Based on the excellent `QuinLED_Dig_Uno_Temp_MQTT` by srg74 and 400killer!
|
||||||
This usermod will read from an attached DS18B20 temperature sensor (as available on the QuinLED Dig-Uno)
|
This usermod will read from an attached DS18B20 temperature sensor (as available on the QuinLED Dig-Uno)
|
||||||
The temperature is displayed both in the Info section of the web UI as well as published to the `/temperature` MQTT topic if enabled.
|
The temperature is displayed both in the Info section of the web UI as well as published to the `/temperature` MQTT topic if enabled.
|
||||||
This usermod will be expanded with support for different sensor types in the future.
|
This usermod may be expanded with support for different sensor types in the future.
|
||||||
|
|
||||||
If temperature sensor is not detected during boot, this usermod will be disabled.
|
If temperature sensor is not detected during boot, this usermod will be disabled.
|
||||||
|
|
||||||
@ -16,18 +16,19 @@ Copy the example `platformio_override.ini` to the root directory. This file sho
|
|||||||
* `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp
|
* `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp
|
||||||
* `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
* `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
||||||
|
|
||||||
All parameters can be configured at runtime using Usermods settings page.
|
All parameters can be configured at runtime using Usermods settings page, including pin, selection to display temerature in degrees Celsius or Farenheit mand measurement interval.
|
||||||
|
|
||||||
## Project link
|
## Project link
|
||||||
|
|
||||||
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||||
|
* [Srg74-WLED-Wemos-shield](https://github.com/srg74/WLED-wemos-shield) - another great DIY WLED board
|
||||||
|
|
||||||
### PlatformIO requirements
|
### PlatformIO requirements
|
||||||
|
|
||||||
If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:d1_mini_usermod_dallas_temperature_C`.
|
If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:d1_mini_usermod_dallas_temperature_C`.
|
||||||
|
|
||||||
|
|
||||||
If you are not using `platformio_override.ini`, you might have to uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
If you are not using `platformio_override.ini`, you might have to uncomment `OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
# platformio.ini
|
# platformio.ini
|
||||||
@ -41,8 +42,7 @@ default_envs = d1_mini
|
|||||||
...
|
...
|
||||||
lib_deps =
|
lib_deps =
|
||||||
...
|
...
|
||||||
#For Dallas sensor uncomment following 2 lines
|
#For Dallas sensor uncomment following line
|
||||||
DallasTemperature@~3.8.0
|
|
||||||
OneWire@~2.3.5
|
OneWire@~2.3.5
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
Binary file not shown.
@ -34,7 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
uint16_t WS2812FX::mode_static(void) {
|
uint16_t WS2812FX::mode_static(void) {
|
||||||
fill(SEGCOLOR(0));
|
fill(SEGCOLOR(0));
|
||||||
return (SEGMENT.getOption(SEG_OPTION_TRANSITIONAL)) ? FRAMETIME : 380; //update faster if in transition
|
return (SEGMENT.getOption(SEG_OPTION_TRANSITIONAL)) ? FRAMETIME : 350; //update faster if in transition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1436,8 +1436,8 @@ uint16_t WS2812FX::mode_tricolor_fade(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte stp = prog; // % 256
|
byte stp = prog; // % 256
|
||||||
uint32_t color = 0;
|
|
||||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||||
|
uint32_t color;
|
||||||
if (stage == 2) {
|
if (stage == 2) {
|
||||||
color = color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 2), color2, stp);
|
color = color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 2), color2, stp);
|
||||||
} else if (stage == 1) {
|
} else if (stage == 1) {
|
||||||
@ -3050,7 +3050,7 @@ uint16_t WS2812FX::mode_drip(void)
|
|||||||
|
|
||||||
numDrops = 1 + (SEGMENT.intensity >> 6); // 255>>6 = 3
|
numDrops = 1 + (SEGMENT.intensity >> 6); // 255>>6 = 3
|
||||||
|
|
||||||
float gravity = -0.001 - (SEGMENT.speed/50000.0);
|
float gravity = -0.0005 - (SEGMENT.speed/50000.0);
|
||||||
gravity *= SEGLEN;
|
gravity *= SEGLEN;
|
||||||
int sourcedrop = 12;
|
int sourcedrop = 12;
|
||||||
|
|
||||||
|
@ -612,6 +612,7 @@ class WS2812FX {
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
isRgbw = false,
|
isRgbw = false,
|
||||||
|
isOffRefreshRequred = false, //periodic refresh is required for the strip to remain off.
|
||||||
gammaCorrectBri = false,
|
gammaCorrectBri = false,
|
||||||
gammaCorrectCol = true,
|
gammaCorrectCol = true,
|
||||||
applyToAllSelected = true,
|
applyToAllSelected = true,
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
Editor: https://www.visualmicro.com/
|
|
||||||
This file is for intellisense purpose only.
|
|
||||||
Visual micro (and the arduino ide) ignore this code during compilation. This code is automatically maintained by visualmicro, manual changes to this file will be overwritten
|
|
||||||
The contents of the _vm sub folder can be deleted prior to publishing a project
|
|
||||||
All non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!).
|
|
||||||
Note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again
|
|
||||||
|
|
||||||
Hardware: ESP32 Dev Module, Platform=esp32, Package=esp32
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(_VMICRO_INTELLISENSE)
|
|
||||||
|
|
||||||
#ifndef _VSARDUINO_H_
|
|
||||||
#define _VSARDUINO_H_
|
|
||||||
#define __ESP32_esp32__
|
|
||||||
#define __ESP32_ESP32__
|
|
||||||
#define ESP_PLATFORM
|
|
||||||
#define HAVE_CONFIG_H
|
|
||||||
#define GCC_NOT_5_2_0 0
|
|
||||||
#define WITH_POSIX
|
|
||||||
#define F_CPU 240000000L
|
|
||||||
#define ARDUINO 108011
|
|
||||||
#define ARDUINO_ESP32_DEV
|
|
||||||
#define ARDUINO_ARCH_ESP32
|
|
||||||
#define ESP32
|
|
||||||
#define CORE_DEBUG_LEVEL 0
|
|
||||||
#define __cplusplus 201103L
|
|
||||||
|
|
||||||
#define _Pragma(x)
|
|
||||||
#undef __cplusplus
|
|
||||||
#define __cplusplus 201103L
|
|
||||||
|
|
||||||
#define __STDC__
|
|
||||||
#define __ARM__
|
|
||||||
#define __arm__
|
|
||||||
#define __inline__
|
|
||||||
#define __asm__(...)
|
|
||||||
#define __extension__
|
|
||||||
#define __ATTR_PURE__
|
|
||||||
#define __ATTR_CONST__
|
|
||||||
#define __volatile__
|
|
||||||
|
|
||||||
#define __ASM
|
|
||||||
#define __INLINE
|
|
||||||
#define __attribute__(noinline)
|
|
||||||
|
|
||||||
//#define _STD_BEGIN
|
|
||||||
//#define EMIT
|
|
||||||
#define WARNING
|
|
||||||
#define _Lockit
|
|
||||||
#define __CLR_OR_THIS_CALL
|
|
||||||
#define C4005
|
|
||||||
#define _NEW
|
|
||||||
|
|
||||||
typedef bool _Bool;
|
|
||||||
typedef int _read;
|
|
||||||
typedef int _seek;
|
|
||||||
typedef int _write;
|
|
||||||
typedef int _close;
|
|
||||||
typedef int __cleanup;
|
|
||||||
|
|
||||||
//#define inline
|
|
||||||
|
|
||||||
#define __builtin_clz
|
|
||||||
#define __builtin_clzl
|
|
||||||
#define __builtin_clzll
|
|
||||||
#define __builtin_labs
|
|
||||||
#define __builtin_va_list
|
|
||||||
typedef int __gnuc_va_list;
|
|
||||||
|
|
||||||
#define __ATOMIC_ACQ_REL
|
|
||||||
|
|
||||||
#define __CHAR_BIT__
|
|
||||||
#define _EXFUN()
|
|
||||||
|
|
||||||
typedef unsigned char byte;
|
|
||||||
extern "C" void __cxa_pure_virtual() {;}
|
|
||||||
|
|
||||||
typedef long __INTPTR_TYPE__ ;
|
|
||||||
typedef long __UINTPTR_TYPE__ ;
|
|
||||||
typedef long __SIZE_TYPE__ ;
|
|
||||||
typedef long __PTRDIFF_TYPE__;
|
|
||||||
|
|
||||||
typedef long pthread_t;
|
|
||||||
typedef long pthread_key_t;
|
|
||||||
typedef long pthread_once_t;
|
|
||||||
typedef long pthread_mutex_t;
|
|
||||||
typedef long pthread_mutex_t;
|
|
||||||
typedef long pthread_cond_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "arduino.h"
|
|
||||||
#include <pins_arduino.h>
|
|
||||||
|
|
||||||
#define interrupts() sei()
|
|
||||||
#define noInterrupts() cli()
|
|
||||||
|
|
||||||
#define ESP_LOGI(tag, ...)
|
|
||||||
|
|
||||||
#include "wled00.ino"
|
|
||||||
#include "wled01_eeprom.ino"
|
|
||||||
#include "wled02_xml.ino"
|
|
||||||
#include "wled03_set.ino"
|
|
||||||
#include "wled04_file.ino"
|
|
||||||
#include "wled05_init.ino"
|
|
||||||
#include "wled06_usermod.ino"
|
|
||||||
#include "wled07_notify.ino"
|
|
||||||
#include "wled08_led.ino"
|
|
||||||
#include "wled09_button.ino"
|
|
||||||
#include "wled10_ntp.ino"
|
|
||||||
#include "wled11_ol.ino"
|
|
||||||
#include "wled12_alexa.ino"
|
|
||||||
#include "wled13_cronixie.ino"
|
|
||||||
#include "wled14_colors.ino"
|
|
||||||
#include "wled15_hue.ino"
|
|
||||||
#include "wled16_blynk.ino"
|
|
||||||
#include "wled17_mqtt.ino"
|
|
||||||
#include "wled18_server.ino"
|
|
||||||
#include "wled19_json.ino"
|
|
||||||
#include "wled20_ir.ino"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -63,7 +63,7 @@ class Bus {
|
|||||||
return _start;
|
return _start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStart(uint16_t start) {
|
inline void setStart(uint16_t start) {
|
||||||
_start = start;
|
_start = start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ class Bus {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint8_t skipFirstLed() {
|
virtual uint8_t skippedLeds() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,10 +184,10 @@ class BusDigital : public Bus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool isRgbw() {
|
inline bool isRgbw() {
|
||||||
return _rgbw;
|
return (_rgbw || _type == TYPE_SK6812_RGBW || _type == TYPE_TM1814);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t skipFirstLed() {
|
inline uint8_t skippedLeds() {
|
||||||
return _skip;
|
return _skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,6 +451,11 @@ class BusManager {
|
|||||||
return Bus::isRgbw(type);
|
return Bus::isRgbw(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Return true if the strip requires a refresh to stay off.
|
||||||
|
static bool isOffRefreshRequred(uint8_t type) {
|
||||||
|
return type == TYPE_TM1814;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t numBusses = 0;
|
uint8_t numBusses = 0;
|
||||||
Bus* busses[WLED_MAX_BUSSES];
|
Bus* busses[WLED_MAX_BUSSES];
|
||||||
|
@ -12,24 +12,7 @@ void getStringFromJson(char* dest, const char* src, size_t len) {
|
|||||||
if (src != nullptr) strlcpy(dest, src, len);
|
if (src != nullptr) strlcpy(dest, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserializeConfig() {
|
bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||||
bool fromeep = false;
|
|
||||||
bool success = deserializeConfigSec();
|
|
||||||
if (!success) { //if file does not exist, try reading from EEPROM
|
|
||||||
deEEPSettings();
|
|
||||||
fromeep = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
|
|
||||||
|
|
||||||
success = readObjectFromFile("/cfg.json", nullptr, &doc);
|
|
||||||
if (!success) { //if file does not exist, try reading from EEPROM
|
|
||||||
if (!fromeep) deEEPSettings();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//int rev_major = doc["rev"][0]; // 1
|
//int rev_major = doc["rev"][0]; // 1
|
||||||
//int rev_minor = doc["rev"][1]; // 0
|
//int rev_minor = doc["rev"][1]; // 0
|
||||||
|
|
||||||
@ -103,6 +86,8 @@ void deserializeConfig() {
|
|||||||
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
|
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
|
||||||
|
|
||||||
JsonArray ins = hw_led["ins"];
|
JsonArray ins = hw_led["ins"];
|
||||||
|
|
||||||
|
if (fromFS || !ins.isNull()) {
|
||||||
uint8_t s = 0; // bus iterator
|
uint8_t s = 0; // bus iterator
|
||||||
strip.isRgbw = false;
|
strip.isRgbw = false;
|
||||||
busses.removeAll();
|
busses.removeAll();
|
||||||
@ -112,6 +97,7 @@ void deserializeConfig() {
|
|||||||
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||||
JsonArray pinArr = elm["pin"];
|
JsonArray pinArr = elm["pin"];
|
||||||
if (pinArr.size() == 0) continue;
|
if (pinArr.size() == 0) continue;
|
||||||
|
pins[0] = pinArr[0];
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
for (int p : pinArr) {
|
for (int p : pinArr) {
|
||||||
pins[i++] = p;
|
pins[i++] = p;
|
||||||
@ -129,7 +115,9 @@ void deserializeConfig() {
|
|||||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||||
// if ((bool)elm[F("rgbw")]) SET_BIT(ledType,7); else UNSET_BIT(ledType,7); // hack bit 7 to indicate RGBW (as an override if necessary)
|
// if ((bool)elm[F("rgbw")]) SET_BIT(ledType,7); else UNSET_BIT(ledType,7); // hack bit 7 to indicate RGBW (as an override if necessary)
|
||||||
// strip.isRgbw |= (bool)elm[F("rgbw")];
|
// strip.isRgbw |= (bool)elm[F("rgbw")];
|
||||||
strip.isRgbw = (strip.isRgbw || Bus::isRgbw(ledType));
|
strip.isRgbw = (strip.isRgbw || BusManager::isRgbw(ledType));
|
||||||
|
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||||
|
strip.isOffRefreshRequred |= BusManager::isOffRefreshRequred(ledType);
|
||||||
s++;
|
s++;
|
||||||
lC += length;
|
lC += length;
|
||||||
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst);
|
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst);
|
||||||
@ -138,44 +126,50 @@ void deserializeConfig() {
|
|||||||
DEBUG_PRINTLN(busses.getNumBusses());
|
DEBUG_PRINTLN(busses.getNumBusses());
|
||||||
if (mem <= MAX_LED_MEMORY && busses.getNumBusses() <= WLED_MAX_BUSSES) busses.add(bc); // finalization will be done in WLED::beginStrip()
|
if (mem <= MAX_LED_MEMORY && busses.getNumBusses() <= WLED_MAX_BUSSES) busses.add(bc); // finalization will be done in WLED::beginStrip()
|
||||||
}
|
}
|
||||||
|
//strip.finalizeInit();
|
||||||
|
}
|
||||||
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."));
|
||||||
|
|
||||||
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["pin"][0];
|
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 (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);
|
||||||
} else {
|
} else {
|
||||||
btnPin = -1;
|
btnPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
|
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
|
||||||
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]);
|
||||||
|
|
||||||
//int hw_btn_ins_0_type = hw_btn_ins_0["type"]; // 0
|
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
#ifndef WLED_DISABLE_INFRARED
|
||||||
int hw_ir_pin = hw["ir"]["pin"] | -1; // 4
|
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||||
|
if (hw_ir_pin > -2) {
|
||||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||||
irPin = hw_ir_pin;
|
irPin = hw_ir_pin;
|
||||||
} else {
|
} else {
|
||||||
irPin = -1;
|
irPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
CJSON(irEnabled, hw["ir"]["type"]);
|
CJSON(irEnabled, hw["ir"]["type"]);
|
||||||
|
|
||||||
JsonObject relay = hw[F("relay")];
|
JsonObject relay = hw[F("relay")];
|
||||||
int hw_relay_pin = relay["pin"] | -1;
|
int hw_relay_pin = relay["pin"] | -2;
|
||||||
if (hw_relay_pin>=0 && pinManager.allocatePin(hw_relay_pin,true)) {
|
if (hw_relay_pin > -2) {
|
||||||
|
if (pinManager.allocatePin(hw_relay_pin,true)) {
|
||||||
rlyPin = hw_relay_pin;
|
rlyPin = hw_relay_pin;
|
||||||
pinMode(rlyPin, OUTPUT);
|
pinMode(rlyPin, OUTPUT);
|
||||||
} else {
|
} else {
|
||||||
rlyPin = -1;
|
rlyPin = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (relay.containsKey("rev")) {
|
if (relay.containsKey("rev")) {
|
||||||
rlyMde = !relay["rev"];
|
rlyMde = !relay["rev"];
|
||||||
}
|
}
|
||||||
@ -202,8 +196,9 @@ void deserializeConfig() {
|
|||||||
|
|
||||||
JsonObject light_nl = light["nl"];
|
JsonObject light_nl = light["nl"];
|
||||||
CJSON(nightlightMode, light_nl[F("mode")]);
|
CJSON(nightlightMode, light_nl[F("mode")]);
|
||||||
CJSON(nightlightDelayMinsDefault, light_nl["dur"]);
|
byte prev = nightlightDelayMinsDefault;
|
||||||
nightlightDelayMins = nightlightDelayMinsDefault;
|
CJSON(nightlightDelayMinsDefault, light_nl[F("dur")]);
|
||||||
|
if (nightlightDelayMinsDefault != prev) nightlightDelayMins = nightlightDelayMinsDefault;
|
||||||
|
|
||||||
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
||||||
CJSON(macroNl, light_nl[F("macro")]);
|
CJSON(macroNl, light_nl[F("macro")]);
|
||||||
@ -231,12 +226,14 @@ void deserializeConfig() {
|
|||||||
JsonObject if_sync_recv = if_sync["recv"];
|
JsonObject if_sync_recv = if_sync["recv"];
|
||||||
CJSON(receiveNotificationBrightness, if_sync_recv["bri"]);
|
CJSON(receiveNotificationBrightness, if_sync_recv["bri"]);
|
||||||
CJSON(receiveNotificationColor, if_sync_recv["col"]);
|
CJSON(receiveNotificationColor, if_sync_recv["col"]);
|
||||||
CJSON(receiveNotificationEffects, if_sync_recv["fx"]);
|
CJSON(receiveNotificationEffects, if_sync_recv[F("fx")]);
|
||||||
|
//! following line might be a problem if called after boot
|
||||||
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||||
|
|
||||||
JsonObject if_sync_send = if_sync["send"];
|
JsonObject if_sync_send = if_sync["send"];
|
||||||
|
prev = notifyDirectDefault;
|
||||||
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
||||||
notifyDirect = notifyDirectDefault;
|
if (notifyDirectDefault != prev) notifyDirect = notifyDirectDefault;
|
||||||
CJSON(notifyButton, if_sync_send[F("btn")]);
|
CJSON(notifyButton, if_sync_send[F("btn")]);
|
||||||
CJSON(notifyAlexa, if_sync_send[F("va")]);
|
CJSON(notifyAlexa, if_sync_send[F("va")]);
|
||||||
CJSON(notifyHue, if_sync_send[F("hue")]);
|
CJSON(notifyHue, if_sync_send[F("hue")]);
|
||||||
@ -321,9 +318,10 @@ void deserializeConfig() {
|
|||||||
CJSON(latitude, if_ntp[F("lt")]);
|
CJSON(latitude, if_ntp[F("lt")]);
|
||||||
|
|
||||||
JsonObject ol = doc[F("ol")];
|
JsonObject ol = doc[F("ol")];
|
||||||
|
prev = overlayDefault;
|
||||||
CJSON(overlayDefault ,ol[F("clock")]); // 0
|
CJSON(overlayDefault ,ol[F("clock")]); // 0
|
||||||
CJSON(countdownMode, ol[F("cntdwn")]);
|
CJSON(countdownMode, ol[F("cntdwn")]);
|
||||||
overlayCurrent = overlayDefault;
|
if (prev != overlayDefault) overlayCurrent = overlayDefault;
|
||||||
|
|
||||||
CJSON(overlayMin, ol["min"]);
|
CJSON(overlayMin, ol["min"]);
|
||||||
CJSON(overlayMax, ol[F("max")]);
|
CJSON(overlayMax, ol[F("max")]);
|
||||||
@ -398,7 +396,32 @@ void deserializeConfig() {
|
|||||||
|
|
||||||
DEBUG_PRINTLN(F("Starting usermod config."));
|
DEBUG_PRINTLN(F("Starting usermod config."));
|
||||||
JsonObject usermods_settings = doc["um"];
|
JsonObject usermods_settings = doc["um"];
|
||||||
usermods.readFromConfig(usermods_settings);
|
if (!usermods_settings.isNull()) usermods.readFromConfig(usermods_settings);
|
||||||
|
|
||||||
|
if (fromFS) return false;
|
||||||
|
doReboot = doc[F("rb")] | doReboot;
|
||||||
|
return (doc["sv"] | true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserializeConfigFromFS() {
|
||||||
|
bool fromeep = false;
|
||||||
|
bool success = deserializeConfigSec();
|
||||||
|
if (!success) { //if file does not exist, try reading from EEPROM
|
||||||
|
deEEPSettings();
|
||||||
|
fromeep = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
DEBUG_PRINTLN(F("Reading settings from /cfg.json..."));
|
||||||
|
|
||||||
|
success = readObjectFromFile("/cfg.json", nullptr, &doc);
|
||||||
|
if (!success) { //if file does not exist, try reading from EEPROM
|
||||||
|
if (!fromeep) deEEPSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializeConfig(doc.as<JsonObject>(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeConfig() {
|
void serializeConfig() {
|
||||||
@ -481,7 +504,7 @@ void serializeConfig() {
|
|||||||
for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]);
|
for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]);
|
||||||
ins[F("order")] = bus->getColorOrder();
|
ins[F("order")] = bus->getColorOrder();
|
||||||
ins["rev"] = bus->reversed;
|
ins["rev"] = bus->reversed;
|
||||||
ins[F("skip")] = bus->skipFirstLed();
|
ins[F("skip")] = bus->skippedLeds();
|
||||||
ins["type"] = bus->getType();
|
ins["type"] = bus->getType();
|
||||||
ins[F("rgbw")] = bus->isRgbw();
|
ins[F("rgbw")] = bus->isRgbw();
|
||||||
}
|
}
|
||||||
|
@ -10,18 +10,18 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
html {
|
html {
|
||||||
--h: 10.55vh;
|
--h: 10.2vh;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
background: #333;
|
background: #333;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: Verdana, Helvetica, sans-serif;
|
font-family: Verdana, Helvetica, sans-serif;
|
||||||
border: 0.3ch solid #333;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
border: 1px solid #333;
|
||||||
font-size: 6vmin;
|
font-size: 6vmin;
|
||||||
height: var(--h);
|
height: var(--h);
|
||||||
width: 95%;
|
width: 95%;
|
||||||
margin-top: 2.4vh;
|
margin-top: 2vh;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
@ -181,9 +181,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function GetV()
|
function GetV(){var d=document;}
|
||||||
{
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
@import url("style.css");
|
@import url("style.css");
|
||||||
|
@ -3,14 +3,15 @@
|
|||||||
<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">
|
||||||
<title>UI 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 = [6,7,8,9,10,11];
|
||||||
var pinO = ["reserved","reserved","reserved","reserved","reserved","reserved"], 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;
|
||||||
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"); }
|
||||||
@ -24,7 +25,9 @@
|
|||||||
localStorage.setItem('locIp', locip);
|
localStorage.setItem('locIp', locip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ldS();
|
GetV();
|
||||||
|
if (numM > 0 || locip) ldS();
|
||||||
|
else gId("um").innerHTML = "No Usermods installed.";
|
||||||
}
|
}
|
||||||
function check(o,k) {
|
function check(o,k) {
|
||||||
var n = o.name.replace("[]","").substr(-3);
|
var n = o.name.replace("[]","").substr(-3);
|
||||||
@ -99,11 +102,8 @@
|
|||||||
urows += `<hr><h3>${k}</h3>`;
|
urows += `<hr><h3>${k}</h3>`;
|
||||||
addField(k,'unknown',o);
|
addField(k,'unknown',o);
|
||||||
}
|
}
|
||||||
if (urows==="")
|
|
||||||
urows = "No Usermods configuration found.<br>Press <i>Save</i> to initialize defaults if usermods were compiled in.";
|
|
||||||
} else {
|
|
||||||
urows = "Usermods configuration not found.<br>Most likely no Usermods exist.<br>Press <i>Save</i> to try 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;
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
Installed version: ##VERSION##<br>
|
Installed version: ##VERSION##<br>
|
||||||
Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases" target="_blank">
|
Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases" target="_blank">
|
||||||
<img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br>
|
<img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br>
|
||||||
<input type='file' class="bt" name='update' accept=".bin" required><br>
|
<input type='file' class="bt" name='update' required><br> <!--should have accept='.bin', but it prevents file upload from android app-->
|
||||||
<input type='submit' class="bt" value='Update!' ><br>
|
<input type='submit' class="bt" value='Update!' ><br>
|
||||||
<button type="button" class="bt" onclick="B()">Back</button></form>
|
<button type="button" class="bt" onclick="B()">Back</button></form>
|
||||||
<div id="msg"><b>Updating...</b><br>Please do not close or refresh the page :)</div>
|
<div id="msg"><b>Updating...</b><br>Please do not close or refresh the page :)</div>
|
||||||
|
@ -26,7 +26,8 @@ void handleButton();
|
|||||||
void handleIO();
|
void handleIO();
|
||||||
|
|
||||||
//cfg.cpp
|
//cfg.cpp
|
||||||
void deserializeConfig();
|
bool deserializeConfig(JsonObject doc, bool fromFS = false);
|
||||||
|
void deserializeConfigFromFS();
|
||||||
bool deserializeConfigSec();
|
bool deserializeConfigSec();
|
||||||
void serializeConfig();
|
void serializeConfig();
|
||||||
void serializeConfigSec();
|
void serializeConfigSec();
|
||||||
|
@ -55,13 +55,12 @@ bool bufferedFind(const char *target, bool fromStart = true) {
|
|||||||
size_t targetLen = strlen(target);
|
size_t targetLen = strlen(target);
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
uint16_t bufsize = 0, count = 0;
|
|
||||||
byte buf[FS_BUFSIZE];
|
byte buf[FS_BUFSIZE];
|
||||||
if (fromStart) f.seek(0);
|
if (fromStart) f.seek(0);
|
||||||
|
|
||||||
while (f.position() < f.size() -1) {
|
while (f.position() < f.size() -1) {
|
||||||
bufsize = f.read(buf, FS_BUFSIZE);
|
uint16_t bufsize = f.read(buf, FS_BUFSIZE);
|
||||||
count = 0;
|
uint16_t count = 0;
|
||||||
while (count < bufsize) {
|
while (count < bufsize) {
|
||||||
if(buf[count] != target[index])
|
if(buf[count] != target[index])
|
||||||
index = 0; // reset index if any char does not match
|
index = 0; // reset index if any char does not match
|
||||||
@ -97,13 +96,12 @@ bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) {
|
|||||||
if (!f || !f.size()) return false;
|
if (!f || !f.size()) return false;
|
||||||
|
|
||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
uint16_t bufsize = 0, count = 0;
|
|
||||||
byte buf[FS_BUFSIZE];
|
byte buf[FS_BUFSIZE];
|
||||||
if (fromStart) f.seek(0);
|
if (fromStart) f.seek(0);
|
||||||
|
|
||||||
while (f.position() < f.size() -1) {
|
while (f.position() < f.size() -1) {
|
||||||
bufsize = f.read(buf, FS_BUFSIZE);
|
uint16_t bufsize = f.read(buf, FS_BUFSIZE);
|
||||||
count = 0;
|
uint16_t count = 0;
|
||||||
|
|
||||||
while (count < bufsize) {
|
while (count < bufsize) {
|
||||||
if(buf[count] == ' ') {
|
if(buf[count] == ' ') {
|
||||||
@ -140,13 +138,12 @@ bool bufferedFindObjectEnd() {
|
|||||||
if (!f || !f.size()) return false;
|
if (!f || !f.size()) return false;
|
||||||
|
|
||||||
uint16_t objDepth = 0; //num of '{' minus num of '}'. return once 0
|
uint16_t objDepth = 0; //num of '{' minus num of '}'. return once 0
|
||||||
uint16_t bufsize = 0, count = 0;
|
|
||||||
//size_t start = f.position();
|
//size_t start = f.position();
|
||||||
byte buf[FS_BUFSIZE];
|
byte buf[FS_BUFSIZE];
|
||||||
|
|
||||||
while (f.position() < f.size() -1) {
|
while (f.position() < f.size() -1) {
|
||||||
bufsize = f.read(buf, FS_BUFSIZE);
|
uint16_t bufsize = f.read(buf, FS_BUFSIZE);
|
||||||
count = 0;
|
uint16_t count = 0;
|
||||||
|
|
||||||
while (count < bufsize) {
|
while (count < bufsize) {
|
||||||
if (buf[count] == '{') objDepth++;
|
if (buf[count] == '{') objDepth++;
|
||||||
|
@ -45,10 +45,10 @@ action="/update" id="uf" enctype="multipart/form-data" onsubmit="U()">
|
|||||||
Installed version: 0.12.2-bl3<br>Download the latest binary: <a
|
Installed version: 0.12.2-bl3<br>Download the latest binary: <a
|
||||||
href="https://github.com/Aircoookie/WLED/releases" target="_blank"><img
|
href="https://github.com/Aircoookie/WLED/releases" target="_blank"><img
|
||||||
src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square">
|
src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square">
|
||||||
</a><br><input type="file" class="bt" name="update" accept=".bin" required><br>
|
</a><br><input type="file" class="bt" name="update" required><br><input
|
||||||
<input type="submit" class="bt" value="Update!"><br><button type="button"
|
type="submit" class="bt" value="Update!"><br><button type="button" class="bt"
|
||||||
class="bt" onclick="B()">Back</button></form><div id="msg"><b>Updating...</b>
|
onclick="B()">Back</button></form><div id="msg"><b>Updating...</b><br>
|
||||||
<br>Please do not close or refresh the page :)</div></body></html>)=====";
|
Please do not close or refresh the page :)</div></body></html>)=====";
|
||||||
|
|
||||||
|
|
||||||
// Autogenerated from wled00/data/welcome.htm, do not edit!!
|
// Autogenerated from wled00/data/welcome.htm, do not edit!!
|
||||||
|
@ -12,7 +12,7 @@ const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,
|
|||||||
// Autogenerated from wled00/data/settings.htm, do not edit!!
|
// Autogenerated from wled00/data/settings.htm, do not edit!!
|
||||||
const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>WLED Settings
|
const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>WLED Settings
|
||||||
</title><style>
|
</title><style>
|
||||||
body{text-align:center;background:#222;height:100px;margin:0}html{--h:10.55vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:.3ch solid #333;display:inline-block;font-size:6vmin;height:var(--h);width:95%%;margin-top:2.4vh}
|
body{text-align:center;background:#222;height:100px;margin:0}html{--h:10.2vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;display:inline-block;border:1px solid #333;font-size:6vmin;height:var(--h);width:95%%;margin-top:2vh}
|
||||||
</style><script>
|
</style><script>
|
||||||
function BB(){window.frameElement&&(document.getElementById("b").style.display="none",document.documentElement.style.setProperty("--h","13.86vh"))}
|
function BB(){window.frameElement&&(document.getElementById("b").style.display="none",document.documentElement.style.setProperty("--h","13.86vh"))}
|
||||||
</script></head><body onload="BB()"><form action="/"><button type="submit"
|
</script></head><body onload="BB()"><form action="/"><button type="submit"
|
||||||
@ -395,9 +395,9 @@ 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>UI 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=["reserved","reserved","reserved","reserved","reserved","reserved"],loc=!1;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))),ldS()}function check(e,o){var i=e.name.replace("[]","").substr(-3);if("number"==e.type&&"pin"==i.substr(0,3))for(var n=0;n<pins.length;n++)if(o!=pinO[n]){if(e.value==pins[n]||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,n]of Object.entries(e))if(isO(n))owner=i,getPins(n);else if("pin"==i.replace("[]","").substr(-3))if(Array.isArray(n))for(var o=0;o<n.length;o++)n[o]>=0&&(pins.push(n[o]),pinO.push(owner));else n>=0&&(pins.push(n),pinO.push(owner));else if(Array.isArray(n))for(o=0;o<n.length;o++)getPins(n[o])}function addField(e,o,i,n=!1){if(isO(i))for(const[o,n]of Object.entries(i))addField(e,o,n);else if(Array.isArray(i))for(var r=0;r<i.length;r++)addField(e,o,i[r],!0);else{var s,t;switch(typeof i){case"boolean":s="checkbox",t=i?'checked value="on"':"";break;case"number":s="number",t=`value="${parseInt(i,10)}"`;break;case"string":default:s="text",t=`value="${i}"`}"checkbox"==s&&(urows+=`<input type="hidden" name="${e}_${o}${n?"[]":""}" value="off">`),urows+=`${o}: <input type="${s}" name="${e}_${o}${n?"[]":""}" ${t} 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,o]of Object.entries(umCfg))urows+=`<hr><h3>${e}</h3>`,addField(e,"unknown",o);""===urows&&(urows="No Usermods configuration found.<br>Press <i>Save</i> to initialize defaults if usermods were compiled in.")}else urows="Usermods configuration not found.<br>Most likely no Usermods exist.<br>Press <i>Save</i> to try 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 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;
|
||||||
</script>%CSS%%SCSS%</head><body onload="S()"><form
|
%CSS%%SCSS%</head><body onload="S()"><form
|
||||||
id="form_s" name="Sf" method="post" onsubmit="svS(event)"><div class="toprow">
|
id="form_s" name="Sf" method="post" onsubmit="svS(event)"><div class="toprow">
|
||||||
<div class="helpB"><button type="button" onclick="H()">?</button></div><button
|
<div class="helpB"><button type="button" onclick="H()">?</button></div><button
|
||||||
type="button" onclick="B()">Back</button><button type="submit">Save</button><br>
|
type="button" onclick="B()">Back</button><button type="submit">Save</button><br>
|
||||||
|
@ -227,7 +227,7 @@ void decodeIR24(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_BRIGHTER : incBrightness(); break;
|
case IR24_BRIGHTER : incBrightness(); break;
|
||||||
case IR24_DARKER : decBrightness(); break;
|
case IR24_DARKER : decBrightness(); break;
|
||||||
case IR24_OFF : briLast = bri; bri = 0; break;
|
case IR24_OFF : if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR24_ON : bri = briLast; break;
|
case IR24_ON : bri = briLast; break;
|
||||||
case IR24_RED : colorFromUint32(COLOR_RED); break;
|
case IR24_RED : colorFromUint32(COLOR_RED); break;
|
||||||
case IR24_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
case IR24_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||||
@ -259,7 +259,7 @@ void decodeIR24OLD(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_OLD_BRIGHTER : incBrightness(); break;
|
case IR24_OLD_BRIGHTER : incBrightness(); break;
|
||||||
case IR24_OLD_DARKER : decBrightness(); break;
|
case IR24_OLD_DARKER : decBrightness(); break;
|
||||||
case IR24_OLD_OFF : briLast = bri; bri = 0; break;
|
case IR24_OLD_OFF : if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR24_OLD_ON : bri = briLast; break;
|
case IR24_OLD_ON : bri = briLast; break;
|
||||||
case IR24_OLD_RED : colorFromUint32(COLOR_RED); break;
|
case IR24_OLD_RED : colorFromUint32(COLOR_RED); break;
|
||||||
case IR24_OLD_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
case IR24_OLD_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||||
@ -292,7 +292,7 @@ void decodeIR24CT(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_CT_BRIGHTER : incBrightness(); break;
|
case IR24_CT_BRIGHTER : incBrightness(); break;
|
||||||
case IR24_CT_DARKER : decBrightness(); break;
|
case IR24_CT_DARKER : decBrightness(); break;
|
||||||
case IR24_CT_OFF : briLast = bri; bri = 0; break;
|
case IR24_CT_OFF : if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR24_CT_ON : bri = briLast; break;
|
case IR24_CT_ON : bri = briLast; break;
|
||||||
case IR24_CT_RED : colorFromUint32(COLOR_RED); break;
|
case IR24_CT_RED : colorFromUint32(COLOR_RED); break;
|
||||||
case IR24_CT_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
case IR24_CT_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||||
@ -327,7 +327,7 @@ void decodeIR40(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR40_BPLUS : incBrightness(); break;
|
case IR40_BPLUS : incBrightness(); break;
|
||||||
case IR40_BMINUS : decBrightness(); break;
|
case IR40_BMINUS : decBrightness(); break;
|
||||||
case IR40_OFF : briLast = bri; bri = 0; break;
|
case IR40_OFF : if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR40_ON : bri = briLast; break;
|
case IR40_ON : bri = briLast; break;
|
||||||
case IR40_RED : colorFromUint24(COLOR_RED); break;
|
case IR40_RED : colorFromUint24(COLOR_RED); break;
|
||||||
case IR40_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
case IR40_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
||||||
@ -384,7 +384,7 @@ void decodeIR44(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR44_BPLUS : incBrightness(); break;
|
case IR44_BPLUS : incBrightness(); break;
|
||||||
case IR44_BMINUS : decBrightness(); break;
|
case IR44_BMINUS : decBrightness(); break;
|
||||||
case IR44_OFF : briLast = bri; bri = 0; break;
|
case IR44_OFF : if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR44_ON : bri = briLast; break;
|
case IR44_ON : bri = briLast; break;
|
||||||
case IR44_RED : colorFromUint24(COLOR_RED); break;
|
case IR44_RED : colorFromUint24(COLOR_RED); break;
|
||||||
case IR44_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
case IR44_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
||||||
@ -447,7 +447,7 @@ void decodeIR21(uint32_t code)
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case IR21_BRIGHTER: incBrightness(); break;
|
case IR21_BRIGHTER: incBrightness(); break;
|
||||||
case IR21_DARKER: decBrightness(); break;
|
case IR21_DARKER: decBrightness(); break;
|
||||||
case IR21_OFF: briLast = bri; bri = 0; break;
|
case IR21_OFF: if (bri > 0) briLast = bri; bri = 0; break;
|
||||||
case IR21_ON: bri = briLast; break;
|
case IR21_ON: bri = briLast; break;
|
||||||
case IR21_RED: colorFromUint32(COLOR_RED); break;
|
case IR21_RED: colorFromUint32(COLOR_RED); break;
|
||||||
case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break;
|
case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break;
|
||||||
|
@ -166,7 +166,7 @@ void deserializeSegment(JsonObject elem, byte it)
|
|||||||
if (icol.isNull()) break;
|
if (icol.isNull()) break;
|
||||||
|
|
||||||
byte sz = icol.size();
|
byte sz = icol.size();
|
||||||
if (sz == 0 && sz > 4) break;
|
if (sz == 0 || sz > 4) break;
|
||||||
|
|
||||||
int rgbw[] = {0,0,0,0};
|
int rgbw[] = {0,0,0,0};
|
||||||
copyArray(icol, rgbw);
|
copyArray(icol, rgbw);
|
||||||
@ -198,6 +198,8 @@ bool deserializeState(JsonObject root)
|
|||||||
bool on = root["on"] | (bri > 0);
|
bool on = root["on"] | (bri > 0);
|
||||||
if (!on != !bri) toggleOnOff();
|
if (!on != !bri) toggleOnOff();
|
||||||
|
|
||||||
|
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||||
|
|
||||||
int tr = root[F("transition")] | -1;
|
int tr = root[F("transition")] | -1;
|
||||||
if (tr >= 0)
|
if (tr >= 0)
|
||||||
{
|
{
|
||||||
@ -813,6 +815,9 @@ void serveJson(AsyncWebServerRequest* request, uint8_t versionAPI)
|
|||||||
request->send_P(200, "application/json", JSON_palette_names);
|
request->send_P(200, "application/json", JSON_palette_names);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (url.indexOf("cfg") > 0 && handleFileRead(request, "/cfg.json")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (url.length() > 6) { //not just /json
|
else if (url.length() > 6) { //not just /json
|
||||||
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||||
return;
|
return;
|
||||||
|
@ -52,23 +52,22 @@ void onMqttConnect(bool sessionPresent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onMqttMessage(char* topic, char* payload0, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||||
|
|
||||||
DEBUG_PRINT(F("MQTT msg: "));
|
DEBUG_PRINT(F("MQTT msg: "));
|
||||||
DEBUG_PRINTLN(topic);
|
DEBUG_PRINTLN(topic);
|
||||||
|
|
||||||
// paranoia check to avoid npe if no payload
|
// paranoia check to avoid npe if no payload
|
||||||
if (payload0==nullptr) {
|
if (payload==nullptr) {
|
||||||
DEBUG_PRINTLN(F("no payload -> leave"));
|
DEBUG_PRINTLN(F("no payload -> leave"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//make a copy of the payload to 0-terminate it
|
||||||
// payload is not always null terminated
|
char* payloadStr = new char[len+1];
|
||||||
char *payload = new char[len+1];
|
if (payloadStr == nullptr) return; //no mem
|
||||||
if (payload==nullptr) return; // out of memory
|
strncpy(payloadStr, payload, len);
|
||||||
strncpy(payload,payload0,len);
|
payloadStr[len] = '\0';
|
||||||
payload[len] = '\0';
|
DEBUG_PRINTLN(payloadStr);
|
||||||
DEBUG_PRINTLN(payload);
|
|
||||||
|
|
||||||
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
||||||
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
||||||
@ -79,8 +78,8 @@ void onMqttMessage(char* topic, char* payload0, AsyncMqttClientMessageProperties
|
|||||||
topic += topicPrefixLen;
|
topic += topicPrefixLen;
|
||||||
} else {
|
} else {
|
||||||
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
||||||
usermods.onMqttMessage(topic, payload);
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
delete[] payload;
|
delete[] payloadStr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,26 +87,26 @@ void onMqttMessage(char* topic, char* payload0, AsyncMqttClientMessageProperties
|
|||||||
//Prefix is stripped from the topic at this point
|
//Prefix is stripped from the topic at this point
|
||||||
|
|
||||||
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
||||||
colorFromDecOrHexString(col, payload);
|
colorFromDecOrHexString(col, (char*)payloadStr);
|
||||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||||
if (payload[0] == '{') { //JSON API
|
if (payload[0] == '{') { //JSON API
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
deserializeJson(doc, payload);
|
deserializeJson(doc, payloadStr);
|
||||||
deserializeState(doc.as<JsonObject>());
|
deserializeState(doc.as<JsonObject>());
|
||||||
} else { //HTTP API
|
} else { //HTTP API
|
||||||
String apireq = "win&";
|
String apireq = "win&";
|
||||||
apireq += payload;
|
apireq += (char*)payloadStr;
|
||||||
handleSet(nullptr, apireq);
|
handleSet(nullptr, apireq);
|
||||||
}
|
}
|
||||||
} else if (strlen(topic) != 0) {
|
} else if (strlen(topic) != 0) {
|
||||||
// non standard topic, check with usermods
|
// non standard topic, check with usermods
|
||||||
usermods.onMqttMessage(topic, payload);
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
} else {
|
} else {
|
||||||
// topmost topic (just wled/MAC)
|
// topmost topic (just wled/MAC)
|
||||||
parseMQTTBriPayload(payload);
|
parseMQTTBriPayload(payloadStr);
|
||||||
}
|
}
|
||||||
delete[] payload;
|
delete[] payloadStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,7 +131,7 @@ void publishMqtt()
|
|||||||
|
|
||||||
strcpy(subuf, mqttDeviceTopic);
|
strcpy(subuf, mqttDeviceTopic);
|
||||||
strcat_P(subuf, PSTR("/status"));
|
strcat_P(subuf, PSTR("/status"));
|
||||||
mqtt->publish(subuf, 0, true, "online"); // do not retain message
|
mqtt->publish(subuf, 0, false, "online"); // do not retain message
|
||||||
|
|
||||||
char apires[1024];
|
char apires[1024];
|
||||||
XML_response(nullptr, apires);
|
XML_response(nullptr, apires);
|
||||||
|
@ -112,7 +112,7 @@ void updateTimezone() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TZ_AUSTRALIA_NORTHERN : {
|
case TZ_AUSTRALIA_NORTHERN : {
|
||||||
tcrStandard = {First, Sun, Apr, 3, 570}; //ACST = UTC + 9.5 hours
|
tcrDaylight = {First, Sun, Apr, 3, 570}; //ACST = UTC + 9.5 hours
|
||||||
tcrStandard = tcrDaylight;
|
tcrStandard = tcrDaylight;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,9 @@ void _overlayAnalogClock()
|
|||||||
}
|
}
|
||||||
if (analogClock5MinuteMarks)
|
if (analogClock5MinuteMarks)
|
||||||
{
|
{
|
||||||
int pix;
|
for (byte i = 0; i <= 12; i++)
|
||||||
for (int i = 0; i <= 12; i++)
|
|
||||||
{
|
{
|
||||||
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
int pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
||||||
if (pix > overlayMax) pix -= overlaySize;
|
if (pix > overlayMax) pix -= overlaySize;
|
||||||
strip.setPixelColor(pix, 0x00FFAA);
|
strip.setPixelColor(pix, 0x00FFAA);
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,14 @@ uint16_t playlistEntryDur = 0;
|
|||||||
|
|
||||||
|
|
||||||
void shufflePlaylist() {
|
void shufflePlaylist() {
|
||||||
int currentIndex = playlistLen, randomIndex;
|
int currentIndex = playlistLen;
|
||||||
|
|
||||||
PlaylistEntry temporaryValue, *entries = reinterpret_cast<PlaylistEntry*>(playlistEntries);
|
PlaylistEntry temporaryValue, *entries = reinterpret_cast<PlaylistEntry*>(playlistEntries);
|
||||||
|
|
||||||
// While there remain elements to shuffle...
|
// While there remain elements to shuffle...
|
||||||
while (currentIndex--) {
|
while (currentIndex--) {
|
||||||
// Pick a random element...
|
// Pick a random element...
|
||||||
randomIndex = random(0, currentIndex);
|
int randomIndex = random(0, currentIndex);
|
||||||
// And swap it with the current element.
|
// And swap it with the current element.
|
||||||
temporaryValue = entries[currentIndex];
|
temporaryValue = entries[currentIndex];
|
||||||
entries[currentIndex] = entries[randomIndex];
|
entries[currentIndex] = entries[randomIndex];
|
||||||
|
@ -31,7 +31,7 @@ bool isAsterisksOnly(const char* str, byte maxLen)
|
|||||||
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||||
{
|
{
|
||||||
|
|
||||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX
|
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods
|
||||||
if (subPage <1 || subPage >8) return;
|
if (subPage <1 || subPage >8) return;
|
||||||
|
|
||||||
//WIFI SETTINGS
|
//WIFI SETTINGS
|
||||||
@ -84,7 +84,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin);
|
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin);
|
||||||
|
|
||||||
strip.isRgbw = false;
|
strip.isRgbw = false;
|
||||||
|
|
||||||
uint8_t colorOrder, type, skip;
|
uint8_t colorOrder, type, skip;
|
||||||
uint16_t length, start;
|
uint16_t length, start;
|
||||||
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -220,7 +220,7 @@ void WLED::loop()
|
|||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
if (!offMode)
|
if (!offMode || strip.isOffRefreshRequred)
|
||||||
strip.service();
|
strip.service();
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
else if (!noWifiSleep)
|
else if (!noWifiSleep)
|
||||||
@ -370,7 +370,7 @@ void WLED::setup()
|
|||||||
updateFSInfo();
|
updateFSInfo();
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading config"));
|
DEBUG_PRINTLN(F("Reading config"));
|
||||||
deserializeConfig();
|
deserializeConfigFromFS();
|
||||||
/*
|
/*
|
||||||
#if STATUSLED
|
#if STATUSLED
|
||||||
bool lStatusLed = false;
|
bool lStatusLed = false;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2105161
|
#define VERSION 2105171
|
||||||
|
|
||||||
//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
|
||||||
|
@ -321,7 +321,7 @@ void loadSettingsFromEEPROM()
|
|||||||
notifyMacro = EEPROM.read(2201);
|
notifyMacro = EEPROM.read(2201);
|
||||||
|
|
||||||
strip.rgbwMode = EEPROM.read(2203);
|
strip.rgbwMode = EEPROM.read(2203);
|
||||||
//was skipFirstLed = EEPROM.read(2204);
|
//skipFirstLed = EEPROM.read(2204);
|
||||||
|
|
||||||
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
|
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
|
||||||
{
|
{
|
||||||
|
@ -85,6 +85,7 @@ void initServer()
|
|||||||
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
|
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
|
||||||
bool verboseResponse = false;
|
bool verboseResponse = false;
|
||||||
uint8_t vAPI = 1;
|
uint8_t vAPI = 1;
|
||||||
|
bool isConfig = false;
|
||||||
{ //scope JsonDocument so it releases its buffer
|
{ //scope JsonDocument so it releases its buffer
|
||||||
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
|
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
|
||||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
|
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
|
||||||
@ -92,6 +93,9 @@ void initServer()
|
|||||||
if (error || root.isNull()) {
|
if (error || root.isNull()) {
|
||||||
request->send(400, "application/json", F("{\"error\":9}")); return;
|
request->send(400, "application/json", F("{\"error\":9}")); return;
|
||||||
}
|
}
|
||||||
|
const String& url = request->url();
|
||||||
|
isConfig = url.indexOf("cfg") > -1;
|
||||||
|
if (!isConfig) {
|
||||||
if (root.containsKey("rev"))
|
if (root.containsKey("rev"))
|
||||||
{
|
{
|
||||||
vAPI = root["rev"] | 1;
|
vAPI = root["rev"] | 1;
|
||||||
@ -99,9 +103,16 @@ void initServer()
|
|||||||
fileDoc = &jsonBuffer; // used for applying presets (presets.cpp)
|
fileDoc = &jsonBuffer; // used for applying presets (presets.cpp)
|
||||||
verboseResponse = deserializeState(root);
|
verboseResponse = deserializeState(root);
|
||||||
fileDoc = nullptr;
|
fileDoc = nullptr;
|
||||||
|
} else {
|
||||||
|
verboseResponse = deserializeConfig(root); //use verboseResponse to determine whether cfg change should be saved immediately
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verboseResponse) {
|
||||||
|
if (!isConfig) {
|
||||||
|
serveJson(request,vAPI); return; //if JSON contains "v"
|
||||||
|
} else {
|
||||||
|
serializeConfig(); //Save new settings to FS
|
||||||
}
|
}
|
||||||
if (verboseResponse) { //if JSON contains "v"
|
|
||||||
serveJson(request,vAPI); return;
|
|
||||||
}
|
}
|
||||||
request->send(200, "application/json", F("{\"success\":true}"));
|
request->send(200, "application/json", F("{\"success\":true}"));
|
||||||
});
|
});
|
||||||
|
@ -185,7 +185,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
obuf = dest;
|
obuf = dest;
|
||||||
olen = 0;
|
olen = 0;
|
||||||
|
|
||||||
if (subPage <1 || subPage >7) return;
|
if (subPage <1 || subPage >8) return;
|
||||||
|
|
||||||
if (subPage == 1)
|
if (subPage == 1)
|
||||||
{
|
{
|
||||||
@ -361,7 +361,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('v',co,bus->getColorOrder());
|
sappend('v',co,bus->getColorOrder());
|
||||||
sappend('v',ls,bus->getStart());
|
sappend('v',ls,bus->getStart());
|
||||||
sappend('c',cv,bus->reversed);
|
sappend('c',cv,bus->reversed);
|
||||||
sappend('c',sl,bus->skipFirstLed());
|
sappend('c',sl,bus->skippedLeds());
|
||||||
// sappend('c',ew,bus->isRgbw());
|
// sappend('c',ew,bus->isRgbw());
|
||||||
}
|
}
|
||||||
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
||||||
@ -579,5 +579,13 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('i',SET_F("CH15"),DMXFixtureMap[14]);
|
sappend('i',SET_F("CH15"),DMXFixtureMap[14]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (subPage == 8) //usermods
|
||||||
|
{
|
||||||
|
oappend(SET_F("numM="));
|
||||||
|
oappendi(usermods.getModCount());
|
||||||
|
oappend(";");
|
||||||
|
}
|
||||||
|
|
||||||
oappend(SET_F("}</script>"));
|
oappend(SET_F("}</script>"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user