068c5851ef
* Add fields for customization Blynk host Add fields to 'Sync Interfaces' for customization Blynk host. Now you can set you own Blynk server. All you needs its set custom host and port to local Blync server. * Lower blynk host length (memory usage) Co-authored-by: cschwinne <dev.aircoookie@gmail.com>
729 lines
21 KiB
C++
729 lines
21 KiB
C++
#include "wled.h"
|
|
|
|
/*
|
|
* Receives client input
|
|
*/
|
|
|
|
void _setRandomColor(bool _sec,bool fromButton)
|
|
{
|
|
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
|
if (_sec){
|
|
colorHStoRGB(lastRandomIndex*256,255,colSec);
|
|
} else {
|
|
colorHStoRGB(lastRandomIndex*256,255,col);
|
|
}
|
|
if (fromButton) colorUpdated(2);
|
|
}
|
|
|
|
|
|
bool isAsterisksOnly(const char* str, byte maxLen)
|
|
{
|
|
for (byte i = 0; i < maxLen; i++) {
|
|
if (str[i] == 0) break;
|
|
if (str[i] != '*') return false;
|
|
}
|
|
//at this point the password contains asterisks only
|
|
return (str[0] != 0); //false on empty string
|
|
}
|
|
|
|
|
|
//called upon POST settings form submit
|
|
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|
{
|
|
|
|
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX
|
|
if (subPage <1 || subPage >7) return;
|
|
|
|
//WIFI SETTINGS
|
|
if (subPage == 1)
|
|
{
|
|
strlcpy(clientSSID,request->arg(F("CS")).c_str(), 33);
|
|
|
|
if (!isAsterisksOnly(request->arg(F("CP")).c_str(), 65)) strlcpy(clientPass, request->arg(F("CP")).c_str(), 65);
|
|
|
|
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
|
|
|
apBehavior = request->arg(F("AB")).toInt();
|
|
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33);
|
|
apHide = request->hasArg(F("AH"));
|
|
int passlen = request->arg(F("AP")).length();
|
|
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg(F("AP")).c_str(), 65))) strlcpy(apPass, request->arg(F("AP")).c_str(), 65);
|
|
int t = request->arg(F("AC")).toInt(); if (t > 0 && t < 14) apChannel = t;
|
|
|
|
noWifiSleep = request->hasArg(F("WS"));
|
|
|
|
char k[3]; k[2] = 0;
|
|
for (int i = 0; i<4; i++)
|
|
{
|
|
k[1] = i+48;//ascii 0,1,2,3
|
|
|
|
k[0] = 'I'; //static IP
|
|
staticIP[i] = request->arg(k).toInt();
|
|
|
|
k[0] = 'G'; //gateway
|
|
staticGateway[i] = request->arg(k).toInt();
|
|
|
|
k[0] = 'S'; //subnet
|
|
staticSubnet[i] = request->arg(k).toInt();
|
|
}
|
|
}
|
|
|
|
//LED SETTINGS
|
|
if (subPage == 2)
|
|
{
|
|
int t = request->arg(F("LC")).toInt();
|
|
if (t > 0 && t <= MAX_LEDS) ledCount = t;
|
|
#ifdef ESP8266
|
|
#if LEDPIN == 3
|
|
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
|
|
#endif
|
|
#endif
|
|
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
|
|
strip.milliampsPerLed = request->arg(F("LA")).toInt();
|
|
|
|
useRGBW = request->hasArg(F("EW"));
|
|
strip.setColorOrder(request->arg(F("CO")).toInt());
|
|
strip.rgbwMode = request->arg(F("AW")).toInt();
|
|
|
|
briS = request->arg(F("CA")).toInt();
|
|
|
|
saveCurrPresetCycConf = request->hasArg(F("PC"));
|
|
turnOnAtBoot = request->hasArg(F("BO"));
|
|
t = request->arg(F("BP")).toInt();
|
|
if (t <= 25) bootPreset = t;
|
|
strip.gammaCorrectBri = request->hasArg(F("GB"));
|
|
strip.gammaCorrectCol = request->hasArg(F("GC"));
|
|
|
|
fadeTransition = request->hasArg(F("TF"));
|
|
t = request->arg(F("TD")).toInt();
|
|
if (t > 0) transitionDelay = t;
|
|
transitionDelayDefault = t;
|
|
strip.paletteFade = request->hasArg(F("PF"));
|
|
|
|
nightlightTargetBri = request->arg(F("TB")).toInt();
|
|
t = request->arg(F("TL")).toInt();
|
|
if (t > 0) nightlightDelayMinsDefault = t;
|
|
nightlightDelayMins = nightlightDelayMinsDefault;
|
|
nightlightMode = request->arg(F("TW")).toInt();
|
|
|
|
t = request->arg(F("PB")).toInt();
|
|
if (t >= 0 && t < 4) strip.paletteBlend = t;
|
|
strip.reverseMode = request->hasArg(F("RV"));
|
|
skipFirstLed = request->hasArg(F("SL"));
|
|
t = request->arg(F("BF")).toInt();
|
|
if (t > 0) briMultiplier = t;
|
|
}
|
|
|
|
//UI
|
|
if (subPage == 3)
|
|
{
|
|
strlcpy(serverDescription, request->arg(F("DS")).c_str(), 33);
|
|
syncToggleReceive = request->hasArg(F("ST"));
|
|
}
|
|
|
|
//SYNC
|
|
if (subPage == 4)
|
|
{
|
|
buttonEnabled = request->hasArg(F("BT"));
|
|
irEnabled = request->arg(F("IR")).toInt();
|
|
int t = request->arg(F("UP")).toInt();
|
|
if (t > 0) udpPort = t;
|
|
t = request->arg(F("U2")).toInt();
|
|
if (t > 0) udpPort2 = t;
|
|
receiveNotificationBrightness = request->hasArg(F("RB"));
|
|
receiveNotificationColor = request->hasArg(F("RC"));
|
|
receiveNotificationEffects = request->hasArg(F("RX"));
|
|
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
|
notifyDirectDefault = request->hasArg(F("SD"));
|
|
notifyDirect = notifyDirectDefault;
|
|
notifyButton = request->hasArg(F("SB"));
|
|
notifyAlexa = request->hasArg(F("SA"));
|
|
notifyHue = request->hasArg(F("SH"));
|
|
notifyMacro = request->hasArg(F("SM"));
|
|
notifyTwice = request->hasArg(F("S2"));
|
|
|
|
receiveDirect = request->hasArg(F("RD"));
|
|
e131SkipOutOfSequence = request->hasArg(F("ES"));
|
|
e131Multicast = request->hasArg(F("EM"));
|
|
t = request->arg(F("EP")).toInt();
|
|
if (t > 0) e131Port = t;
|
|
t = request->arg(F("EU")).toInt();
|
|
if (t >= 0 && t <= 63999) e131Universe = t;
|
|
t = request->arg(F("DA")).toInt();
|
|
if (t >= 0 && t <= 510) DMXAddress = t;
|
|
t = request->arg(F("DM")).toInt();
|
|
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_RGBW) DMXMode = t;
|
|
t = request->arg(F("ET")).toInt();
|
|
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
|
|
arlsForceMaxBri = request->hasArg(F("FB"));
|
|
arlsDisableGammaCorrection = request->hasArg(F("RG"));
|
|
t = request->arg(F("WO")).toInt();
|
|
if (t >= -255 && t <= 255) arlsOffset = t;
|
|
|
|
alexaEnabled = request->hasArg(F("AL"));
|
|
strlcpy(alexaInvocationName, request->arg(F("AI")).c_str(), 33);
|
|
|
|
strlcpy(blynkHost, request->arg("BH").c_str(), 33);
|
|
t = request->arg(F("BP")).toInt();
|
|
if (t > 0) blynkPort = t;
|
|
|
|
if (request->hasArg("BK") && !request->arg("BK").equals(F("Hidden"))) {
|
|
strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey, blynkHost, blynkPort);
|
|
}
|
|
|
|
#ifdef WLED_ENABLE_MQTT
|
|
mqttEnabled = request->hasArg(F("MQ"));
|
|
strlcpy(mqttServer, request->arg(F("MS")).c_str(), 33);
|
|
t = request->arg(F("MQPORT")).toInt();
|
|
if (t > 0) mqttPort = t;
|
|
strlcpy(mqttUser, request->arg(F("MQUSER")).c_str(), 41);
|
|
if (!isAsterisksOnly(request->arg(F("MQPASS")).c_str(), 41)) strlcpy(mqttPass, request->arg(F("MQPASS")).c_str(), 41);
|
|
strlcpy(mqttClientID, request->arg(F("MQCID")).c_str(), 41);
|
|
strlcpy(mqttDeviceTopic, request->arg(F("MD")).c_str(), 33);
|
|
strlcpy(mqttGroupTopic, request->arg(F("MG")).c_str(), 33);
|
|
#endif
|
|
|
|
#ifndef WLED_DISABLE_HUESYNC
|
|
for (int i=0;i<4;i++){
|
|
String a = "H"+String(i);
|
|
hueIP[i] = request->arg(a).toInt();
|
|
}
|
|
|
|
t = request->arg(F("HL")).toInt();
|
|
if (t > 0) huePollLightId = t;
|
|
|
|
t = request->arg(F("HI")).toInt();
|
|
if (t > 50) huePollIntervalMs = t;
|
|
|
|
hueApplyOnOff = request->hasArg(F("HO"));
|
|
hueApplyBri = request->hasArg(F("HB"));
|
|
hueApplyColor = request->hasArg(F("HC"));
|
|
huePollingEnabled = request->hasArg(F("HP"));
|
|
hueStoreAllowed = true;
|
|
reconnectHue();
|
|
#endif
|
|
}
|
|
|
|
//TIME
|
|
if (subPage == 5)
|
|
{
|
|
ntpEnabled = request->hasArg(F("NT"));
|
|
strlcpy(ntpServerName, request->arg(F("NS")).c_str(), 33);
|
|
useAMPM = !request->hasArg(F("CF"));
|
|
currentTimezone = request->arg(F("TZ")).toInt();
|
|
utcOffsetSecs = request->arg(F("UO")).toInt();
|
|
|
|
//start ntp if not already connected
|
|
if (ntpEnabled && WLED_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
|
|
|
if (request->hasArg(F("OL"))) {
|
|
overlayDefault = request->arg(F("OL")).toInt();
|
|
overlayCurrent = overlayDefault;
|
|
}
|
|
|
|
overlayMin = request->arg(F("O1")).toInt();
|
|
overlayMax = request->arg(F("O2")).toInt();
|
|
analogClock12pixel = request->arg(F("OM")).toInt();
|
|
analogClock5MinuteMarks = request->hasArg(F("O5"));
|
|
analogClockSecondsTrail = request->hasArg(F("OS"));
|
|
|
|
strcpy(cronixieDisplay,request->arg(F("CX")).c_str());
|
|
cronixieBacklight = request->hasArg(F("CB"));
|
|
countdownMode = request->hasArg(F("CE"));
|
|
countdownYear = request->arg(F("CY")).toInt();
|
|
countdownMonth = request->arg(F("CI")).toInt();
|
|
countdownDay = request->arg(F("CD")).toInt();
|
|
countdownHour = request->arg(F("CH")).toInt();
|
|
countdownMin = request->arg(F("CM")).toInt();
|
|
countdownSec = request->arg(F("CS")).toInt();
|
|
|
|
macroAlexaOn = request->arg(F("A0")).toInt();
|
|
macroAlexaOff = request->arg(F("A1")).toInt();
|
|
macroButton = request->arg(F("MP")).toInt();
|
|
macroLongPress = request->arg(F("ML")).toInt();
|
|
macroCountdown = request->arg(F("MC")).toInt();
|
|
macroNl = request->arg(F("MN")).toInt();
|
|
macroDoublePress = request->arg(F("MD")).toInt();
|
|
|
|
char k[3]; k[2] = 0;
|
|
for (int i = 0; i<8; i++)
|
|
{
|
|
k[1] = i+48;//ascii 0,1,2,3
|
|
|
|
k[0] = 'H'; //timer hours
|
|
timerHours[i] = request->arg(k).toInt();
|
|
|
|
k[0] = 'N'; //minutes
|
|
timerMinutes[i] = request->arg(k).toInt();
|
|
|
|
k[0] = 'T'; //macros
|
|
timerMacro[i] = request->arg(k).toInt();
|
|
|
|
k[0] = 'W'; //weekdays
|
|
timerWeekday[i] = request->arg(k).toInt();
|
|
}
|
|
}
|
|
|
|
//SECURITY
|
|
if (subPage == 6)
|
|
{
|
|
if (request->hasArg(F("RS"))) //complete factory reset
|
|
{
|
|
WLED_FS.format();
|
|
clearEEPROM();
|
|
serveMessage(request, 200, F("All Settings erased."), F("Connect to WLED-AP to setup again"),255);
|
|
doReboot = true;
|
|
}
|
|
|
|
bool pwdCorrect = !otaLock; //always allow access if ota not locked
|
|
if (request->hasArg(F("OP")))
|
|
{
|
|
if (otaLock && strcmp(otaPass,request->arg(F("OP")).c_str()) == 0)
|
|
{
|
|
pwdCorrect = true;
|
|
}
|
|
if (!otaLock && request->arg(F("OP")).length() > 0)
|
|
{
|
|
strlcpy(otaPass,request->arg(F("OP")).c_str(), 33);
|
|
}
|
|
}
|
|
|
|
if (pwdCorrect) //allow changes if correct pwd or no ota active
|
|
{
|
|
otaLock = request->hasArg(F("NO"));
|
|
wifiLock = request->hasArg(F("OW"));
|
|
aOtaEnabled = request->hasArg(F("AO"));
|
|
}
|
|
}
|
|
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
|
if (subPage == 7)
|
|
{
|
|
int t = request->arg(F("PU")).toInt();
|
|
if (t >= 0 && t <= 63999) e131ProxyUniverse = t;
|
|
|
|
t = request->arg(F("CN")).toInt();
|
|
if (t>0 && t<16) {
|
|
DMXChannels = t;
|
|
}
|
|
t = request->arg(F("CS")).toInt();
|
|
if (t>0 && t<513) {
|
|
DMXStart = t;
|
|
}
|
|
t = request->arg(F("CG")).toInt();
|
|
if (t>0 && t<513) {
|
|
DMXGap = t;
|
|
}
|
|
t = request->arg(F("SL")).toInt();
|
|
if (t>=0 && t < MAX_LEDS) {
|
|
DMXStartLED = t;
|
|
}
|
|
for (int i=0; i<15; i++) {
|
|
String argname = "CH" + String((i+1));
|
|
t = request->arg(argname).toInt();
|
|
DMXFixtureMap[i] = t;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
if (subPage != 6 || !doReboot) serializeConfig(); //do not save if factory reset
|
|
if (subPage == 2) {
|
|
strip.init(useRGBW,ledCount,skipFirstLed);
|
|
}
|
|
if (subPage == 4) alexaInit();
|
|
}
|
|
|
|
|
|
|
|
//helper to get int value at a position in string
|
|
int getNumVal(const String* req, uint16_t pos)
|
|
{
|
|
return req->substring(pos+3).toInt();
|
|
}
|
|
|
|
|
|
//helper to get int value at a position in string
|
|
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv)
|
|
{
|
|
int pos = req->indexOf(key);
|
|
if (pos < 1) return false;
|
|
|
|
if (req->charAt(pos+3) == '~') {
|
|
int out = getNumVal(req, pos+1);
|
|
if (out == 0)
|
|
{
|
|
if (req->charAt(pos+4) == '-')
|
|
{
|
|
*val = (*val <= minv)? maxv : *val -1;
|
|
} else {
|
|
*val = (*val >= maxv)? minv : *val +1;
|
|
}
|
|
} else {
|
|
out += *val;
|
|
if (out > maxv) out = maxv;
|
|
if (out < minv) out = minv;
|
|
*val = out;
|
|
}
|
|
} else
|
|
{
|
|
*val = getNumVal(req, pos);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//HTTP API request parser
|
|
bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|
{
|
|
if (!(req.indexOf("win") >= 0)) return false;
|
|
|
|
int pos = 0;
|
|
DEBUG_PRINT(F("API req: "));
|
|
DEBUG_PRINTLN(req);
|
|
|
|
strip.applyToAllSelected = true;
|
|
|
|
//segment select (sets main segment)
|
|
byte prevMain = strip.getMainSegmentId();
|
|
pos = req.indexOf(F("SM="));
|
|
if (pos > 0) {
|
|
strip.mainSegment = getNumVal(&req, pos);
|
|
}
|
|
byte main = strip.getMainSegmentId();
|
|
if (main != prevMain) setValuesFromMainSeg();
|
|
|
|
pos = req.indexOf(F("SS="));
|
|
if (pos > 0) {
|
|
byte t = getNumVal(&req, pos);
|
|
if (t < strip.getMaxSegments()) main = t;
|
|
}
|
|
|
|
WS2812FX::Segment& mainseg = strip.getSegment(main);
|
|
pos = req.indexOf(F("SV=")); //segment selected
|
|
if (pos > 0) {
|
|
byte t = getNumVal(&req, pos);
|
|
if (t == 2) {
|
|
for (uint8_t i = 0; i < strip.getMaxSegments(); i++)
|
|
{
|
|
strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0);
|
|
}
|
|
}
|
|
mainseg.setOption(SEG_OPTION_SELECTED, t);
|
|
}
|
|
|
|
uint16_t startI = mainseg.start;
|
|
uint16_t stopI = mainseg.stop;
|
|
uint8_t grpI = mainseg.grouping;
|
|
uint16_t spcI = mainseg.spacing;
|
|
pos = req.indexOf(F("&S=")); //segment start
|
|
if (pos > 0) {
|
|
startI = getNumVal(&req, pos);
|
|
}
|
|
pos = req.indexOf(F("S2=")); //segment stop
|
|
if (pos > 0) {
|
|
stopI = getNumVal(&req, pos);
|
|
}
|
|
pos = req.indexOf(F("GP=")); //segment grouping
|
|
if (pos > 0) {
|
|
grpI = getNumVal(&req, pos);
|
|
if (grpI == 0) grpI = 1;
|
|
}
|
|
pos = req.indexOf(F("SP=")); //segment spacing
|
|
if (pos > 0) {
|
|
spcI = getNumVal(&req, pos);
|
|
}
|
|
strip.setSegment(main, startI, stopI, grpI, spcI);
|
|
|
|
main = strip.getMainSegmentId();
|
|
|
|
//set presets
|
|
pos = req.indexOf(F("P1=")); //sets first preset for cycle
|
|
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
|
|
|
pos = req.indexOf(F("P2=")); //sets last preset for cycle
|
|
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
|
|
|
//preset cycle
|
|
pos = req.indexOf(F("CY="));
|
|
if (pos > 0)
|
|
{
|
|
char cmd = req.charAt(pos+3);
|
|
if (cmd == '2') presetCyclingEnabled = !presetCyclingEnabled;
|
|
else presetCyclingEnabled = (cmd != '0');
|
|
presetCycCurr = presetCycleMin;
|
|
}
|
|
|
|
pos = req.indexOf(F("PT=")); //sets cycle time in ms
|
|
if (pos > 0) {
|
|
int v = getNumVal(&req, pos);
|
|
if (v > 100) presetCycleTime = v/100;
|
|
}
|
|
|
|
pos = req.indexOf(F("PS=")); //saves current in preset
|
|
if (pos > 0) savePreset(getNumVal(&req, pos));
|
|
|
|
//apply preset
|
|
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
|
|
applyPreset(presetCycCurr);
|
|
}
|
|
|
|
//set brightness
|
|
updateVal(&req, "&A=", &bri);
|
|
|
|
//set colors
|
|
updateVal(&req, "&R=", &col[0]);
|
|
updateVal(&req, "&G=", &col[1]);
|
|
updateVal(&req, "&B=", &col[2]);
|
|
updateVal(&req, "&W=", &col[3]);
|
|
updateVal(&req, "R2=", &colSec[0]);
|
|
updateVal(&req, "G2=", &colSec[1]);
|
|
updateVal(&req, "B2=", &colSec[2]);
|
|
updateVal(&req, "W2=", &colSec[3]);
|
|
|
|
#ifdef WLED_ENABLE_LOXONE
|
|
//lox parser
|
|
pos = req.indexOf(F("LX=")); // Lox primary color
|
|
if (pos > 0) {
|
|
int lxValue = getNumVal(&req, pos);
|
|
if (parseLx(lxValue, col)) {
|
|
bri = 255;
|
|
nightlightActive = false; //always disable nightlight when toggling
|
|
}
|
|
}
|
|
pos = req.indexOf(F("LY=")); // Lox secondary color
|
|
if (pos > 0) {
|
|
int lxValue = getNumVal(&req, pos);
|
|
if(parseLx(lxValue, colSec)) {
|
|
bri = 255;
|
|
nightlightActive = false; //always disable nightlight when toggling
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
//set hue
|
|
pos = req.indexOf(F("HU="));
|
|
if (pos > 0) {
|
|
uint16_t temphue = getNumVal(&req, pos);
|
|
byte tempsat = 255;
|
|
pos = req.indexOf(F("SA="));
|
|
if (pos > 0) {
|
|
tempsat = getNumVal(&req, pos);
|
|
}
|
|
colorHStoRGB(temphue,tempsat,(req.indexOf(F("H2"))>0)? colSec:col);
|
|
}
|
|
|
|
//set white spectrum (kelvin)
|
|
pos = req.indexOf(F("&K="));
|
|
if (pos > 0) {
|
|
colorKtoRGB(getNumVal(&req, pos),(req.indexOf(F("K2"))>0)? colSec:col);
|
|
}
|
|
|
|
//set color from HEX or 32bit DEC
|
|
pos = req.indexOf(F("CL="));
|
|
if (pos > 0) {
|
|
colorFromDecOrHexString(col, (char*)req.substring(pos + 3).c_str());
|
|
}
|
|
pos = req.indexOf(F("C2="));
|
|
if (pos > 0) {
|
|
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
|
|
}
|
|
pos = req.indexOf(F("C3="));
|
|
if (pos > 0) {
|
|
byte t[4];
|
|
colorFromDecOrHexString(t, (char*)req.substring(pos + 3).c_str());
|
|
strip.setColor(2, t[0], t[1], t[2], t[3]);
|
|
}
|
|
|
|
//set to random hue SR=0->1st SR=1->2nd
|
|
pos = req.indexOf(F("SR"));
|
|
if (pos > 0) {
|
|
_setRandomColor(getNumVal(&req, pos));
|
|
}
|
|
|
|
//swap 2nd & 1st
|
|
pos = req.indexOf(F("SC"));
|
|
if (pos > 0) {
|
|
byte temp;
|
|
for (uint8_t i=0; i<4; i++)
|
|
{
|
|
temp = col[i];
|
|
col[i] = colSec[i];
|
|
colSec[i] = temp;
|
|
}
|
|
}
|
|
|
|
//set effect parameters
|
|
if (updateVal(&req, "FX=", &effectCurrent, 0, strip.getModeCount()-1)) presetCyclingEnabled = false;
|
|
updateVal(&req, "SX=", &effectSpeed);
|
|
updateVal(&req, "IX=", &effectIntensity);
|
|
updateVal(&req, "FP=", &effectPalette, 0, strip.getPaletteCount()-1);
|
|
|
|
//set advanced overlay
|
|
pos = req.indexOf(F("OL="));
|
|
if (pos > 0) {
|
|
overlayCurrent = getNumVal(&req, pos);
|
|
}
|
|
|
|
//apply macro (deprecated, added for compatibility with pre-0.11 automations)
|
|
pos = req.indexOf(F("&M="));
|
|
if (pos > 0) {
|
|
applyPreset(getNumVal(&req, pos) + 16);
|
|
}
|
|
|
|
//toggle send UDP direct notifications
|
|
pos = req.indexOf(F("SN="));
|
|
if (pos > 0) notifyDirect = (req.charAt(pos+3) != '0');
|
|
|
|
//toggle receive UDP direct notifications
|
|
pos = req.indexOf(F("RN="));
|
|
if (pos > 0) receiveNotifications = (req.charAt(pos+3) != '0');
|
|
|
|
//receive live data via UDP/Hyperion
|
|
pos = req.indexOf(F("RD="));
|
|
if (pos > 0) receiveDirect = (req.charAt(pos+3) != '0');
|
|
|
|
//main toggle on/off (parse before nightlight, #1214)
|
|
pos = req.indexOf(F("&T="));
|
|
if (pos > 0) {
|
|
nightlightActive = false; //always disable nightlight when toggling
|
|
switch (getNumVal(&req, pos))
|
|
{
|
|
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off, only if it was previously on
|
|
case 1: if (bri == 0) bri = briLast; break; //on, only if it was previously off
|
|
default: toggleOnOff(); //toggle
|
|
}
|
|
}
|
|
|
|
//toggle nightlight mode
|
|
bool aNlDef = false;
|
|
if (req.indexOf(F("&ND")) > 0) aNlDef = true;
|
|
pos = req.indexOf(F("NL="));
|
|
if (pos > 0)
|
|
{
|
|
if (req.charAt(pos+3) == '0')
|
|
{
|
|
nightlightActive = false;
|
|
} else {
|
|
nightlightActive = true;
|
|
if (!aNlDef) nightlightDelayMins = getNumVal(&req, pos);
|
|
nightlightStartTime = millis();
|
|
}
|
|
} else if (aNlDef)
|
|
{
|
|
nightlightActive = true;
|
|
nightlightStartTime = millis();
|
|
}
|
|
|
|
//set nightlight target brightness
|
|
pos = req.indexOf(F("NT="));
|
|
if (pos > 0) {
|
|
nightlightTargetBri = getNumVal(&req, pos);
|
|
nightlightActiveOld = false; //re-init
|
|
}
|
|
|
|
//toggle nightlight fade
|
|
pos = req.indexOf(F("NF="));
|
|
if (pos > 0)
|
|
{
|
|
nightlightMode = getNumVal(&req, pos);
|
|
|
|
nightlightActiveOld = false; //re-init
|
|
}
|
|
if (nightlightMode > NL_MODE_SUN) nightlightMode = NL_MODE_SUN;
|
|
|
|
#if AUXPIN >= 0
|
|
//toggle general purpose output
|
|
pos = req.indexOf(F("AX="));
|
|
if (pos > 0) {
|
|
auxTime = getNumVal(&req, pos);
|
|
auxActive = true;
|
|
if (auxTime == 0) auxActive = false;
|
|
}
|
|
#endif
|
|
|
|
pos = req.indexOf(F("TT="));
|
|
if (pos > 0) transitionDelay = getNumVal(&req, pos);
|
|
|
|
//Segment reverse
|
|
pos = req.indexOf(F("RV="));
|
|
if (pos > 0) strip.getSegment(main).setOption(SEG_OPTION_REVERSED, req.charAt(pos+3) != '0');
|
|
|
|
//Segment reverse
|
|
pos = req.indexOf(F("MI="));
|
|
if (pos > 0) strip.getSegment(main).setOption(SEG_OPTION_MIRROR, req.charAt(pos+3) != '0');
|
|
|
|
//Segment brightness/opacity
|
|
pos = req.indexOf(F("SB="));
|
|
if (pos > 0) {
|
|
byte segbri = getNumVal(&req, pos);
|
|
strip.getSegment(main).setOption(SEG_OPTION_ON, segbri);
|
|
if (segbri) {
|
|
strip.getSegment(main).opacity = segbri;
|
|
}
|
|
}
|
|
|
|
//set time (unix timestamp)
|
|
pos = req.indexOf(F("ST="));
|
|
if (pos > 0) {
|
|
setTime(getNumVal(&req, pos));
|
|
}
|
|
|
|
//set countdown goal (unix timestamp)
|
|
pos = req.indexOf(F("CT="));
|
|
if (pos > 0) {
|
|
countdownTime = getNumVal(&req, pos);
|
|
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
|
}
|
|
|
|
pos = req.indexOf(F("LO="));
|
|
if (pos > 0) {
|
|
realtimeOverride = getNumVal(&req, pos);
|
|
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
|
}
|
|
|
|
pos = req.indexOf(F("RB"));
|
|
if (pos > 0) doReboot = true;
|
|
|
|
//cronixie
|
|
#ifndef WLED_DISABLE_CRONIXIE
|
|
//mode, 1 countdown
|
|
pos = req.indexOf(F("NM="));
|
|
if (pos > 0) countdownMode = (req.charAt(pos+3) != '0');
|
|
|
|
pos = req.indexOf(F("NX=")); //sets digits to code
|
|
if (pos > 0) {
|
|
strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6);
|
|
setCronixie();
|
|
}
|
|
|
|
pos = req.indexOf(F("NB="));
|
|
if (pos > 0) //sets backlight
|
|
{
|
|
cronixieBacklight = (req.charAt(pos+3) != '0');
|
|
overlayRefreshedTime = 0;
|
|
}
|
|
#endif
|
|
|
|
pos = req.indexOf(F("U0=")); //user var 0
|
|
if (pos > 0) {
|
|
userVar0 = getNumVal(&req, pos);
|
|
}
|
|
|
|
pos = req.indexOf(F("U1=")); //user var 1
|
|
if (pos > 0) {
|
|
userVar1 = getNumVal(&req, pos);
|
|
}
|
|
//you can add more if you need
|
|
|
|
if (!apply) return true; //when called by JSON API, do not call colorUpdated() here
|
|
|
|
//internal call, does not send XML response
|
|
pos = req.indexOf(F("IN"));
|
|
if (pos < 1) XML_response(request);
|
|
|
|
pos = req.indexOf(F("&NN")); //do not send UDP notifications this time
|
|
colorUpdated((pos > 0) ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
|
|
|
return true;
|
|
}
|