Merge pull request #1193 from Aircoookie/merge-fs2

Update FS branch
This commit is contained in:
Aircoookie 2020-09-22 08:34:23 +02:00 committed by GitHub
commit 85c0002a78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 908 additions and 661 deletions

View file

@ -2,6 +2,29 @@
### Development versions after the 0.10.2 release
#### Build 2009202
- Fixed LPD8806 compilation
#### Build 2009201
- Added support for preset cycle toggling using CY=2
- Added ESP32 touch pin support (#1190)
- Fixed modem sleep on ESP8266 (#1184)
#### Build 2009200
- Increased available heap memory by 4kB
- Use F() macro for the majority of strings
- Restructure timezone code
- Restructured settings saved code
- Updated ArduinoJSON to 6.16.1
#### Build 2009170
- New WLED logo on Welcome screen (#1164)
- Fixed 170th pixel dark in E1.31
#### Build 2009100
- Fixed sunrise mode not reinitializing

View file

@ -165,7 +165,8 @@ lib_extra_dirs =
lib_compat_mode = strict
lib_deps =
FastLED@3.3.2
NeoPixelBus@2.5.7
#NeoPixelBus@2.5.7
https://github.com/Makuna/NeoPixelBus
ESPAsyncTCP@1.2.0
ESPAsyncUDP
AsyncTCP@1.0.3
@ -336,6 +337,14 @@ lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
[env:custom32_TOUCHPIN_T0]
board = esp32dev
platform = espressif32@1.12.4
build_flags = ${common.build_flags_esp32} -D TOUCHPIN=T0
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
[env:wemos_shield_esp32]
board = esp32dev
platform = espressif32@1.12.4

View file

@ -21,6 +21,7 @@ build_flags = ${common.build_flags_esp8266}
; PIN defines - uncomment and change, if needed:
; -D LEDPIN=2
; -D BTNPIN=0
; -D TOUCHPIN=T0
; -D IR_PIN=4
; -D RLYPIN=12
; -D RLYMDE=1

View file

@ -72,7 +72,7 @@ WS2811 | 12v | 3-LED segments
WS2815 | 12v |
GS8208 | 12v |
## 🧊 Compatibe PC RGB Fans and ARGB accessories
## 🧊 Compatible PC RGB Fans and ARGB accessories
Brand | Model | Comments
|---|---|---|
Corsair | HD120 Fan | Uses WS2812B, data-in only
@ -97,7 +97,7 @@ If WLED really brightens up your every day, you can [![](https://img.shields.io/
*Disclaimer:*
If you are sensitive to photoeleptic seizures it is not recommended that you use this software.
If you are sensitive to photosensitive epilepsy it is not recommended that you use this software.
In case you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
As per the MIT license, i assume no liability for any damage to you or any other person or equipment.
As per the MIT license, I assume no liability for any damage to you or any other person or equipment.

View file

@ -0,0 +1,19 @@
# ESP32 Touch Brightness Control
Toggle On/Off with a long press (800ms)
Switch through 5 brightness levels (defined in usermod_touchbrightness.h, values 0-255) with a short (100ms) touch
## Installation
Copy 'usermod_touchbrightness.h' to the wled00 directory.
in 'usermod_list.cpp' add this:
> #include "usermod_touchbrightness.h"
above "void registerUsermods()"
and
> usermods.add(new TouchBrightnessControl());
inside the "registerUsermods()" function

View file

@ -0,0 +1,89 @@
//
// usermod_touchbrightness.h
// github.com/aircoookie/WLED
//
// Created by Justin Kühner on 14.09.2020.
// Copyright © 2020 NeariX. All rights reserved.
// https://github.com/NeariX67/
// Discord: @NeariX#4799
#pragma once
#include "wled.h"
#define threshold 40 //Increase value if touches falsely accur. Decrease value if actual touches are not recognized
#define touchPin T0 //T0 = D4 / GPIO4
//Define the 5 brightness levels
//Long press to turn off / on
#define brightness1 51
#define brightness2 102
#define brightness3 153
#define brightness4 204
#define brightness5 255
#ifdef ESP32
class TouchBrightnessControl : public Usermod {
private:
unsigned long lastTime = 0; //Interval
unsigned long lastTouch = 0; //Timestamp of last Touch
unsigned long lastRelease = 0; //Timestamp of last Touch release
boolean released = true; //current Touch state (touched/released)
uint16_t touchReading = 0; //sensor reading, maybe use uint8_t???
uint16_t touchDuration = 0; //duration of last touch
public:
void setup() {
lastTouch = millis();
lastRelease = millis();
lastTime = millis();
}
void loop() {
if (millis() - lastTime >= 50) { //Check every 50ms if a touch occurs
lastTime = millis();
touchReading = touchRead(touchPin); //Read touch sensor on pin T0 (GPIO4 / D4)
if(touchReading < threshold && released) { //Touch started
released = false;
lastTouch = millis();
}
else if(touchReading >= threshold && !released) { //Touch released
released = true;
lastRelease = millis();
touchDuration = lastRelease - lastTouch; //Calculate duration
}
//Serial.println(touchDuration);
if(touchDuration >= 800 && released) { //Toggle power if button press is longer than 800ms
touchDuration = 0; //Reset touch duration to avoid multiple actions on same touch
toggleOnOff();
colorUpdated(2); //Refresh values
}
else if(touchDuration >= 100 && released) { //Switch to next brightness if touch is between 100 and 800ms
touchDuration = 0; //Reset touch duration to avoid multiple actions on same touch
if(bri < brightness1) {
bri = brightness1;
} else if(bri >= brightness1 && bri < brightness2) {
bri = brightness2;
} else if(bri >= brightness2 && bri < brightness3) {
bri = brightness3;
} else if(bri >= brightness3 && bri < brightness4) {
bri = brightness4;
} else if(bri >= brightness4 && bri < brightness5) {
bri = brightness5;
} else if(bri >= brightness5) {
bri = brightness1;
}
colorUpdated(2); //Refresh values
}
}
}
};
#endif

View file

@ -49,7 +49,11 @@
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
#define MAX_NUM_SEGMENTS 10
#ifdef ESP8266
#define MAX_NUM_SEGMENTS 10
#else
#define MAX_NUM_SEGMENTS 10
#endif
/* How much data bytes all segments combined may allocate */
#ifdef ESP8266

View file

@ -21,6 +21,10 @@
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#endif
#ifndef TOUCHPIN
//#define TOUCHPIN T0 //touch pin. Behaves the same as button. ESP32 only.
#endif
#ifndef IR_PIN
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#endif
@ -138,6 +142,7 @@
#define PIXELFEATURE4 DotStarLbgrFeature
#elif defined(USE_LPD8806)
#define PIXELFEATURE3 Lpd8806GrbFeature
#define PIXELFEATURE4 Lpd8806GrbFeature
#elif defined(USE_WS2801)
#define PIXELFEATURE3 NeoRbgFeature
#define PIXELFEATURE4 NeoRbgFeature

View file

@ -15,13 +15,24 @@ void shortPressAction()
}
}
bool isButtonPressed()
{
#ifdef BTNPIN
if (digitalRead(BTNPIN) == LOW) return true;
#endif
#ifdef TOUCHPIN
if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true;
#endif
return false;
}
void handleButton()
{
#ifdef BTNPIN
#if defined(BTNPIN) || defined(TOUCHPIN)
if (!buttonEnabled) return;
if (digitalRead(BTNPIN) == LOW) //pressed
if (isButtonPressed()) //pressed
{
if (!buttonPressedBefore) buttonPressedTime = millis();
buttonPressedBefore = true;
@ -37,7 +48,7 @@ void handleButton()
}
}
}
else if (digitalRead(BTNPIN) == HIGH && buttonPressedBefore) //released
else if (!isButtonPressed() && buttonPressedBefore) //released
{
long dur = millis() - buttonPressedTime;
if (dur < 50) {buttonPressedBefore = false; return;} //too short "press", debounce

View file

@ -104,6 +104,15 @@
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
#define SEG_OPTION_TRANSITIONAL 7
// WLED Error modes
#define ERR_NONE 0 // All good :)
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
#define ERR_JSON 9 // JSON parsing failed (input too large?)
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
//Timer mode types
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
#define NL_MODE_FADE 1 //Fade to target brightness gradually
@ -126,12 +135,14 @@
#define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit
// WLED Error modes
#define ERR_NONE 0 // All good :)
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?)
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive
// Size of buffer for API JSON object (increase for more segments)
#ifdef ESP8266
#define JSON_BUFFER_SIZE 9216
#else
#define JSON_BUFFER_SIZE 16384
#endif
#endif

View file

@ -137,14 +137,14 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / 3;
previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * MAX_LEDS_PER_UNIVERSE;
}
uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset) / 3;
uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / 3;
for (uint16_t i = previousLeds; i < ledsTotal; i++) {
setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], 0);
}
break;
}
default:
DEBUG_PRINTLN("unknown E1.31 DMX mode");
DEBUG_PRINTLN(F("unknown E1.31 DMX mode"));
return; // nothing to do
break;
}

View file

@ -21,6 +21,7 @@ void updateBlynk();
//button.cpp
void shortPressAction();
bool isButtonPressed();
void handleButton();
void handleIO();
@ -197,7 +198,7 @@ bool applyPreset(byte index, bool loadBri = true);
void savePreset(byte index, bool persist = true, const char* pname = nullptr, byte prio = 50, JsonObject saveobj = JsonObject());
void loadMacro(byte index, char* m);
void applyMacro(byte index);
void saveMacro(byte index, String mc, bool persist = true); //only commit on single save, not in settings
void saveMacro(byte index, const String& mc, bool persist = true); //only commit on single save, not in settings
//wled_serial.cpp
void handleSerial();
@ -209,10 +210,10 @@ void initServer();
void serveIndexOrWelcome(AsyncWebServerRequest *request);
void serveIndex(AsyncWebServerRequest* request);
String msgProcessor(const String& var);
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255);
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);
String settingsProcessor(const String& var);
String dmxProcessor(const String& var);
void serveSettings(AsyncWebServerRequest* request);
void serveSettings(AsyncWebServerRequest* request, bool post = false);
//ws.cpp
void handleWs();

View file

@ -34,7 +34,7 @@ void handleHue()
void reconnectHue()
{
if (!WLED_CONNECTED || !huePollingEnabled) return;
DEBUG_PRINTLN("Hue reconnect");
DEBUG_PRINTLN(F("Hue reconnect"));
if (hueClient == nullptr) {
hueClient = new AsyncClient();
hueClient->onConnect(&onHueConnect, hueClient);
@ -47,13 +47,13 @@ void reconnectHue()
void onHueError(void* arg, AsyncClient* client, int8_t error)
{
DEBUG_PRINTLN("Hue err");
DEBUG_PRINTLN(F("Hue err"));
hueError = HUE_ERROR_TIMEOUT;
}
void onHueConnect(void* arg, AsyncClient* client)
{
DEBUG_PRINTLN("Hue connect");
DEBUG_PRINTLN(F("Hue connect"));
sendHuePoll();
}
@ -68,9 +68,10 @@ void sendHuePoll()
req += F("\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}");
} else
{
req += "GET /api/";
req += F("GET /api/");
req += hueApiKey;
req += "/lights/" + String(huePollLightId);
req += F("/lights/");
req += String(huePollLightId);
req += F(" HTTP/1.1\r\nHost: ");
req += hueIP.toString();
req += "\r\n\r\n";
@ -100,7 +101,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
hueError = HUE_ERROR_JSON_PARSING; return;
}
int hueErrorCode = root[0]["error"]["type"];
int hueErrorCode = root[0][F("error")][F("type")];
if (hueErrorCode)//hue bridge returned error
{
hueError = hueErrorCode;
@ -115,7 +116,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
if (hueAuthRequired)
{
const char* apikey = root[0]["success"]["username"];
const char* apikey = root[0][F("success")][F("username")];
if (apikey != nullptr && strlen(apikey) < sizeof(hueApiKey))
{
strcpy(hueApiKey, apikey);
@ -146,10 +147,10 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
{
hueBri = root["bri"];
hueBri++;
const char* cm =root["colormode"];
const char* cm =root[F("colormode")];
if (cm != nullptr) //Color device
{
if (strstr(cm,"ct") != nullptr) //ct mode
if (strstr(cm,("ct")) != nullptr) //ct mode
{
hueCt = root["ct"];
hueColormode = 3;
@ -160,8 +161,8 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
hueColormode = 1;
} else //hs mode
{
hueHue = root["hue"];
hueSat = root["sat"];
hueHue = root[F("hue")];
hueSat = root[F("sat")];
hueColormode = 2;
}
}

View file

@ -6,19 +6,19 @@
void deserializeSegment(JsonObject elem, byte it)
{
byte id = elem["id"] | it;
byte id = elem[F("id")] | it;
if (id < strip.getMaxSegments())
{
WS2812FX::Segment& seg = strip.getSegment(id);
uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
uint16_t start = elem[F("start")] | seg.start;
int stop = elem[F("stop")] | -1;
if (stop < 0) {
uint16_t len = elem["len"];
uint16_t len = elem[F("len")];
stop = (len > 0) ? start + len : seg.stop;
}
uint16_t grp = elem["grp"] | seg.grouping;
uint16_t spc = elem["spc"] | seg.spacing;
uint16_t grp = elem[F("grp")] | seg.grouping;
uint16_t spc = elem[F("spc")] | seg.spacing;
strip.setSegment(id, start, stop, grp, spc);
int segbri = elem["bri"] | -1;
@ -31,7 +31,7 @@ void deserializeSegment(JsonObject elem, byte it)
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON));
JsonArray colarr = elem["col"];
JsonArray colarr = elem[F("col")];
if (!colarr.isNull())
{
for (uint8_t i = 0; i < 3; i++)
@ -57,25 +57,25 @@ void deserializeSegment(JsonObject elem, byte it)
}
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(SEG_OPTION_SELECTED, elem["sel"] | seg.getOption(SEG_OPTION_SELECTED));
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
seg.setOption(SEG_OPTION_MIRROR , elem["mi"] | seg.getOption(SEG_OPTION_MIRROR ));
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
seg.setOption(SEG_OPTION_REVERSED, elem[F("rev")] | seg.getOption(SEG_OPTION_REVERSED));
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
//temporary, strip object gets updated via colorUpdated()
if (id == strip.getMainSegmentId()) {
effectCurrent = elem["fx"] | effectCurrent;
effectSpeed = elem["sx"] | effectSpeed;
effectIntensity = elem["ix"] | effectIntensity;
effectPalette = elem["pal"] | effectPalette;
effectCurrent = elem[F("fx")] | effectCurrent;
effectSpeed = elem[F("sx")] | effectSpeed;
effectIntensity = elem[F("ix")] | effectIntensity;
effectPalette = elem[F("pal")] | effectPalette;
} else { //permanent
byte fx = elem["fx"] | seg.mode;
byte fx = elem[F("fx")] | seg.mode;
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
seg.speed = elem["sx"] | seg.speed;
seg.intensity = elem["ix"] | seg.intensity;
seg.palette = elem["pal"] | seg.palette;
seg.speed = elem[F("sx")] | seg.speed;
seg.intensity = elem[F("ix")] | seg.intensity;
seg.palette = elem[F("pal")] | seg.palette;
}
JsonArray iarr = elem["i"]; //set individual LEDs
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
strip.setPixelSegment(id);
@ -127,9 +127,9 @@ void deserializeSegment(JsonObject elem, byte it)
bool deserializeState(JsonObject root)
{
strip.applyToAllSelected = false;
bool stateResponse = root["v"] | false;
bool stateResponse = root[F("v")] | false;
int ps = root["ps"] | -1;
int ps = root[F("ps")] | -1;
if (ps >= 0) applyPreset(ps);
bri = root["bri"] | bri;
@ -137,14 +137,14 @@ bool deserializeState(JsonObject root)
bool on = root["on"] | (bri > 0);
if (!on != !bri) toggleOnOff();
int tr = root["transition"] | -1;
int tr = root[F("transition")] | -1;
if (tr >= 0)
{
transitionDelay = tr;
transitionDelay *= 100;
}
tr = root["tt"] | -1;
tr = root[F("tt")] | -1;
if (tr >= 0)
{
transitionDelayTemp = tr;
@ -152,42 +152,42 @@ bool deserializeState(JsonObject root)
jsonTransitionOnce = true;
}
int cy = root["pl"] | -2;
int cy = root[F("pl")] | -2;
if (cy > -2) presetCyclingEnabled = (cy >= 0);
JsonObject ccnf = root["ccnf"];
presetCycleMin = ccnf["min"] | presetCycleMin;
presetCycleMax = ccnf["max"] | presetCycleMax;
tr = ccnf["time"] | -1;
JsonObject ccnf = root[F("ccnf")];
presetCycleMin = ccnf[F("min")] | presetCycleMin;
presetCycleMax = ccnf[F("max")] | presetCycleMax;
tr = ccnf[F("time")] | -1;
if (tr >= 2) presetCycleTime = tr;
JsonObject nl = root["nl"];
JsonObject nl = root[F("nl")];
nightlightActive = nl["on"] | nightlightActive;
nightlightDelayMins = nl["dur"] | nightlightDelayMins;
nightlightMode = nl["fade"] | nightlightMode; //deprecated
nightlightMode = nl["mode"] | nightlightMode;
nightlightTargetBri = nl["tbri"] | nightlightTargetBri;
nightlightDelayMins = nl[F("dur")] | nightlightDelayMins;
nightlightMode = nl[F("fade")] | nightlightMode; //deprecated
nightlightMode = nl[F("mode")] | nightlightMode;
nightlightTargetBri = nl[F("tbri")] | nightlightTargetBri;
JsonObject udpn = root["udpn"];
notifyDirect = udpn["send"] | notifyDirect;
receiveNotifications = udpn["recv"] | receiveNotifications;
bool noNotification = udpn["nn"]; //send no notification just for this request
JsonObject udpn = root[F("udpn")];
notifyDirect = udpn[F("send")] | notifyDirect;
receiveNotifications = udpn[F("recv")] | receiveNotifications;
bool noNotification = udpn[F("nn")]; //send no notification just for this request
int timein = root["time"] | -1;
int timein = root[F("time")] | -1;
if (timein != -1) setTime(timein);
doReboot = root["rb"] | doReboot;
doReboot = root[F("rb")] | doReboot;
realtimeOverride = root["lor"] | realtimeOverride;
realtimeOverride = root[F("lor")] | realtimeOverride;
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
byte prevMain = strip.getMainSegmentId();
strip.mainSegment = root["mainseg"] | prevMain;
strip.mainSegment = root[F("mainseg")] | prevMain;
if (strip.getMainSegmentId() != prevMain) setValuesFromMainSeg();
int it = 0;
JsonVariant segVar = root["seg"];
JsonVariant segVar = root[F("seg")];
if (segVar.is<JsonObject>())
{
int id = segVar["id"] | -1;
int id = segVar[F("id")] | -1;
if (id < 0) { //set all selected segments
bool didSet = false;
@ -222,9 +222,9 @@ bool deserializeState(JsonObject root)
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
//write presets to flash directly?
bool persistSaves = !(root["np"] | false);
bool persistSaves = !(root[F("np")] | false);
ps = root["psave"] | -1;
ps = root[F("psave")] | -1;
if (ps >= 0) savePreset(ps, persistSaves, root["n"], root["p"] | 50, root["o"].as<JsonObject>());
return stateResponse;
@ -232,12 +232,12 @@ bool deserializeState(JsonObject root)
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset)
{
root["id"] = id;
root["start"] = seg.start;
root["stop"] = seg.stop;
if (!forPreset) root["len"] = seg.stop - seg.start;
root["grp"] = seg.grouping;
root["spc"] = seg.spacing;
root[F("id")] = id;
root[F("start")] = seg.start;
root[F("stop")] = seg.stop;
if (!forPreset) root[F("len")] = seg.stop - seg.start;
root[F("grp")] = seg.grouping;
root[F("spc")] = seg.spacing;
root["on"] = seg.getOption(SEG_OPTION_ON);
byte segbri = seg.opacity;
root["bri"] = (segbri) ? segbri : 255;
@ -263,52 +263,52 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
}
}
root["fx"] = seg.mode;
root["sx"] = seg.speed;
root["ix"] = seg.intensity;
root["pal"] = seg.palette;
root["sel"] = seg.isSelected();
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
root["mi"] = seg.getOption(SEG_OPTION_MIRROR);
root[F("fx")] = seg.mode;
root[F("sx")] = seg.speed;
root[F("ix")] = seg.intensity;
root[F("pal")] = seg.palette;
root[F("sel")] = seg.isSelected();
root[F("rev")] = seg.getOption(SEG_OPTION_REVERSED);
root[F("mi")] = seg.getOption(SEG_OPTION_MIRROR);
}
void serializeState(JsonObject root, bool forPreset)
{
if (errorFlag) root[F("error")] = errorFlag;
root["on"] = (bri > 0);
root["bri"] = briLast;
root["transition"] = transitionDelay/100; //in 100ms
root[F("transition")] = transitionDelay/100; //in 100ms
if (!forPreset) {
if (errorFlag) root["error"] = errorFlag;
root["ps"] = currentPreset;
root["pss"] = savedPresets;
root["pl"] = (presetCyclingEnabled) ? 0: -1;
root[F("ps")] = currentPreset;
root[F("pss")] = savedPresets;
root[F("pl")] = (presetCyclingEnabled) ? 0: -1;
usermods.addToJsonState(root);
//temporary for preset cycle
JsonObject ccnf = root.createNestedObject("ccnf");
ccnf["min"] = presetCycleMin;
ccnf["max"] = presetCycleMax;
ccnf["time"] = presetCycleTime;
ccnf[F("min")] = presetCycleMin;
ccnf[F("max")] = presetCycleMax;
ccnf[F("time")] = presetCycleTime;
JsonObject nl = root.createNestedObject("nl");
nl["on"] = nightlightActive;
nl["dur"] = nightlightDelayMins;
nl["fade"] = (nightlightMode > NL_MODE_SET); //deprecated
nl["mode"] = nightlightMode;
nl["tbri"] = nightlightTargetBri;
JsonObject udpn = root.createNestedObject("udpn");
udpn["send"] = notifyDirect;
udpn["recv"] = receiveNotifications;
nl[F("dur")] = nightlightDelayMins;
nl[F("fade")] = (nightlightMode > NL_MODE_SET); //deprecated
nl[F("mode")] = nightlightMode;
nl[F("tbri")] = nightlightTargetBri;
root["lor"] = realtimeOverride;
JsonObject udpn = root.createNestedObject("udpn");
udpn[F("send")] = notifyDirect;
udpn[F("recv")] = receiveNotifications;
root[F("lor")] = realtimeOverride;
}
root["mainseg"] = strip.getMainSegmentId();
root[F("mainseg")] = strip.getMainSegmentId();
JsonArray seg = root.createNestedArray("seg");
for (byte s = 0; s < strip.getMaxSegments(); s++)
@ -344,61 +344,62 @@ int getSignalQuality(int rssi)
void serializeInfo(JsonObject root)
{
root["ver"] = versionString;
root["vid"] = VERSION;
//root["cn"] = WLED_CODENAME;
root[F("ver")] = versionString;
root[F("vid")] = VERSION;
//root[F("cn")] = WLED_CODENAME;
JsonObject leds = root.createNestedObject("leds");
leds["count"] = ledCount;
leds["rgbw"] = useRGBW;
leds["wv"] = useRGBW && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed?
leds[F("count")] = ledCount;
leds[F("rgbw")] = useRGBW;
leds[F("wv")] = useRGBW && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed?
JsonArray leds_pin = leds.createNestedArray("pin");
leds_pin.add(LEDPIN);
leds["pwr"] = strip.currentMilliamps;
leds["maxpwr"] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
leds["maxseg"] = strip.getMaxSegments();
leds["seglock"] = false; //will be used in the future to prevent modifications to segment config
leds[F("pwr")] = strip.currentMilliamps;
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
leds[F("maxseg")] = strip.getMaxSegments();
leds[F("seglock")] = false; //will be used in the future to prevent modifications to segment config
root["str"] = syncToggleReceive;
root[F("str")] = syncToggleReceive;
root["name"] = serverDescription;
root["udpport"] = udpPort;
root["live"] = (bool)realtimeMode;
root[F("name")] = serverDescription;
root[F("udpport")] = udpPort;
root[F("live")] = (bool)realtimeMode;
switch (realtimeMode) {
case REALTIME_MODE_INACTIVE: root["lm"] = ""; break;
case REALTIME_MODE_GENERIC: root["lm"] = ""; break;
case REALTIME_MODE_UDP: root["lm"] = "UDP"; break;
case REALTIME_MODE_HYPERION: root["lm"] = "Hyperion"; break;
case REALTIME_MODE_E131: root["lm"] = "E1.31"; break;
case REALTIME_MODE_UDP: root["lm"] = F("UDP"); break;
case REALTIME_MODE_HYPERION: root["lm"] = F("Hyperion"); break;
case REALTIME_MODE_E131: root["lm"] = F("E1.31"); break;
case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight/TPM2"); break;
case REALTIME_MODE_ARTNET: root["lm"] = "Art-Net"; break;
case REALTIME_MODE_ARTNET: root["lm"] = F("Art-Net"); break;
case REALTIME_MODE_TPM2NET: root["lm"] = F("tpm2.net"); break;
}
if (realtimeIP[0] == 0)
{
root["lip"] = "";
root[F("lip")] = "";
} else {
root["lip"] = realtimeIP.toString();
root[F("lip")] = realtimeIP.toString();
}
#ifdef WLED_ENABLE_WEBSOCKETS
root["ws"] = ws.count();
root[F("ws")] = ws.count();
#else
root["ws"] = -1;
root[F("ws")] = -1;
#endif
root["fxcount"] = strip.getModeCount();
root["palcount"] = strip.getPaletteCount();
root[F("fxcount")] = strip.getModeCount();
root[F("palcount")] = strip.getPaletteCount();
JsonObject wifi_info = root.createNestedObject("wifi");
wifi_info["bssid"] = WiFi.BSSIDstr();
wifi_info[F("bssid")] = WiFi.BSSIDstr();
int qrssi = WiFi.RSSI();
wifi_info["rssi"] = qrssi;
wifi_info["signal"] = getSignalQuality(qrssi);
wifi_info["channel"] = WiFi.channel();
wifi_info[F("rssi")] = qrssi;
wifi_info[F("signal")] = getSignalQuality(qrssi);
wifi_info[F("channel")] = WiFi.channel();
JsonObject fs_info = root.createNestedObject("fs");
FSInfo fsi;
@ -408,30 +409,31 @@ void serializeInfo(JsonObject root)
#ifdef ARDUINO_ARCH_ESP32
#ifdef WLED_DEBUG
wifi_info["txPower"] = (int) WiFi.getTxPower();
wifi_info["sleep"] = (bool) WiFi.getSleep();
wifi_info[F("txPower")] = (int) WiFi.getTxPower();
wifi_info[F("sleep")] = (bool) WiFi.getSleep();
#endif
root["arch"] = "esp32";
root["core"] = ESP.getSdkVersion();
//root["maxalloc"] = ESP.getMaxAllocHeap();
root[F("arch")] = "esp32";
root[F("core")] = ESP.getSdkVersion();
//root[F("maxalloc")] = ESP.getMaxAllocHeap();
#ifdef WLED_DEBUG
root["resetReason0"] = (int)rtc_get_reset_reason(0);
root["resetReason1"] = (int)rtc_get_reset_reason(1);
root[F("resetReason0")] = (int)rtc_get_reset_reason(0);
root[F("resetReason1")] = (int)rtc_get_reset_reason(1);
#endif
root["lwip"] = 0;
root[F("lwip")] = 0;
#else
root["arch"] = "esp8266";
root["core"] = ESP.getCoreVersion();
//root["maxalloc"] = ESP.getMaxFreeBlockSize();
root[F("arch")] = "esp8266";
root[F("core")] = ESP.getCoreVersion();
//root[F("maxalloc")] = ESP.getMaxFreeBlockSize();
#ifdef WLED_DEBUG
root["resetReason"] = (int)ESP.getResetInfoPtr()->reason;
root[F("resetReason")] = (int)ESP.getResetInfoPtr()->reason;
#endif
root["lwip"] = LWIP_VERSION_MAJOR;
root[F("lwip")] = LWIP_VERSION_MAJOR;
#endif
root["freeheap"] = ESP.getFreeHeap();
root["uptime"] = millis()/1000 + rolloverMillis*4294967;
root[F("freeheap")] = ESP.getFreeHeap();
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
usermods.addToJsonInfo(root);
byte os = 0;
@ -459,11 +461,11 @@ void serializeInfo(JsonObject root)
#ifndef WLED_DISABLE_OTA
os += 0x01;
#endif
root["opt"] = os;
root[F("opt")] = os;
root["brand"] = "WLED";
root["product"] = "FOSS";
root["mac"] = escapedMac;
root[F("brand")] = "WLED";
root[F("product")] = F("FOSS");
root[F("mac")] = escapedMac;
}
void serveJson(AsyncWebServerRequest* request)
@ -477,11 +479,11 @@ void serveJson(AsyncWebServerRequest* request)
serveLiveLeds(request);
return;
}
else if (url.indexOf("eff") > 0) {
else if (url.indexOf(F("eff")) > 0) {
request->send_P(200, "application/json", JSON_mode_names);
return;
}
else if (url.indexOf("pal") > 0) {
else if (url.indexOf(F("pal")) > 0) {
request->send_P(200, "application/json", JSON_palette_names);
return;
}
@ -490,7 +492,7 @@ void serveJson(AsyncWebServerRequest* request)
return;
}
AsyncJsonResponse* response = new AsyncJsonResponse();
AsyncJsonResponse* response = new AsyncJsonResponse(JSON_BUFFER_SIZE);
JsonObject doc = response->getRoot();
switch (subJson)
@ -506,8 +508,8 @@ void serveJson(AsyncWebServerRequest* request)
serializeInfo(info);
if (subJson != 3)
{
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
doc[F("effects")] = serialized((const __FlashStringHelper*)JSON_mode_names);
doc[F("palettes")] = serialized((const __FlashStringHelper*)JSON_palette_names);
}
}
@ -529,7 +531,8 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
uint16_t used = ledCount;
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
char buffer[2000] = "{\"leds\":[";
char buffer[2000];
strcpy_P(buffer, PSTR("{\"leds\":["));
obuf = buffer;
olen = 9;
@ -538,7 +541,7 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
olen += sprintf(obuf + olen, "\"%06X\",", strip.getPixelColor(i));
}
olen -= 1;
oappend("],\"n\":");
oappend((const char*)F("],\"n\":"));
oappendi(n);
oappend("}");
if (request) {

View file

@ -48,18 +48,18 @@ void onMqttConnect(bool sessionPresent)
}
doPublishMqtt = true;
DEBUG_PRINTLN("MQTT ready");
DEBUG_PRINTLN(F("MQTT ready"));
}
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
DEBUG_PRINT("MQTT msg: ");
DEBUG_PRINT(F("MQTT msg: "));
DEBUG_PRINTLN(topic);
// paranoia check to avoid npe if no payload
if (payload==nullptr) {
DEBUG_PRINTLN("no payload -> leave");
DEBUG_PRINTLN(F("no payload -> leave"));
return;
}
DEBUG_PRINTLN(payload);
@ -83,7 +83,7 @@ void publishMqtt()
{
doPublishMqtt = false;
if (!WLED_MQTT_CONNECTED) return;
DEBUG_PRINTLN("Publish MQTT");
DEBUG_PRINTLN(F("Publish MQTT"));
char s[10];
char subuf[38];
@ -100,7 +100,7 @@ void publishMqtt()
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/status");
mqtt->publish(subuf, 0, true, "online");
mqtt->publish(subuf, 0, true, (const char*)F("online"));
char apires[1024];
XML_response(nullptr, apires);
@ -124,7 +124,7 @@ bool initMqtt()
}
if (mqtt->connected()) return true;
DEBUG_PRINTLN("Reconnecting MQTT");
DEBUG_PRINTLN(F("Reconnecting MQTT"));
IPAddress mqttIP;
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
{
@ -137,7 +137,7 @@ bool initMqtt()
strcpy(mqttStatusTopic, mqttDeviceTopic);
strcat(mqttStatusTopic, "/status");
mqtt->setWill(mqttStatusTopic, 0, true, "offline");
mqtt->setWill(mqttStatusTopic, 0, true, (const char*)F("offline"));
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
mqtt->connect();
return true;

View file

@ -4,69 +4,127 @@
/*
* Acquires time from NTP server
*/
Timezone* tz;
TimeChangeRule UTCr = {Last, Sun, Mar, 1, 0}; // UTC
Timezone tzUTC(UTCr, UTCr);
#define TZ_UTC 0
#define TZ_UK 1
#define TZ_EUROPE_CENTRAL 2
#define TZ_EUROPE_EASTERN 3
#define TZ_US_EASTERN 4
#define TZ_US_CENTRAL 5
#define TZ_US_MOUNTAIN 6
#define TZ_US_ARIZONA 7
#define TZ_US_PACIFIC 8
#define TZ_CHINA 9
#define TZ_JAPAN 10
#define TZ_AUSTRALIA_EASTERN 11
#define TZ_NEW_ZEALAND 12
#define TZ_NORTH_KOREA 13
#define TZ_INDIA 14
#define TZ_SASKACHEWAN 15
#define TZ_AUSTRALIA_NORTHERN 16
#define TZ_AUSTRALIA_SOUTHERN 17
#define TZ_INIT 255
TimeChangeRule BST = {Last, Sun, Mar, 1, 60}; // British Summer Time
TimeChangeRule GMT = {Last, Sun, Oct, 2, 0}; // Standard Time
Timezone tzUK(BST, GMT);
byte tzCurrent = TZ_INIT; //uninitialized
TimeChangeRule CEST = {Last, Sun, Mar, 2, 120}; //Central European Summer Time
TimeChangeRule CET = {Last, Sun, Oct, 3, 60}; //Central European Standard Time
Timezone tzEUCentral(CEST, CET);
void updateTimezone() {
delete tz;
TimeChangeRule tcrDaylight = {Last, Sun, Mar, 1, 0}; //UTC
TimeChangeRule tcrStandard = tcrDaylight; //UTC
TimeChangeRule EEST = {Last, Sun, Mar, 3, 180}; //Central European Summer Time
TimeChangeRule EET = {Last, Sun, Oct, 4, 120}; //Central European Standard Time
Timezone tzEUEastern(EEST, EET);
switch (currentTimezone) {
case TZ_UK : {
tcrDaylight = {Last, Sun, Mar, 1, 60}; //British Summer Time
tcrStandard = {Last, Sun, Oct, 2, 0}; //Standard Time
break;
}
case TZ_EUROPE_CENTRAL : {
tcrDaylight = {Last, Sun, Mar, 2, 120}; //Central European Summer Time
tcrStandard = {Last, Sun, Oct, 3, 60}; //Central European Standard Time
break;
}
case TZ_EUROPE_EASTERN : {
tcrDaylight = {Last, Sun, Mar, 3, 180}; //East European Summer Time
tcrStandard = {Last, Sun, Oct, 4, 120}; //East European Standard Time
break;
}
case TZ_US_EASTERN : {
tcrDaylight = {Second, Sun, Mar, 2, -240}; //EDT = UTC - 4 hours
tcrStandard = {First, Sun, Nov, 2, -300}; //EST = UTC - 5 hours
break;
}
case TZ_US_CENTRAL : {
tcrDaylight = {Second, Sun, Mar, 2, -300}; //CDT = UTC - 5 hours
tcrStandard = {First, Sun, Nov, 2, -360}; //CST = UTC - 6 hours
break;
}
case TZ_US_MOUNTAIN : {
tcrDaylight = {Second, Sun, Mar, 2, -360}; //MDT = UTC - 6 hours
tcrStandard = {First, Sun, Nov, 2, -420}; //MST = UTC - 7 hours
break;
}
case TZ_US_ARIZONA : {
tcrDaylight = {First, Sun, Nov, 2, -420}; //MST = UTC - 7 hours
tcrStandard = {First, Sun, Nov, 2, -420}; //MST = UTC - 7 hours
break;
}
case TZ_US_PACIFIC : {
tcrDaylight = {Second, Sun, Mar, 2, -420}; //PDT = UTC - 7 hours
tcrStandard = {First, Sun, Nov, 2, -480}; //PST = UTC - 8 hours
break;
}
case TZ_CHINA : {
tcrDaylight = {Last, Sun, Mar, 1, 480}; //CST = UTC + 8 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_JAPAN : {
tcrDaylight = {Last, Sun, Mar, 1, 540}; //JST = UTC + 9 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_AUSTRALIA_EASTERN : {
tcrDaylight = {Second, Sun, Oct, 2, 660}; //AEDT = UTC + 11 hours
tcrStandard = {First, Sun, Apr, 3, 600}; //AEST = UTC + 10 hours
break;
}
case TZ_NEW_ZEALAND : {
tcrDaylight = {Second, Sun, Sep, 2, 780}; //NZDT = UTC + 13 hours
tcrStandard = {First, Sun, Apr, 3, 720}; //NZST = UTC + 12 hours
break;
}
case TZ_NORTH_KOREA : {
tcrDaylight = {Last, Sun, Mar, 1, 510}; //Pyongyang Time = UTC + 8.5 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_INDIA : {
tcrDaylight = {Last, Sun, Mar, 1, 330}; //India Standard Time = UTC + 5.5 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_SASKACHEWAN : {
tcrDaylight = {First, Sun, Nov, 2, -360}; //CST = UTC - 6 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_AUSTRALIA_NORTHERN : {
tcrStandard = {First, Sun, Apr, 3, 570}; //ACST = UTC + 9.5 hours
tcrStandard = tcrDaylight;
break;
}
case TZ_AUSTRALIA_SOUTHERN : {
tcrDaylight = {First, Sun, Oct, 2, 630}; //ACDT = UTC + 10.5 hours
tcrStandard = {First, Sun, Apr, 3, 570}; //ACST = UTC + 9.5 hours
break;
}
}
TimeChangeRule EDT = {Second, Sun, Mar, 2, -240 }; //Daylight time = UTC - 4 hours
TimeChangeRule EST = {First, Sun, Nov, 2, -300 }; //Standard time = UTC - 5 hours
Timezone tzUSEastern(EDT, EST);
tzCurrent = currentTimezone;
TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 }; //Daylight time = UTC - 5 hours
TimeChangeRule CST = {First, Sun, Nov, 2, -360 }; //Standard time = UTC - 6 hours
Timezone tzUSCentral(CDT, CST);
Timezone tzCASaskatchewan(CST, CST); //Central without DST
TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 }; //Daylight time = UTC - 6 hours
TimeChangeRule MST = {First, Sun, Nov, 2, -420 }; //Standard time = UTC - 7 hours
Timezone tzUSMountain(MDT, MST);
Timezone tzUSArizona(MST, MST); //Mountain without DST
TimeChangeRule PDT = {Second, Sun, Mar, 2, -420 }; //Daylight time = UTC - 7 hours
TimeChangeRule PST = {First, Sun, Nov, 2, -480 }; //Standard time = UTC - 8 hours
Timezone tzUSPacific(PDT, PST);
TimeChangeRule ChST = {Last, Sun, Mar, 1, 480}; // China Standard Time = UTC + 8 hours
Timezone tzChina(ChST, ChST);
TimeChangeRule JST = {Last, Sun, Mar, 1, 540}; // Japan Standard Time = UTC + 9 hours
Timezone tzJapan(JST, JST);
TimeChangeRule AEDT = {Second, Sun, Oct, 2, 660 }; //Daylight time = UTC + 11 hours
TimeChangeRule AEST = {First, Sun, Apr, 3, 600 }; //Standard time = UTC + 10 hours
Timezone tzAUEastern(AEDT, AEST);
TimeChangeRule NZDT = {Second, Sun, Sep, 2, 780 }; //Daylight time = UTC + 13 hours
TimeChangeRule NZST = {First, Sun, Apr, 3, 720 }; //Standard time = UTC + 12 hours
Timezone tzNZ(NZDT, NZST);
TimeChangeRule NKST = {Last, Sun, Mar, 1, 510}; //Pyongyang Time = UTC + 8.5 hours
Timezone tzNK(NKST, NKST);
TimeChangeRule IST = {Last, Sun, Mar, 1, 330}; // India Standard Time = UTC + 5.5 hours
Timezone tzIndia(IST, IST);
TimeChangeRule ACST = {First, Sun, Apr, 3, 570}; //Australian Central Standard = UTC + 9.5 hours
TimeChangeRule ACDT = {First, Sun, Oct, 2, 630}; //Australian Central Daylight = UTC + 10.5 hours
Timezone tzAUNorthern(ACST, ACST);
Timezone tzAUSouthern(ACDT, ACST);
// Pick your timezone from here.
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan, &tzAUNorthern, &tzAUSouthern};
tz = new Timezone(tcrDaylight, tcrStandard);
}
void handleNetworkTime()
{
@ -95,7 +153,7 @@ void sendNTPPacket()
#endif
}
DEBUG_PRINTLN("send NTP");
DEBUG_PRINTLN(F("send NTP"));
byte pbuf[NTP_PACKET_SIZE];
memset(pbuf, 0, NTP_PACKET_SIZE);
@ -118,7 +176,7 @@ bool checkNTPResponse()
{
int cb = ntpUdp.parsePacket();
if (cb) {
DEBUG_PRINT("NTP recv, l=");
DEBUG_PRINT(F("NTP recv, l="));
DEBUG_PRINTLN(cb);
byte pbuf[NTP_PACKET_SIZE];
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
@ -129,7 +187,7 @@ bool checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord;
DEBUG_PRINT("Unix time = ");
DEBUG_PRINT(F("Unix time = "));
unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
setTime(epoch);
DEBUG_PRINTLN(epoch);
@ -141,8 +199,9 @@ bool checkNTPResponse()
void updateLocalTime()
{
if (currentTimezone != tzCurrent) updateTimezone();
unsigned long tmc = now()+ utcOffsetSecs;
localTime = timezones[currentTimezone]->toLocal(tmc);
localTime = tz->toLocal(tmc);
}
void getTimeString(char* out)
@ -165,7 +224,8 @@ void getTimeString(char* out)
void setCountdown()
{
countdownTime = timezones[currentTimezone]->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear));
if (currentTimezone != tzCurrent) updateTimezone();
countdownTime = tz->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear));
if (countdownTime - now() > 0) countdownOverTriggered = false;
}

View file

@ -37,20 +37,20 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//WIFI SETTINGS
if (subPage == 1)
{
strlcpy(clientSSID,request->arg("CS").c_str(), 33);
strlcpy(clientSSID,request->arg(F("CS")).c_str(), 33);
if (!isAsterisksOnly(request->arg("CP").c_str(), 65)) strlcpy(clientPass, request->arg("CP").c_str(), 65);
if (!isAsterisksOnly(request->arg(F("CP")).c_str(), 65)) strlcpy(clientPass, request->arg(F("CP")).c_str(), 65);
strlcpy(cmDNS, request->arg("CM").c_str(), 33);
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
apBehavior = request->arg("AB").toInt();
strlcpy(apSSID, request->arg("AS").c_str(), 33);
apHide = request->hasArg("AH");
int passlen = request->arg("AP").length();
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg("AP").c_str(), 65))) strlcpy(apPass, request->arg("AP").c_str(), 65);
int t = request->arg("AC").toInt(); if (t > 0 && t < 14) apChannel = t;
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("WS");
noWifiSleep = request->hasArg(F("WS"));
char k[3]; k[2] = 0;
for (int i = 0; i<4; i++)
@ -71,110 +71,110 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//LED SETTINGS
if (subPage == 2)
{
int t = request->arg("LC").toInt();
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("MA").toInt();
strip.milliampsPerLed = request->arg("LA").toInt();
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
strip.milliampsPerLed = request->arg(F("LA")).toInt();
useRGBW = request->hasArg("EW");
strip.colorOrder = request->arg("CO").toInt();
strip.rgbwMode = request->arg("AW").toInt();
useRGBW = request->hasArg(F("EW"));
strip.colorOrder = request->arg(F("CO")).toInt();
strip.rgbwMode = request->arg(F("AW")).toInt();
briS = request->arg("CA").toInt();
briS = request->arg(F("CA")).toInt();
saveCurrPresetCycConf = request->hasArg("PC");
turnOnAtBoot = request->hasArg("BO");
t = request->arg("BP").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("GB");
strip.gammaCorrectCol = request->hasArg("GC");
strip.gammaCorrectBri = request->hasArg(F("GB"));
strip.gammaCorrectCol = request->hasArg(F("GC"));
fadeTransition = request->hasArg("TF");
t = request->arg("TD").toInt();
fadeTransition = request->hasArg(F("TF"));
t = request->arg(F("TD")).toInt();
if (t > 0) transitionDelay = t;
transitionDelayDefault = t;
strip.paletteFade = request->hasArg("PF");
strip.paletteFade = request->hasArg(F("PF"));
nightlightTargetBri = request->arg("TB").toInt();
t = request->arg("TL").toInt();
nightlightTargetBri = request->arg(F("TB")).toInt();
t = request->arg(F("TL")).toInt();
if (t > 0) nightlightDelayMinsDefault = t;
nightlightDelayMins = nightlightDelayMinsDefault;
nightlightMode = request->arg("TW").toInt();
nightlightMode = request->arg(F("TW")).toInt();
t = request->arg("PB").toInt();
t = request->arg(F("PB")).toInt();
if (t >= 0 && t < 4) strip.paletteBlend = t;
strip.reverseMode = request->hasArg("RV");
skipFirstLed = request->hasArg("SL");
t = request->arg("BF").toInt();
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("DS").c_str(), 33);
syncToggleReceive = request->hasArg("ST");
strlcpy(serverDescription, request->arg(F("DS")).c_str(), 33);
syncToggleReceive = request->hasArg(F("ST"));
}
//SYNC
if (subPage == 4)
{
buttonEnabled = request->hasArg("BT");
irEnabled = request->arg("IR").toInt();
int t = request->arg("UP").toInt();
buttonEnabled = request->hasArg(F("BT"));
irEnabled = request->arg(F("IR")).toInt();
int t = request->arg(F("UP")).toInt();
if (t > 0) udpPort = t;
receiveNotificationBrightness = request->hasArg("RB");
receiveNotificationColor = request->hasArg("RC");
receiveNotificationEffects = request->hasArg("RX");
receiveNotificationBrightness = request->hasArg(F("RB"));
receiveNotificationColor = request->hasArg(F("RC"));
receiveNotificationEffects = request->hasArg(F("RX"));
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
notifyDirectDefault = request->hasArg("SD");
notifyDirectDefault = request->hasArg(F("SD"));
notifyDirect = notifyDirectDefault;
notifyButton = request->hasArg("SB");
notifyAlexa = request->hasArg("SA");
notifyHue = request->hasArg("SH");
notifyMacro = request->hasArg("SM");
notifyTwice = request->hasArg("S2");
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("RD");
e131SkipOutOfSequence = request->hasArg("ES");
e131Multicast = request->hasArg("EM");
t = request->arg("EP").toInt();
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("EU").toInt();
t = request->arg(F("EU")).toInt();
if (t >= 0 && t <= 63999) e131Universe = t;
t = request->arg("DA").toInt();
t = request->arg(F("DA")).toInt();
if (t >= 0 && t <= 510) DMXAddress = t;
t = request->arg("DM").toInt();
t = request->arg(F("DM")).toInt();
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_DRGB) DMXMode = t;
t = request->arg("ET").toInt();
t = request->arg(F("ET")).toInt();
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
arlsForceMaxBri = request->hasArg("FB");
arlsDisableGammaCorrection = request->hasArg("RG");
t = request->arg("WO").toInt();
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("AL");
strlcpy(alexaInvocationName, request->arg("AI").c_str(), 33);
alexaEnabled = request->hasArg(F("AL"));
strlcpy(alexaInvocationName, request->arg(F("AI")).c_str(), 33);
if (request->hasArg("BK") && !request->arg("BK").equals("Hidden")) {
if (request->hasArg("BK") && !request->arg("BK").equals(F("Hidden"))) {
strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey);
}
#ifdef WLED_ENABLE_MQTT
mqttEnabled = request->hasArg("MQ");
strlcpy(mqttServer, request->arg("MS").c_str(), 33);
t = request->arg("MQPORT").toInt();
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("MQUSER").c_str(), 41);
if (!isAsterisksOnly(request->arg("MQPASS").c_str(), 41)) strlcpy(mqttPass, request->arg("MQPASS").c_str(), 41);
strlcpy(mqttClientID, request->arg("MQCID").c_str(), 41);
strlcpy(mqttDeviceTopic, request->arg("MD").c_str(), 33);
strlcpy(mqttGroupTopic, request->arg("MG").c_str(), 33);
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
@ -183,16 +183,16 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
hueIP[i] = request->arg(a).toInt();
}
t = request->arg("HL").toInt();
t = request->arg(F("HL")).toInt();
if (t > 0) huePollLightId = t;
t = request->arg("HI").toInt();
t = request->arg(F("HI")).toInt();
if (t > 50) huePollIntervalMs = t;
hueApplyOnOff = request->hasArg("HO");
hueApplyBri = request->hasArg("HB");
hueApplyColor = request->hasArg("HC");
huePollingEnabled = request->hasArg("HP");
hueApplyOnOff = request->hasArg(F("HO"));
hueApplyBri = request->hasArg(F("HB"));
hueApplyColor = request->hasArg(F("HC"));
huePollingEnabled = request->hasArg(F("HP"));
hueStoreAllowed = true;
reconnectHue();
#endif
@ -201,35 +201,35 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//TIME
if (subPage == 5)
{
ntpEnabled = request->hasArg("NT");
strlcpy(ntpServerName, request->arg("NS").c_str(), 33);
useAMPM = !request->hasArg("CF");
currentTimezone = request->arg("TZ").toInt();
utcOffsetSecs = request->arg("UO").toInt();
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("OL")){
overlayDefault = request->arg("OL").toInt();
if (request->hasArg(F("OL"))) {
overlayDefault = request->arg(F("OL")).toInt();
overlayCurrent = overlayDefault;
}
overlayMin = request->arg("O1").toInt();
overlayMax = request->arg("O2").toInt();
analogClock12pixel = request->arg("OM").toInt();
analogClock5MinuteMarks = request->hasArg("O5");
analogClockSecondsTrail = request->hasArg("OS");
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("CX").c_str());
cronixieBacklight = request->hasArg("CB");
countdownMode = request->hasArg("CE");
countdownYear = request->arg("CY").toInt();
countdownMonth = request->arg("CI").toInt();
countdownDay = request->arg("CD").toInt();
countdownHour = request->arg("CH").toInt();
countdownMin = request->arg("CM").toInt();
countdownSec = request->arg("CS").toInt();
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();
for (int i=1;i<17;i++)
{
@ -237,14 +237,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
if (request->hasArg(a.c_str())) saveMacro(i,request->arg(a),false);
}
macroBoot = request->arg("MB").toInt();
macroAlexaOn = request->arg("A0").toInt();
macroAlexaOff = request->arg("A1").toInt();
macroButton = request->arg("MP").toInt();
macroLongPress = request->arg("ML").toInt();
macroCountdown = request->arg("MC").toInt();
macroNl = request->arg("MN").toInt();
macroDoublePress = request->arg("MD").toInt();
macroBoot = request->arg(F("MB")).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++)
@ -268,52 +268,52 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//SECURITY
if (subPage == 6)
{
if (request->hasArg("RS")) //complete factory reset
if (request->hasArg(F("RS"))) //complete factory reset
{
clearEEPROM();
serveMessage(request, 200, "All Settings erased.", "Connect to WLED-AP to setup again",255);
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("OP"))
if (request->hasArg(F("OP")))
{
if (otaLock && strcmp(otaPass,request->arg("OP").c_str()) == 0)
if (otaLock && strcmp(otaPass,request->arg(F("OP")).c_str()) == 0)
{
pwdCorrect = true;
}
if (!otaLock && request->arg("OP").length() > 0)
if (!otaLock && request->arg(F("OP")).length() > 0)
{
strlcpy(otaPass,request->arg("OP").c_str(), 33);
strlcpy(otaPass,request->arg(F("OP")).c_str(), 33);
}
}
if (pwdCorrect) //allow changes if correct pwd or no ota active
{
otaLock = request->hasArg("NO");
wifiLock = request->hasArg("OW");
aOtaEnabled = request->hasArg("AO");
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("PU").toInt();
int t = request->arg(F("PU")).toInt();
if (t >= 0 && t <= 63999) e131ProxyUniverse = t;
t = request->arg("CN").toInt();
t = request->arg(F("CN")).toInt();
if (t>0 && t<16) {
DMXChannels = t;
}
t = request->arg("CS").toInt();
t = request->arg(F("CS")).toInt();
if (t>0 && t<513) {
DMXStart = t;
}
t = request->arg("CG").toInt();
t = request->arg(F("CG")).toInt();
if (t>0 && t<513) {
DMXGap = t;
}
t = request->arg("SL").toInt();
t = request->arg(F("SL")).toInt();
if (t>=0 && t < MAX_LEDS) {
DMXStartLED = t;
}
@ -377,18 +377,18 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (!(req.indexOf("win") >= 0)) return false;
int pos = 0;
DEBUG_PRINT("API req: ");
DEBUG_PRINT(F("API req: "));
DEBUG_PRINTLN(req);
//write presets and macros saved to flash directly?
bool persistSaves = true;
pos = req.indexOf("NP");
pos = req.indexOf(F("NP"));
if (pos > 0) {
persistSaves = false;
}
//save macro, requires &MS=<slot>(<macro>) format
pos = req.indexOf("&MS=");
pos = req.indexOf(F("&MS="));
if (pos > 0) {
int i = req.substring(pos + 4).toInt();
pos = req.indexOf('(') +1;
@ -399,7 +399,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
saveMacro(i, mc, persistSaves);
}
pos = req.indexOf("IN");
pos = req.indexOf(F("IN"));
if (pos < 1) XML_response(request);
return true;
//if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise
@ -409,21 +409,21 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
//segment select (sets main segment)
byte prevMain = strip.getMainSegmentId();
pos = req.indexOf("SM=");
pos = req.indexOf(F("SM="));
if (pos > 0) {
strip.mainSegment = getNumVal(&req, pos);
}
byte main = strip.getMainSegmentId();
if (main != prevMain) setValuesFromMainSeg();
pos = req.indexOf("SS=");
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("SV="); //segment selected
pos = req.indexOf(F("SV=")); //segment selected
if (pos > 0) {
byte t = getNumVal(&req, pos);
if (t == 2) {
@ -439,20 +439,20 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
uint16_t stopI = mainseg.stop;
uint8_t grpI = mainseg.grouping;
uint16_t spcI = mainseg.spacing;
pos = req.indexOf("&S="); //segment start
pos = req.indexOf(F("&S=")); //segment start
if (pos > 0) {
startI = getNumVal(&req, pos);
}
pos = req.indexOf("S2="); //segment stop
pos = req.indexOf(F("S2=")); //segment stop
if (pos > 0) {
stopI = getNumVal(&req, pos);
}
pos = req.indexOf("GP="); //segment grouping
pos = req.indexOf(F("GP=")); //segment grouping
if (pos > 0) {
grpI = getNumVal(&req, pos);
if (grpI == 0) grpI = 1;
}
pos = req.indexOf("SP="); //segment spacing
pos = req.indexOf(F("SP=")); //segment spacing
if (pos > 0) {
spcI = getNumVal(&req, pos);
}
@ -461,30 +461,32 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
main = strip.getMainSegmentId();
//set presets
pos = req.indexOf("P1="); //sets first preset for cycle
pos = req.indexOf(F("P1=")); //sets first preset for cycle
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
pos = req.indexOf("P2="); //sets last preset for cycle
pos = req.indexOf(F("P2=")); //sets last preset for cycle
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
//preset cycle
pos = req.indexOf("CY=");
pos = req.indexOf(F("CY="));
if (pos > 0)
{
presetCyclingEnabled = (req.charAt(pos+3) != '0');
char cmd = req.charAt(pos+3);
if (cmd == '2') presetCyclingEnabled = !presetCyclingEnabled;
else presetCyclingEnabled = (cmd != '0');
presetCycCurr = presetCycleMin;
}
pos = req.indexOf("PT="); //sets cycle time in ms
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("PA="); //apply brightness from preset
pos = req.indexOf(F("PA=")); //apply brightness from preset
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
pos = req.indexOf("PS="); //saves current in preset
pos = req.indexOf(F("PS=")); //saves current in preset
if (pos > 0) savePreset(getNumVal(&req, pos), persistSaves);
//apply preset
@ -506,27 +508,27 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
updateVal(&req, "W2=", &colSec[3]);
//set hue
pos = req.indexOf("HU=");
pos = req.indexOf(F("HU="));
if (pos > 0) {
uint16_t temphue = getNumVal(&req, pos);
byte tempsat = 255;
pos = req.indexOf("SA=");
pos = req.indexOf(F("SA="));
if (pos > 0) {
tempsat = getNumVal(&req, pos);
}
colorHStoRGB(temphue,tempsat,(req.indexOf("H2")>0)? colSec:col);
colorHStoRGB(temphue,tempsat,(req.indexOf(F("H2"))>0)? colSec:col);
}
//set color from HEX or 32bit DEC
pos = req.indexOf("CL=");
pos = req.indexOf(F("CL="));
if (pos > 0) {
colorFromDecOrHexString(col, (char*)req.substring(pos + 3).c_str());
}
pos = req.indexOf("C2=");
pos = req.indexOf(F("C2="));
if (pos > 0) {
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
}
pos = req.indexOf("C3=");
pos = req.indexOf(F("C3="));
if (pos > 0) {
byte t[4];
colorFromDecOrHexString(t, (char*)req.substring(pos + 3).c_str());
@ -534,13 +536,13 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
//set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf("SR");
pos = req.indexOf(F("SR"));
if (pos > 0) {
_setRandomColor(getNumVal(&req, pos));
}
//swap 2nd & 1st
pos = req.indexOf("SC");
pos = req.indexOf(F("SC"));
if (pos > 0) {
byte temp;
for (uint8_t i=0; i<4; i++)
@ -558,33 +560,33 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
updateVal(&req, "FP=", &effectPalette, 0, strip.getPaletteCount()-1);
//set advanced overlay
pos = req.indexOf("OL=");
pos = req.indexOf(F("OL="));
if (pos > 0) {
overlayCurrent = getNumVal(&req, pos);
}
//apply macro
pos = req.indexOf("&M=");
pos = req.indexOf(F("&M="));
if (pos > 0) {
applyMacro(getNumVal(&req, pos));
}
//toggle send UDP direct notifications
pos = req.indexOf("SN=");
pos = req.indexOf(F("SN="));
if (pos > 0) notifyDirect = (req.charAt(pos+3) != '0');
//toggle receive UDP direct notifications
pos = req.indexOf("RN=");
pos = req.indexOf(F("RN="));
if (pos > 0) receiveNotifications = (req.charAt(pos+3) != '0');
//receive live data via UDP/Hyperion
pos = req.indexOf("RD=");
pos = req.indexOf(F("RD="));
if (pos > 0) receiveDirect = (req.charAt(pos+3) != '0');
//toggle nightlight mode
bool aNlDef = false;
if (req.indexOf("&ND") > 0) aNlDef = true;
pos = req.indexOf("NL=");
if (req.indexOf(F("&ND")) > 0) aNlDef = true;
pos = req.indexOf(F("NL="));
if (pos > 0)
{
if (req.charAt(pos+3) == '0')
@ -603,14 +605,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
//set nightlight target brightness
pos = req.indexOf("NT=");
pos = req.indexOf(F("NT="));
if (pos > 0) {
nightlightTargetBri = getNumVal(&req, pos);
nightlightActiveOld = false; //re-init
}
//toggle nightlight fade
pos = req.indexOf("NF=");
pos = req.indexOf(F("NF="));
if (pos > 0)
{
nightlightMode = getNumVal(&req, pos);
@ -621,7 +623,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
#if AUXPIN >= 0
//toggle general purpose output
pos = req.indexOf("AX=");
pos = req.indexOf(F("AX="));
if (pos > 0) {
auxTime = getNumVal(&req, pos);
auxActive = true;
@ -629,11 +631,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
#endif
pos = req.indexOf("TT=");
pos = req.indexOf(F("TT="));
if (pos > 0) transitionDelay = getNumVal(&req, pos);
//main toggle on/off
pos = req.indexOf("&T=");
pos = req.indexOf(F("&T="));
if (pos > 0) {
nightlightActive = false; //always disable nightlight when toggling
switch (getNumVal(&req, pos))
@ -645,15 +647,15 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
//Segment reverse
pos = req.indexOf("RV=");
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("MI=");
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("SB=");
pos = req.indexOf(F("SB="));
if (pos > 0) {
byte segbri = getNumVal(&req, pos);
strip.getSegment(main).setOption(SEG_OPTION_ON, segbri);
@ -663,40 +665,40 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
//set time (unix timestamp)
pos = req.indexOf("ST=");
pos = req.indexOf(F("ST="));
if (pos > 0) {
setTime(getNumVal(&req, pos));
}
//set countdown goal (unix timestamp)
pos = req.indexOf("CT=");
pos = req.indexOf(F("CT="));
if (pos > 0) {
countdownTime = getNumVal(&req, pos);
if (countdownTime - now() > 0) countdownOverTriggered = false;
}
pos = req.indexOf("LO=");
pos = req.indexOf(F("LO="));
if (pos > 0) {
realtimeOverride = getNumVal(&req, pos);
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
}
pos = req.indexOf("RB");
pos = req.indexOf(F("RB"));
if (pos > 0) doReboot = true;
//cronixie
#ifndef WLED_DISABLE_CRONIXIE
//mode, 1 countdown
pos = req.indexOf("NM=");
pos = req.indexOf(F("NM="));
if (pos > 0) countdownMode = (req.charAt(pos+3) != '0');
pos = req.indexOf("NX="); //sets digits to code
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("NB=");
pos = req.indexOf(F("NB="));
if (pos > 0) //sets backlight
{
cronixieBacklight = (req.charAt(pos+3) != '0');
@ -704,22 +706,22 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
}
#endif
pos = req.indexOf("U0="); //user var 0
pos = req.indexOf(F("U0=")); //user var 0
if (pos > 0) {
userVar0 = getNumVal(&req, pos);
}
pos = req.indexOf("U1="); //user var 1
pos = req.indexOf(F("U1=")); //user var 1
if (pos > 0) {
userVar1 = getNumVal(&req, pos);
}
//you can add more if you need
//internal call, does not send XML response
pos = req.indexOf("IN");
pos = req.indexOf(F("IN"));
if (pos < 1) XML_response(request);
pos = req.indexOf("&NN"); //do not send UDP notifications this time
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;

View file

@ -15,7 +15,11 @@
#include "ArduinoJson-v6.h"
#include <Print.h>
#define DYNAMIC_JSON_DOCUMENT_SIZE 8192
#ifdef ESP8266
#define DYNAMIC_JSON_DOCUMENT_SIZE 8192
#else
#define DYNAMIC_JSON_DOCUMENT_SIZE 16384
#endif
constexpr const char* JSON_MIMETYPE = "application/json";

View file

@ -94,8 +94,13 @@ void WLED::loop()
}
yield();
if (!offMode)
strip.service();
#ifdef ESP8266
else if (!noWifiSleep)
delay(1); //required to make sure ESP enters modem sleep (see #1184)
#endif
}
yield();
#ifdef ESP8266
@ -168,7 +173,7 @@ void WLED::setup()
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
strip.setBrightness(0);
DEBUG_PRINT("LEDs inited. heap usage ~");
DEBUG_PRINT(F("LEDs inited. heap usage ~"));
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifndef WLED_DISABLE_FILESYSTEM
@ -178,7 +183,7 @@ void WLED::setup()
WLED_FS.begin();
#endif
DEBUG_PRINTLN("Load EEPROM");
DEBUG_PRINTLN(F("Load EEPROM"));
loadSettingsFromEEPROM(true);
beginStrip();
userSetup();
@ -189,7 +194,7 @@ void WLED::setup()
if (macroBoot > 0)
applyMacro(macroBoot);
Serial.println("Ada");
Serial.println(F("Ada"));
// generate module IDs
escapedMac = WiFi.macAddress();
@ -197,15 +202,15 @@ void WLED::setup()
escapedMac.toLowerCase();
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
{
strcpy(cmDNS, "wled-");
strcpy_P(cmDNS, PSTR("wled-"));
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttDeviceTopic[0] == 0) {
strcpy(mqttDeviceTopic, "wled/");
strcpy_P(mqttDeviceTopic, PSTR("wled/"));
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttClientID[0] == 0) {
strcpy(mqttClientID, "WLED-");
strcpy_P(mqttClientID, PSTR("WLED-"));
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
}
@ -217,7 +222,7 @@ void WLED::setup()
#ifdef ESP8266
wifi_set_sleep_type(NONE_SLEEP_T);
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
DEBUG_PRINTLN(F("Start ArduinoOTA"));
});
if (strlen(cmDNS) > 0)
ArduinoOTA.setHostname(cmDNS);
@ -254,8 +259,8 @@ void WLED::beginStrip()
#endif
// disable button if it is "pressed" unintentionally
#ifdef BTNPIN
if (digitalRead(BTNPIN) == LOW)
#if defined(BTNPIN) || defined(TOUCHPIN)
if (isButtonPressed())
buttonEnabled = false;
#else
buttonEnabled = false;
@ -268,17 +273,17 @@ void WLED::initAP(bool resetAP)
return;
if (!apSSID[0] || resetAP)
strcpy(apSSID, "WLED-AP");
strcpy(apSSID, (const char*)F("WLED-AP"));
if (resetAP)
strcpy(apPass, DEFAULT_AP_PASS);
DEBUG_PRINT("Opening access point ");
DEBUG_PRINT(F("Opening access point "));
DEBUG_PRINTLN(apSSID);
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(apSSID, apPass, apChannel, apHide);
if (!apActive) // start captive portal if AP active
{
DEBUG_PRINTLN("Init AP interfaces");
DEBUG_PRINTLN(F("Init AP interfaces"));
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort) {
udpConnected = notifierUdp.begin(udpPort);
@ -313,7 +318,7 @@ void WLED::initConnection()
lastReconnectAttempt = millis();
if (!WLED_WIFI_CONFIGURED) {
DEBUG_PRINT("No connection configured. ");
DEBUG_PRINT(F("No connection configured. "));
if (!apActive)
initAP(); // instantly go to ap mode
return;
@ -321,14 +326,14 @@ void WLED::initConnection()
if (apBehavior == AP_BEHAVIOR_ALWAYS) {
initAP();
} else {
DEBUG_PRINTLN("Access point disabled.");
DEBUG_PRINTLN(F("Access point disabled."));
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
}
}
showWelcomePage = false;
DEBUG_PRINT("Connecting to ");
DEBUG_PRINT(F("Connecting to "));
DEBUG_PRINT(clientSSID);
DEBUG_PRINTLN("...");
@ -374,7 +379,7 @@ void WLED::initConnection()
void WLED::initInterfaces()
{
DEBUG_PRINTLN("Init STA interfaces");
DEBUG_PRINTLN(F("Init STA interfaces"));
if (hueIP[0] == 0) {
hueIP[0] = WiFi.localIP()[0];
@ -401,7 +406,7 @@ void WLED::initInterfaces()
MDNS.begin(cmDNS);
#endif
DEBUG_PRINTLN("mDNS started");
DEBUG_PRINTLN(F("mDNS started"));
MDNS.addService("http", "tcp", 80);
MDNS.addService("wled", "tcp", 80);
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
@ -439,7 +444,7 @@ void WLED::handleConnection()
if (millis() - heapTime > 5000) {
uint32_t heap = ESP.getFreeHeap();
if (heap < 9000 && lastHeap < 9000) {
DEBUG_PRINT("Heap too low! ");
DEBUG_PRINT(F("Heap too low! "));
DEBUG_PRINTLN(heap);
forceReconnect = true;
}
@ -458,7 +463,7 @@ void WLED::handleConnection()
#endif
if (stac != stacO) {
stacO = stac;
DEBUG_PRINT("Connected AP clients: ");
DEBUG_PRINT(F("Connected AP clients: "));
DEBUG_PRINTLN(stac);
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
if (stac)
@ -469,7 +474,7 @@ void WLED::handleConnection()
}
}
if (forceReconnect) {
DEBUG_PRINTLN("Forcing reconnect.");
DEBUG_PRINTLN(F("Forcing reconnect."));
initConnection();
interfacesInited = false;
forceReconnect = false;
@ -478,7 +483,7 @@ void WLED::handleConnection()
}
if (!WLED_CONNECTED) {
if (interfacesInited) {
DEBUG_PRINTLN("Disconnected!");
DEBUG_PRINTLN(F("Disconnected!"));
interfacesInited = false;
initConnection();
}
@ -488,7 +493,7 @@ void WLED::handleConnection()
initAP();
} else if (!interfacesInited) { // newly connected
DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: ");
DEBUG_PRINT(F("Connected! IP address: "));
DEBUG_PRINTLN(WiFi.localIP());
initInterfaces();
userConnected();
@ -499,7 +504,7 @@ void WLED::handleConnection()
dnsServer.stop();
WiFi.softAPdisconnect(true);
apActive = false;
DEBUG_PRINTLN("Access point disabled.");
DEBUG_PRINTLN(F("Access point disabled."));
}
}
}

View file

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2009100
#define VERSION 2009202
// ESP8266-01 (blue) got too little storage space to work with WLED. 0.10.2 is the last release supporting this unit.

View file

@ -758,7 +758,7 @@ void applyMacro(byte index)
}
void saveMacro(byte index, String mc, bool persist) //only commit on single save, not in settings
void saveMacro(byte index, const String& mc, bool persist) //only commit on single save, not in settings
{
index-=1;
if (index > 15) return;

View file

@ -25,7 +25,7 @@ bool captivePortal(AsyncWebServerRequest *request)
if (!isIp(hostH) && hostH.indexOf("wled.me") < 0 && hostH.indexOf(cmDNS) < 0) {
DEBUG_PRINTLN("Captive portal");
AsyncWebServerResponse *response = request->beginResponse(302);
response->addHeader("Location", "http://4.3.2.1");
response->addHeader(F("Location"), F("http://4.3.2.1"));
request->send(response);
return true;
}
@ -35,9 +35,9 @@ bool captivePortal(AsyncWebServerRequest *request)
void initServer()
{
//CORS compatiblity
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*");
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveview);
@ -64,45 +64,12 @@ void initServer()
});
server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 200,"Rebooting now...",F("Please wait ~10 seconds..."),129);
serveMessage(request, 200,F("Rebooting now..."),F("Please wait ~10 seconds..."),129);
doReboot = true;
});
server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){
if (!(wifiLock && otaLock)) handleSettingsSet(request, 1);
serveMessage(request, 200,F("WiFi settings saved."),F("Please connect to the new IP (if changed)"),129);
forceReconnect = true;
});
server.on("/settings/leds", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 2);
serveMessage(request, 200,F("LED settings saved."),"Redirecting...",1);
});
server.on("/settings/ui", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 3);
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
});
server.on("/settings/dmx", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 7);
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
});
server.on("/settings/sync", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 4);
serveMessage(request, 200,F("Sync settings saved."),"Redirecting...",1);
});
server.on("/settings/time", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 5);
serveMessage(request, 200,F("Time settings saved."),"Redirecting...",1);
});
server.on("/settings/sec", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 6);
if (!doReboot) serveMessage(request, 200,F("Security settings saved."),F("Rebooting, please wait ~10 seconds..."),129);
doReboot = true;
server.on("/settings", HTTP_POST, [](AsyncWebServerRequest *request){
serveSettings(request, true);
});
server.on("/json", HTTP_GET, [](AsyncWebServerRequest *request){
@ -112,18 +79,18 @@ void initServer()
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
bool verboseResponse = false;
{ //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(8192);
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
JsonObject root = jsonBuffer.as<JsonObject>();
if (error || root.isNull()) {
request->send(400, "application/json", "{\"error\":10}"); return;
request->send(400, "application/json", F("{\"error\":9}")); return;
}
verboseResponse = deserializeState(root);
}
if (verboseResponse) { //if JSON contains "v"
serveJson(request); return;
}
request->send(200, "application/json", "{\"success\":true}");
request->send(200, "application/json", F("{\"success\":true}"));
});
server.addHandler(handler);
@ -181,7 +148,7 @@ void initServer()
doReboot = true;
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index){
DEBUG_PRINTLN("OTA Update Start");
DEBUG_PRINTLN(F("OTA Update Start"));
#ifdef ESP8266
Update.runAsync(true);
#endif
@ -190,9 +157,9 @@ void initServer()
if(!Update.hasError()) Update.write(data, len);
if(final){
if(Update.end(true)){
DEBUG_PRINTLN("Update Success");
DEBUG_PRINTLN(F("Update Success"));
} else {
DEBUG_PRINTLN("Update Failed");
DEBUG_PRINTLN(F("Update Failed"));
}
}
});
@ -273,7 +240,7 @@ void serveIndex(AsyncWebServerRequest* request)
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_index, PAGE_index_L);
response->addHeader("Content-Encoding","gzip");
response->addHeader(F("Content-Encoding"),"gzip");
request->send(response);
}
@ -283,19 +250,23 @@ String msgProcessor(const String& var)
{
if (var == "MSG") {
String messageBody = messageHead;
messageBody += "</h2>";
messageBody += F("</h2>");
messageBody += messageSub;
uint32_t optt = optionType;
if (optt < 60) //redirect to settings after optionType seconds
{
messageBody += "<script>setTimeout(RS," + String(optt*1000) + ")</script>";
messageBody += F("<script>setTimeout(RS,");
messageBody +=String(optt*1000);
messageBody += F(")</script>");
} else if (optt < 120) //redirect back after optionType-60 seconds, unused
{
//messageBody += "<script>setTimeout(B," + String((optt-60)*1000) + ")</script>";
} else if (optt < 180) //reload parent after optionType-120 seconds
{
messageBody += "<script>setTimeout(RP," + String((optt-120)*1000) + ")</script>";
messageBody += F("<script>setTimeout(RP,");
messageBody += String((optt-120)*1000);
messageBody += F(")</script>");
} else if (optt == 253)
{
messageBody += F("<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"); //button to settings
@ -309,7 +280,7 @@ String msgProcessor(const String& var)
}
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl, byte optionT)
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl, byte optionT)
{
messageHead = headl;
messageSub = subl;
@ -359,7 +330,7 @@ String dmxProcessor(const String& var)
}
void serveSettings(AsyncWebServerRequest* request)
void serveSettings(AsyncWebServerRequest* request, bool post)
{
byte subPage = 0;
const String& url = request->url();
@ -380,6 +351,31 @@ void serveSettings(AsyncWebServerRequest* request)
{
serveMessage(request, 500, "Access Denied", F("Please unlock OTA in security settings!"), 254); return;
}
if (post) { //settings/set POST request, saving
if (subPage != 1 || !(wifiLock && otaLock)) handleSettingsSet(request, subPage);
char s[32];
char s2[45] = "";
switch (subPage) {
case 1: strcpy_P(s, PSTR("WiFi")); strcpy_P(s2, PSTR("Please connect to the new IP (if changed)")); forceReconnect = true; break;
case 2: strcpy_P(s, PSTR("LED")); break;
case 3: strcpy_P(s, PSTR("UI")); break;
case 4: strcpy_P(s, PSTR("Sync")); break;
case 5: strcpy_P(s, PSTR("Time")); break;
case 6: strcpy_P(s, PSTR("Security")); strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break;
case 7: strcpy_P(s, PSTR("DMX")); break;
}
strcat_P(s, PSTR(" settings saved."));
if (!s2[0]) strcpy_P(s2, PSTR("Redirecting..."));
if (!doReboot) serveMessage(request, 200, s, s2, (subPage == 1 || subPage == 6) ? 129 : 1);
if (subPage == 6) doReboot = true;
return;
}
#ifdef WLED_DISABLE_MOBILE_UI //disable welcome page if not enough storage
if (subPage == 255) {serveIndex(request); return;}

View file

@ -29,7 +29,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
{
bool verboseResponse = false;
{ //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(8192);
DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, data, len);
JsonObject root = jsonBuffer.as<JsonObject>();
if (error || root.isNull()) return;
@ -57,7 +57,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
if((info->index + len) == info->len){
if(info->final){
if(info->message_opcode == WS_TEXT) {
client->text("{\"error\":10}"); //we do not handle split packets right now
client->text(F("{\"error\":9}")); //we do not handle split packets right now
}
}
}
@ -77,7 +77,7 @@ void sendDataWs(AsyncWebSocketClient * client)
AsyncWebSocketMessageBuffer * buffer;
{ //scope JsonDocument so it releases its buffer
DynamicJsonDocument doc(8192);
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
JsonObject state = doc.createNestedObject("state");
serializeState(state);
JsonObject info = doc.createNestedObject("info");

View file

@ -4,6 +4,9 @@
* Sending XML status files to client
*/
//macro to convert F to const
#define SET_F(x) (const char*)F(x)
//build XML response to HTTP /win API request
void XML_response(AsyncWebServerRequest *request, char* dest)
{
@ -11,9 +14,9 @@ void XML_response(AsyncWebServerRequest *request, char* dest)
obuf = (dest == nullptr)? sbuf:dest;
olen = 0;
oappend((const char*)F("<?xml version=\"1.0\" ?><vs><ac>"));
oappend(SET_F("<?xml version=\"1.0\" ?><vs><ac>"));
oappendi((nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri);
oappend("</ac>");
oappend(SET_F("</ac>"));
for (int i = 0; i < 3; i++)
{
@ -27,47 +30,47 @@ void XML_response(AsyncWebServerRequest *request, char* dest)
oappendi(colSec[i]);
oappend("</cs>");
}
oappend("<ns>");
oappend(SET_F("<ns>"));
oappendi(notifyDirect);
oappend("</ns><nr>");
oappend(SET_F("</ns><nr>"));
oappendi(receiveNotifications);
oappend("</nr><nl>");
oappend(SET_F("</nr><nl>"));
oappendi(nightlightActive);
oappend("</nl><nf>");
oappend(SET_F("</nl><nf>"));
oappendi(nightlightMode > NL_MODE_SET);
oappend("</nf><nd>");
oappend(SET_F("</nf><nd>"));
oappendi(nightlightDelayMins);
oappend("</nd><nt>");
oappend(SET_F("</nd><nt>"));
oappendi(nightlightTargetBri);
oappend("</nt><fx>");
oappend(SET_F("</nt><fx>"));
oappendi(effectCurrent);
oappend("</fx><sx>");
oappend(SET_F("</fx><sx>"));
oappendi(effectSpeed);
oappend("</sx><ix>");
oappend(SET_F("</sx><ix>"));
oappendi(effectIntensity);
oappend("</ix><fp>");
oappend(SET_F("</ix><fp>"));
oappendi(effectPalette);
oappend("</fp><wv>");
oappend(SET_F("</fp><wv>"));
if (strip.rgbwMode) {
oappendi(col[3]);
} else {
oappend("-1");
}
oappend("</wv><ws>");
oappend(SET_F("</wv><ws>"));
oappendi(colSec[3]);
oappend("</ws><ps>");
oappend(SET_F("</ws><ps>"));
oappendi((currentPreset < 1) ? 0:currentPreset);
oappend("</ps><cy>");
oappend(SET_F("</ps><cy>"));
oappendi(presetCyclingEnabled);
oappend("</cy><ds>");
oappend(SET_F("</cy><ds>"));
oappend(serverDescription);
if (realtimeMode)
{
oappend(" (live)");
oappend(SET_F(" (live)"));
}
oappend("</ds><ss>");
oappend(SET_F("</ds><ss>"));
oappendi(strip.getMainSegmentId());
oappend("</ss></vs>");
oappend(SET_F("</ss></vs>"));
if (request != nullptr) request->send(200, "text/xml", obuf);
}
@ -79,41 +82,41 @@ void URL_response(AsyncWebServerRequest *request)
olen = 0;
char s[16];
oappend("http://");
oappend(SET_F("http://"));
IPAddress localIP = WiFi.localIP();
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
oappend(s);
oappend("/win&A=");
oappend(SET_F("/win&A="));
oappendi(bri);
oappend("&CL=h");
oappend(SET_F("&CL=h"));
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", col[i]);
oappend(s);
}
oappend("&C2=h");
oappend(SET_F("&C2=h"));
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", colSec[i]);
oappend(s);
}
oappend("&FX=");
oappend(SET_F("&FX="));
oappendi(effectCurrent);
oappend("&SX=");
oappend(SET_F("&SX="));
oappendi(effectSpeed);
oappend("&IX=");
oappend(SET_F("&IX="));
oappendi(effectIntensity);
oappend("&FP=");
oappend(SET_F("&FP="));
oappendi(effectPalette);
obuf = sbuf;
olen = 0;
oappend((const char*)F("<html><body><a href=\""));
oappend(SET_F("<html><body><a href=\""));
oappend(s2buf);
oappend((const char*)F("\" target=\"_blank\">"));
oappend(SET_F("\" target=\"_blank\">"));
oappend(s2buf);
oappend((const char*)F("</a></body></html>"));
oappend(SET_F("</a></body></html>"));
if (request != nullptr) request->send(200, "text/html", obuf);
}
@ -142,7 +145,7 @@ void sappend(char stype, const char* key, int val)
case 'i': //selectedIndex
oappend(ds);
oappend(key);
oappend(".selectedIndex=");
oappend(SET_F(".selectedIndex="));
oappendi(val);
oappend(";");
break;
@ -162,9 +165,9 @@ void sappends(char stype, const char* key, char* val)
oappend("\";");
break;
case 'm': //message
oappend("d.getElementsByClassName");
oappend(SET_F("d.getElementsByClassName"));
oappend(key);
oappend(".innerHTML=\"");
oappend(SET_F(".innerHTML=\""));
oappend(val);
oappend("\";");
break;
@ -176,7 +179,7 @@ void sappends(char stype, const char* key, char* val)
void getSettingsJS(byte subPage, char* dest)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
DEBUG_PRINT("settings resp");
DEBUG_PRINT(F("settings resp"));
DEBUG_PRINTLN(subPage);
obuf = dest;
olen = 0;
@ -184,13 +187,13 @@ void getSettingsJS(byte subPage, char* dest)
if (subPage <1 || subPage >7) return;
if (subPage == 1) {
sappends('s',"CS",clientSSID);
sappends('s',SET_F("CS"),clientSSID);
byte l = strlen(clientPass);
char fpass[l+1]; //fill password field with ***
fpass[l] = 0;
memset(fpass,'*',l);
sappends('s',"CP",fpass);
sappends('s',SET_F("CP"),fpass);
char k[3]; k[2] = 0; //IP addresses
for (int i = 0; i<4; i++)
@ -201,19 +204,19 @@ void getSettingsJS(byte subPage, char* dest)
k[0] = 'S'; sappend('v',k,staticSubnet[i]);
}
sappends('s',"CM",cmDNS);
sappend('i',"AB",apBehavior);
sappends('s',"AS",apSSID);
sappend('c',"AH",apHide);
sappends('s',SET_F("CM"),cmDNS);
sappend('i',SET_F("AB"),apBehavior);
sappends('s',SET_F("AS"),apSSID);
sappend('c',SET_F("AH"),apHide);
l = strlen(apPass);
char fapass[l+1]; //fill password field with ***
fapass[l] = 0;
memset(fapass,'*',l);
sappends('s',"AP",fapass);
sappends('s',SET_F("AP"),fapass);
sappend('v',"AC",apChannel);
sappend('c',"WS",noWifiSleep);
sappend('v',SET_F("AC"),apChannel);
sappend('c',SET_F("WS"),noWifiSleep);
if (WiFi.localIP()[0] != 0) //is connected
@ -221,10 +224,10 @@ void getSettingsJS(byte subPage, char* dest)
char s[16];
IPAddress localIP = WiFi.localIP();
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
sappends('m',"(\"sip\")[0]",s);
sappends('m',SET_F("(\"sip\")[0]"),s);
} else
{
sappends('m',"(\"sip\")[0]","Not connected");
sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected"));
}
if (WiFi.softAPIP()[0] != 0) //is active
@ -232,114 +235,114 @@ void getSettingsJS(byte subPage, char* dest)
char s[16];
IPAddress apIP = WiFi.softAPIP();
sprintf(s, "%d.%d.%d.%d", apIP[0], apIP[1], apIP[2], apIP[3]);
sappends('m',"(\"sip\")[1]",s);
sappends('m',SET_F("(\"sip\")[1]"),s);
} else
{
sappends('m',"(\"sip\")[1]","Not active");
sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active"));
}
}
if (subPage == 2) {
#ifdef ESP8266
#if LEDPIN == 3
oappend("d.Sf.LC.max=500;");
oappend(SET_F("d.Sf.LC.max=500;"));
#endif
#endif
sappend('v',"LC",ledCount);
sappend('v',"MA",strip.ablMilliampsMax);
sappend('v',"LA",strip.milliampsPerLed);
sappend('v',SET_F("LC"),ledCount);
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed);
if (strip.currentMilliamps)
{
sappends('m',"(\"pow\")[0]","");
sappends('m',SET_F("(\"pow\")[0]"),"");
olen -= 2; //delete ";
oappendi(strip.currentMilliamps);
oappend("mA\";");
oappend(SET_F("mA\";"));
}
sappend('v',"CA",briS);
sappend('c',"EW",useRGBW);
sappend('i',"CO",strip.colorOrder);
sappend('v',"AW",strip.rgbwMode);
sappend('v',SET_F("CA"),briS);
sappend('c',SET_F("EW"),useRGBW);
sappend('i',SET_F("CO"),strip.colorOrder);
sappend('v',SET_F("AW"),strip.rgbwMode);
sappend('c',"BO",turnOnAtBoot);
sappend('v',"BP",bootPreset);
sappend('c',SET_F("BO"),turnOnAtBoot);
sappend('v',SET_F("BP"),bootPreset);
sappend('c',"GB",strip.gammaCorrectBri);
sappend('c',"GC",strip.gammaCorrectCol);
sappend('c',"TF",fadeTransition);
sappend('v',"TD",transitionDelayDefault);
sappend('c',"PF",strip.paletteFade);
sappend('v',"BF",briMultiplier);
sappend('v',"TB",nightlightTargetBri);
sappend('v',"TL",nightlightDelayMinsDefault);
sappend('v',"TW",nightlightMode);
sappend('i',"PB",strip.paletteBlend);
sappend('c',"RV",strip.reverseMode);
sappend('c',"SL",skipFirstLed);
sappend('c',SET_F("GB"),strip.gammaCorrectBri);
sappend('c',SET_F("GC"),strip.gammaCorrectCol);
sappend('c',SET_F("TF"),fadeTransition);
sappend('v',SET_F("TD"),transitionDelayDefault);
sappend('c',SET_F("PF"),strip.paletteFade);
sappend('v',SET_F("BF"),briMultiplier);
sappend('v',SET_F("TB"),nightlightTargetBri);
sappend('v',SET_F("TL"),nightlightDelayMinsDefault);
sappend('v',SET_F("TW"),nightlightMode);
sappend('i',SET_F("PB"),strip.paletteBlend);
sappend('c',SET_F("RV"),strip.reverseMode);
sappend('c',SET_F("SL"),skipFirstLed);
}
if (subPage == 3)
{
sappends('s',"DS",serverDescription);
sappend('c',"ST",syncToggleReceive);
sappends('s',SET_F("DS"),serverDescription);
sappend('c',SET_F("ST"),syncToggleReceive);
}
if (subPage == 4)
{
sappend('c',"BT",buttonEnabled);
sappend('v',"IR",irEnabled);
sappend('v',"UP",udpPort);
sappend('c',"RB",receiveNotificationBrightness);
sappend('c',"RC",receiveNotificationColor);
sappend('c',"RX",receiveNotificationEffects);
sappend('c',"SD",notifyDirectDefault);
sappend('c',"SB",notifyButton);
sappend('c',"SH",notifyHue);
sappend('c',"SM",notifyMacro);
sappend('c',"S2",notifyTwice);
sappend('c',"RD",receiveDirect);
sappend('v',"EP",e131Port);
sappend('c',"ES",e131SkipOutOfSequence);
sappend('c',"EM",e131Multicast);
sappend('v',"EU",e131Universe);
sappend('v',"DA",DMXAddress);
sappend('v',"DM",DMXMode);
sappend('v',"ET",realtimeTimeoutMs);
sappend('c',"FB",arlsForceMaxBri);
sappend('c',"RG",arlsDisableGammaCorrection);
sappend('v',"WO",arlsOffset);
sappend('c',"AL",alexaEnabled);
sappends('s',"AI",alexaInvocationName);
sappend('c',"SA",notifyAlexa);
sappends('s',"BK",(char*)((blynkEnabled)?"Hidden":""));
sappend('c',SET_F("BT"),buttonEnabled);
sappend('v',SET_F("IR"),irEnabled);
sappend('v',SET_F("UP"),udpPort);
sappend('c',SET_F("RB"),receiveNotificationBrightness);
sappend('c',SET_F("RC"),receiveNotificationColor);
sappend('c',SET_F("RX"),receiveNotificationEffects);
sappend('c',SET_F("SD"),notifyDirectDefault);
sappend('c',SET_F("SB"),notifyButton);
sappend('c',SET_F("SH"),notifyHue);
sappend('c',SET_F("SM"),notifyMacro);
sappend('c',SET_F("S2"),notifyTwice);
sappend('c',SET_F("RD"),receiveDirect);
sappend('v',SET_F("EP"),e131Port);
sappend('c',SET_F("ES"),e131SkipOutOfSequence);
sappend('c',SET_F("EM"),e131Multicast);
sappend('v',SET_F("EU"),e131Universe);
sappend('v',SET_F("DA"),DMXAddress);
sappend('v',SET_F("DM"),DMXMode);
sappend('v',SET_F("ET"),realtimeTimeoutMs);
sappend('c',SET_F("FB"),arlsForceMaxBri);
sappend('c',SET_F("RG"),arlsDisableGammaCorrection);
sappend('v',SET_F("WO"),arlsOffset);
sappend('c',SET_F("AL"),alexaEnabled);
sappends('s',SET_F("AI"),alexaInvocationName);
sappend('c',SET_F("SA"),notifyAlexa);
sappends('s',SET_F("BK"),(char*)((blynkEnabled)?SET_F("Hidden"):""));
#ifdef WLED_ENABLE_MQTT
sappend('c',"MQ",mqttEnabled);
sappends('s',"MS",mqttServer);
sappend('v',"MQPORT",mqttPort);
sappends('s',"MQUSER",mqttUser);
sappends('s',"MQPASS",mqttPass);
sappend('c',SET_F("MQ"),mqttEnabled);
sappends('s',SET_F("MS"),mqttServer);
sappend('v',SET_F("MQPORT"),mqttPort);
sappends('s',SET_F("MQUSER"),mqttUser);
sappends('s',SET_F("MQPASS"),mqttPass);
byte l = strlen(mqttPass);
char fpass[l+1]; //fill password field with ***
fpass[l] = 0;
memset(fpass,'*',l);
sappends('s',"MQPASS",fpass);
sappends('s',"MQCID",mqttClientID);
sappends('s',"MD",mqttDeviceTopic);
sappends('s',"MG",mqttGroupTopic);
sappends('s',SET_F("MQPASS"),fpass);
sappends('s',SET_F("MQCID"),mqttClientID);
sappends('s',SET_F("MD"),mqttDeviceTopic);
sappends('s',SET_F("MG"),mqttGroupTopic);
#endif
#ifndef WLED_DISABLE_HUESYNC
sappend('v',"H0",hueIP[0]);
sappend('v',"H1",hueIP[1]);
sappend('v',"H2",hueIP[2]);
sappend('v',"H3",hueIP[3]);
sappend('v',"HL",huePollLightId);
sappend('v',"HI",huePollIntervalMs);
sappend('c',"HP",huePollingEnabled);
sappend('c',"HO",hueApplyOnOff);
sappend('c',"HB",hueApplyBri);
sappend('c',"HC",hueApplyColor);
sappend('v',SET_F("H0"),hueIP[0]);
sappend('v',SET_F("H1"),hueIP[1]);
sappend('v',SET_F("H2"),hueIP[2]);
sappend('v',SET_F("H3"),hueIP[3]);
sappend('v',SET_F("HL"),huePollLightId);
sappend('v',SET_F("HI"),huePollIntervalMs);
sappend('c',SET_F("HP"),huePollingEnabled);
sappend('c',SET_F("HO"),hueApplyOnOff);
sappend('c',SET_F("HB"),hueApplyBri);
sappend('c',SET_F("HC"),hueApplyColor);
char hueErrorString[25];
switch (hueError)
{
@ -350,38 +353,38 @@ void getSettingsJS(byte subPage, char* dest)
case HUE_ERROR_PUSHLINK : strcpy(hueErrorString,(char*)F("Link button not pressed")); break;
case HUE_ERROR_JSON_PARSING : strcpy(hueErrorString,(char*)F("JSON parsing error")); break;
case HUE_ERROR_TIMEOUT : strcpy(hueErrorString,(char*)F("Timeout")); break;
default: sprintf(hueErrorString,"Bridge Error %i",hueError);
default: sprintf(hueErrorString,(char*)F("Bridge Error %i"),hueError);
}
sappends('m',"(\"sip\")[0]",hueErrorString);
sappends('m',SET_F("(\"sip\")[0]"),hueErrorString);
#endif
}
if (subPage == 5)
{
sappend('c',"NT",ntpEnabled);
sappends('s',"NS",ntpServerName);
sappend('c',"CF",!useAMPM);
sappend('i',"TZ",currentTimezone);
sappend('v',"UO",utcOffsetSecs);
sappend('c',SET_F("NT"),ntpEnabled);
sappends('s',SET_F("NS"),ntpServerName);
sappend('c',SET_F("CF"),!useAMPM);
sappend('i',SET_F("TZ"),currentTimezone);
sappend('v',SET_F("UO"),utcOffsetSecs);
char tm[32];
getTimeString(tm);
sappends('m',"(\"times\")[0]",tm);
sappend('i',"OL",overlayCurrent);
sappend('v',"O1",overlayMin);
sappend('v',"O2",overlayMax);
sappend('v',"OM",analogClock12pixel);
sappend('c',"OS",analogClockSecondsTrail);
sappend('c',"O5",analogClock5MinuteMarks);
sappends('s',"CX",cronixieDisplay);
sappend('c',"CB",cronixieBacklight);
sappend('c',"CE",countdownMode);
sappend('v',"CY",countdownYear);
sappend('v',"CI",countdownMonth);
sappend('v',"CD",countdownDay);
sappend('v',"CH",countdownHour);
sappend('v',"CM",countdownMin);
sappend('v',"CS",countdownSec);
sappends('m',SET_F("(\"times\")[0]"),tm);
sappend('i',SET_F("OL"),overlayCurrent);
sappend('v',SET_F("O1"),overlayMin);
sappend('v',SET_F("O2"),overlayMax);
sappend('v',SET_F("OM"),analogClock12pixel);
sappend('c',SET_F("OS"),analogClockSecondsTrail);
sappend('c',SET_F("O5"),analogClock5MinuteMarks);
sappends('s',SET_F("CX"),cronixieDisplay);
sappend('c',SET_F("CB"),cronixieBacklight);
sappend('c',SET_F("CE"),countdownMode);
sappend('v',SET_F("CY"),countdownYear);
sappend('v',SET_F("CI"),countdownMonth);
sappend('v',SET_F("CD"),countdownDay);
sappend('v',SET_F("CH"),countdownHour);
sappend('v',SET_F("CM"),countdownMin);
sappend('v',SET_F("CS"),countdownSec);
char k[4]; k[0]= 'M';
for (int i=1;i<17;i++)
{
@ -391,14 +394,14 @@ void getSettingsJS(byte subPage, char* dest)
sappends('s',k,m);
}
sappend('v',"MB",macroBoot);
sappend('v',"A0",macroAlexaOn);
sappend('v',"A1",macroAlexaOff);
sappend('v',"MP",macroButton);
sappend('v',"ML",macroLongPress);
sappend('v',"MC",macroCountdown);
sappend('v',"MN",macroNl);
sappend('v',"MD",macroDoublePress);
sappend('v',SET_F("MB"),macroBoot);
sappend('v',SET_F("A0"),macroAlexaOn);
sappend('v',SET_F("A1"),macroAlexaOff);
sappend('v',SET_F("MP"),macroButton);
sappend('v',SET_F("ML"),macroLongPress);
sappend('v',SET_F("MC"),macroCountdown);
sappend('v',SET_F("MN"),macroNl);
sappend('v',SET_F("MD"),macroDoublePress);
k[2] = 0; //Time macros
for (int i = 0; i<8; i++)
@ -413,43 +416,43 @@ void getSettingsJS(byte subPage, char* dest)
if (subPage == 6)
{
sappend('c',"NO",otaLock);
sappend('c',"OW",wifiLock);
sappend('c',"AO",aOtaEnabled);
sappends('m',"(\"sip\")[0]","WLED ");
sappend('c',SET_F("NO"),otaLock);
sappend('c',SET_F("OW"),wifiLock);
sappend('c',SET_F("AO"),aOtaEnabled);
sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED "));
olen -= 2; //delete ";
oappend(versionString);
oappend(" (build ");
oappend(SET_F(" (build "));
oappendi(VERSION);
oappend(")\";");
oappend(SET_F(")\";"));
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == 7)
{
sappend('v',"PU",e131ProxyUniverse);
sappend('v',SET_F("PU"),e131ProxyUniverse);
sappend('v',"CN",DMXChannels);
sappend('v',"CG",DMXGap);
sappend('v',"CS",DMXStart);
sappend('v',"SL",DMXStartLED);
sappend('v',SET_F("CN"),DMXChannels);
sappend('v',SET_F("CG"),DMXGap);
sappend('v',SET_F("CS"),DMXStart);
sappend('v',SET_F("SL"),DMXStartLED);
sappend('i',"CH1",DMXFixtureMap[0]);
sappend('i',"CH2",DMXFixtureMap[1]);
sappend('i',"CH3",DMXFixtureMap[2]);
sappend('i',"CH4",DMXFixtureMap[3]);
sappend('i',"CH5",DMXFixtureMap[4]);
sappend('i',"CH6",DMXFixtureMap[5]);
sappend('i',"CH7",DMXFixtureMap[6]);
sappend('i',"CH8",DMXFixtureMap[7]);
sappend('i',"CH9",DMXFixtureMap[8]);
sappend('i',"CH10",DMXFixtureMap[9]);
sappend('i',"CH11",DMXFixtureMap[10]);
sappend('i',"CH12",DMXFixtureMap[11]);
sappend('i',"CH13",DMXFixtureMap[12]);
sappend('i',"CH14",DMXFixtureMap[13]);
sappend('i',"CH15",DMXFixtureMap[14]);
sappend('i',SET_F("CH1"),DMXFixtureMap[0]);
sappend('i',SET_F("CH2"),DMXFixtureMap[1]);
sappend('i',SET_F("CH3"),DMXFixtureMap[2]);
sappend('i',SET_F("CH4"),DMXFixtureMap[3]);
sappend('i',SET_F("CH5"),DMXFixtureMap[4]);
sappend('i',SET_F("CH6"),DMXFixtureMap[5]);
sappend('i',SET_F("CH7"),DMXFixtureMap[6]);
sappend('i',SET_F("CH8"),DMXFixtureMap[7]);
sappend('i',SET_F("CH9"),DMXFixtureMap[8]);
sappend('i',SET_F("CH10"),DMXFixtureMap[9]);
sappend('i',SET_F("CH11"),DMXFixtureMap[10]);
sappend('i',SET_F("CH12"),DMXFixtureMap[11]);
sappend('i',SET_F("CH13"),DMXFixtureMap[12]);
sappend('i',SET_F("CH14"),DMXFixtureMap[13]);
sappend('i',SET_F("CH15"),DMXFixtureMap[14]);
}
#endif
oappend("}</script>");
oappend(SET_F("}</script>"));
}