Merge remote-tracking branch 'origin/ac_main' into mdev

This commit is contained in:
Ewoud
2022-12-06 14:38:49 +01:00
29 changed files with 5225 additions and 4981 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -104,7 +104,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(strip.matrix.bottomStart, matrix[F("pb")]);
CJSON(strip.matrix.rightStart, matrix[F("pr")]);
CJSON(strip.matrix.vertical, matrix[F("pv")]);
CJSON(strip.matrix.serpentine, matrix[F("ps")]);
CJSON(strip.matrix.serpentine, matrix["ps"]);
JsonArray panels = matrix[F("panels")];
uint8_t s = 0;
@@ -192,6 +192,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
// read multiple button configuration
JsonObject btn_obj = hw["btn"];
int pull = -1; // trick for inverted setting
CJSON(pull, btn_obj[F("pull")]);
if (pull>=0) disablePullUp = pull;
JsonArray hw_btn_ins = btn_obj[F("ins")];
if (!hw_btn_ins.isNull()) {
uint8_t s = 0;
@@ -200,11 +203,15 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
int8_t pin = btn["pin"][0] | -1;
if (pin > -1 && pinManager.allocatePin(pin, false, PinOwner::Button)) {
btnPin[s] = pin;
#ifdef ESP32
pinMode(btnPin[s], buttonType[s]==BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP);
#else
pinMode(btnPin[s], INPUT_PULLUP);
#endif
if (disablePullUp) {
pinMode(btnPin[s], INPUT);
} else {
#ifdef ESP32
pinMode(btnPin[s], buttonType[s]==BTN_TYPE_PUSH_ACT_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP);
#else
pinMode(btnPin[s], INPUT_PULLUP);
#endif
}
} else {
btnPin[s] = -1;
}
@@ -687,7 +694,7 @@ void serializeConfig() {
matrix[F("pb")] = strip.matrix.bottomStart;
matrix[F("pr")] = strip.matrix.rightStart;
matrix[F("pv")] = strip.matrix.vertical;
matrix[F("ps")] = strip.matrix.serpentine;
matrix["ps"] = strip.matrix.serpentine;
JsonArray panels = matrix.createNestedArray(F("panels"));
for (uint8_t i=0; i<strip.hPanels*strip.vPanels; i++) {
@@ -735,6 +742,7 @@ void serializeConfig() {
// button(s)
JsonObject hw_btn = hw.createNestedObject("btn");
hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used)
hw_btn[F("pull")] = !disablePullUp;
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
// configuration for all buttons

View File

@@ -98,10 +98,11 @@
#define USERMOD_ID_PING_PONG_CLOCK 34 //Usermod "usermod_v2_ping_pong_clock.h"
#define USERMOD_ID_ADS1115 35 //Usermod "usermod_ads1115.h"
#define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h"
#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h
//WLEDMM
#define USERMOD_ID_CUSTOMEFFECTS 38 //Usermod "usermod_v2_customeffects.h"
#define USERMOD_ID_WEATHER 39 //Usermod "usermod_v2_weather.h"
#define USERMOD_ID_GAMES 40 //Usermod "usermod_v2_games.h"
#define USERMOD_ID_CUSTOMEFFECTS 39 //Usermod "usermod_v2_customeffects.h"
#define USERMOD_ID_WEATHER 40 //Usermod "usermod_v2_weather.h"
#define USERMOD_ID_GAMES 41 //Usermod "usermod_v2_games.h"
//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot

View File

@@ -17,6 +17,7 @@ var d = document;
var palettesData;
var fxdata = [];
var pJson = {}, eJson = {}, lJson = {};
var plJson = {}; // array of playlists
var pN = "", pI = 0, pNum = 0;
var pmt = 1, pmtLS = 0, pmtLast = 0;
var lastinfo = {};
@@ -522,7 +523,7 @@ function loadFXData(callback = null)
fxdata = json||[];
// add default value for Solid
fxdata.shift()
fxdata.unshift(";!;0");
fxdata.unshift(";!;");
})
.catch((e)=>{
fxdata = [];
@@ -871,18 +872,19 @@ function populateEffects()
let fd = "";
if (ef.name.indexOf("RSVD") < 0) {
if (Array.isArray(fxdata) && fxdata.length>id) {
if (fxdata[id].length==0) fd = ";;!;1d"
if (fxdata[id].length==0) fd = ";;!;1"
else fd = fxdata[id];
let eP = (fd == '')?[]:fd.split(";"); // effect parameters
let p = (eP.length<3 || eP[2]==='')?[]:eP[2].split(","); // palette data
if (p.length>0 && (p[0] !== "" && !isNumeric(p[0]))) nm += "&#x1F3A8;"; // effects using palette
let m = (eP.length<4 || eP[3]==='')?[]:eP[3].split(","); // metadata
if (m.length>0) for (let r of m) {
if (r.substring(0,2)=="1d") nm += "&#8942;"; // 1D effects
if (r.substring(0,4)=="1.5d") nm += "&#8942;&#8942;"; // 1D effects + vStrips
if (r.substring(0,2)=="2d") nm += "&#9638;"; // 2D effects
if (r.substring(0,2)=="vo") nm += "&#9834;"; // volume effects
if (r.substring(0,2)=="fr") nm += "&#9835;"; // frequency effects
let m = (eP.length<4 || eP[3]==='')?'1':eP[3]; // flags
if (id == 0) m = ''; // solid has no flags
if (m.length>0) {
if (m.includes('1')) nm += "&#8942;"; // 1D effects
if (m.includes("1.5d")) nm += "&#8942;"; // WLEDMM: vStrips
if (m.includes('2')) nm += "&#9638;"; // 2D effects
if (m.includes('v')) nm += "&#9834;"; // volume effects
if (m.includes('f')) nm += "&#9835;"; // frequency effects
}
}
html += generateListItemHtml('fx',id,nm,'setFX','',fd);
@@ -1722,15 +1724,6 @@ function resetUtil()
+ '<div class="segname" onclick="makeSeg()"><i class="icons btn-icon">&#xe18a;</i>Add segment</div></div>';
}
var plJson = {"0":{
"ps": [0],
"dur": [100],
"transition": [-1], // to be inited to default transition dur
"repeat": 0,
"r": false,
"end": 0
}};
function makePlSel(el, incPl=false) {
var plSelContent = "";
delete pJson["0"]; // remove filler preset
@@ -1811,6 +1804,14 @@ function plR(p) {
function makeP(i,pl) {
var content = "";
if (pl) {
if (i===0) plJson[0] = {
ps: [1],
dur: [100],
transition: [tr],
repeat: 0,
r: false,
end: 0
};
var rep = plJson[i].repeat ? plJson[i].repeat : 0;
content =
`<div id="ple${i}" style="margin-top:10px;"></div><label class="check revchkl">Shuffle
@@ -1933,7 +1934,6 @@ function makePlUtil()
if (pNum < 2) {
showToast("You need at least 2 presets to make a playlist!"); //return;
}
if (plJson[0].transition[0] < 0) plJson[0].transition[0] = tr;
let p = gId('putil');
p.classList.remove('staybot');
p.classList.add('pres');

View File

@@ -619,6 +619,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
</div>
<hr class="sml">
<div id="btns"></div>
Disable internal pull-up/down: <input type="checkbox" name="IP"><br>
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
<div id="irOnOff2">
<em style="color:darkorange">This firmware build does not include IR Remote support. <br></em>

View File

@@ -184,18 +184,13 @@
}
}
// https://stackoverflow.com/questions/26440494/insert-text-after-this-input-element-with-javascript
//WLEDMM Add pre and post texts
function addInfo(name,el,txt, txt2="") {
let obj = d.getElementsByName(name);
if (!obj.length) return;
if (typeof el === "string" && obj[0]) obj[0].placeholder = el;
else if (obj[el]) {
if (txt2!="") {
obj[el].insertAdjacentHTML('beforebegin', txt + '&nbsp;');
obj[el].insertAdjacentHTML('afterend', '&nbsp;'+txt2);
}
else
obj[el].insertAdjacentHTML('afterend', '&nbsp;'+txt);
if (txt!="") obj[el].insertAdjacentHTML('afterend', '&nbsp;'+txt);
if (txt2!="") obj[el].insertAdjacentHTML('beforebegin', txt2 + '&nbsp;'); //add pre texts
}
}
// load settings and insert values into DOM

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -456,6 +456,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
// if preset contains HTTP API call do not change presetCycCurr
if (root["win"].isNull()) presetCycCurr = currentPreset;
stateChanged = false; // cancel state change update (preset was set directly by applying values stored in UI JSON array)
notify(callMode);
} else if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) {
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
presetCycCurr = ps;
@@ -463,7 +464,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
root.remove("v"); // may be added in UI call
root.remove("time"); // may be added in UI call
root.remove("ps");
root.remove("on"); // some exetrnal calls add "on" to "ps" call
root.remove("on"); // some external calls add "on" to "ps" call
if (root.size() == 0) {
unloadPlaylist(); // we need to unload playlist
applyPreset(ps, callMode); // async load (only preset ID was specified)

View File

@@ -195,14 +195,14 @@ void handleTransitions()
}
if (tper - tperLast < 0.004) return;
tperLast = tper;
briT = briOld +((bri - briOld )*tper);
briT = briOld + ((bri - briOld) * tper);
applyBri();
}
}
//legacy method, applies values from col, effectCurrent, ... to selected segments
// legacy method, applies values from col, effectCurrent, ... to selected segments
void colorUpdated(byte callMode){
applyValuesToSelectedSegs();
stateUpdated(callMode);
@@ -213,8 +213,8 @@ void handleNightlight()
{
static unsigned long lastNlUpdate;
unsigned long now = millis();
if (now < 100 && lastNlUpdate > 0) lastNlUpdate = 0; //take care of millis() rollover
if (now - lastNlUpdate < 100) return; //allow only 10 NL updates per second
if (now < 100 && lastNlUpdate > 0) lastNlUpdate = 0; // take care of millis() rollover
if (now - lastNlUpdate < 100) return; // allow only 10 NL updates per second
lastNlUpdate = now;
if (nightlightActive)

View File

@@ -307,7 +307,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
#ifdef WLED_DEBUG
DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: GPIO "));
DEBUG_PRINT(gpio);
DEBUG_PRINT(" as "); DEBUG_PRINT(mptArray[i].isOutput ? "output": "input"); // WLEDMM
DEBUG_PRINT(" as "); DEBUG_PRINT(mptArray[i].isOutput ? "output": "input");
DEBUG_PRINTLN(F(""));
#else // WLEDMM
USER_PRINTF("PIN ALLOC: invalid pin - cannot use GPIO%d for %s.\n", gpio, mptArray[i].isOutput ? "output": "input");
@@ -350,7 +350,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
continue;
}
if (gpio >= WLED_NUM_PINS)
continue; // WLEDMM - invalid GPIO => avoid array bounds violation
continue; // other unexpected GPIO => avoid array bounds violation
byte by = gpio >> 3;
byte bi = gpio - 8*by;
@@ -371,7 +371,7 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
{
// HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) { // WLEDMM bugfix - avoid array bounds violation
if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) {
#ifdef WLED_DEBUG
if (gpio < 255) { // 255 (-1) is the "not defined GPIO"
if (!isPinOk(gpio, output)) {
@@ -495,6 +495,7 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
}
PinOwner PinManagerClass::getPinOwner(byte gpio) {
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // catch error case, to avoid array out-of-bounds access
if (!isPinOk(gpio, false)) return PinOwner::None;
if (gpio >= WLED_NUM_PINS) return PinOwner::None; // WLEDMM: catch error cases
return ownerTag[gpio];

View File

@@ -58,7 +58,8 @@ enum struct PinOwner : uint8_t {
UM_BME280 = USERMOD_ID_BME280, // 0x18 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
UM_BH1750 = USERMOD_ID_BH1750, // 0x19 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE, // 0x1E // Usermod "audio_reactive.h"
UM_SdCard = USERMOD_ID_SD_CARD // 0x24 // Usermod "usermod_sd_card.h"
UM_SdCard = USERMOD_ID_SD_CARD, // 0x24 // Usermod "usermod_sd_card.h"
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS // 0x21 // Usermod "usermod_pwm_outputs.h"
};
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");

View File

@@ -245,7 +245,8 @@ void handlePresets()
#endif
releaseJSONBufferLock(); // will also clear fileDoc
colorUpdated(tmpMode);
if (changePreset) notify(tmpMode); // force UDP notification
stateUpdated(tmpMode); // was colorUpdated() if anything breaks
updateInterfaces(tmpMode);
}

View File

@@ -161,6 +161,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
}
rlyMde = (bool)request->hasArg(F("RM"));
disablePullUp = (bool)request->hasArg(F("IP"));
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
char bt[4] = "BT"; bt[2] = (i<10?48:55)+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
char be[4] = "BE"; be[2] = (i<10?48:55)+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)

View File

@@ -172,6 +172,11 @@
#include "../usermods/sd_card/usermod_sd_card.h"
#endif
#ifdef USERMOD_PWM_OUTPUTS
#include "../usermods/pwm_outputs/usermod_pwm_outputs.h"
#endif
//WLEDMM Custom Effects
#ifdef USERMOD_CUSTOMEFFECTS
#include "../usermods/customeffects/usermod_v2_customeffects.h"
@@ -339,6 +344,10 @@ void registerUsermods()
#ifdef SD_ADAPTER
usermods.add(new UsermodSdCard());
#endif
#ifdef USERMOD_PWM_OUTPUTS
usermods.add(new PwmOutputsUsermod());
#endif
//WLEDMM Custom Effects
#ifdef USERMOD_CUSTOMEFFECTS

View File

@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2212051
#define VERSION 2212060
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@@ -517,6 +517,7 @@ WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
WLED_GLOBAL bool buttonLongPressed[WLED_MAX_BUTTONS] _INIT({false});
WLED_GLOBAL unsigned long buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
WLED_GLOBAL unsigned long buttonWaitTime[WLED_MAX_BUTTONS] _INIT({0});
WLED_GLOBAL bool disablePullUp _INIT(false);
WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESHOLD);
// notifications

View File

@@ -22,15 +22,15 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
if (client->id() == wsLiveClientId) wsLiveClientId = 0;
DEBUG_PRINTLN(F("WS client disconnected."));
} else if(type == WS_EVT_DATA){
//data packet
// data packet
AwsFrameInfo * info = (AwsFrameInfo*)arg;
if(info->final && info->index == 0 && info->len == len){
//the whole message is in a single frame and we got all of its data (max. 1450byte)
// the whole message is in a single frame and we got all of its data (max. 1450 bytes)
if(info->opcode == WS_TEXT)
{
if (len > 0 && len < 10 && data[0] == 'p') {
//application layer ping/pong heartbeat.
//client-side socket layer ping packets are unresponded (investigate)
// application layer ping/pong heartbeat.
// client-side socket layer ping packets are unresponded (investigate)
client->text(F("pong"));
return;
}
@@ -54,7 +54,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
}
releaseJSONBufferLock(); // will clean fileDoc
// force broadcast in 500ms after upadting client
// force broadcast in 500ms after updating client
if (verboseResponse) {
sendDataWs(client);
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);

View File

@@ -458,6 +458,7 @@ void getSettingsJS(byte subPage, char* dest)
oappend(itoa(buttonType[i],nS,10));
oappend(SET_F(");"));
}
sappend('c',SET_F("IP"),disablePullUp);
sappend('v',SET_F("TT"),touchThreshold);
sappend('v',SET_F("IR"),irPin);
sappend('v',SET_F("IT"),irEnabled);