Reduce heap usage by 4kB

This commit is contained in:
cschwinne 2020-09-20 01:18:31 +02:00
parent ff55a305cd
commit edbe8131ab
18 changed files with 3752 additions and 2450 deletions

View File

@ -2,6 +2,14 @@
### Development versions after the 0.10.2 release ### Development versions after the 0.10.2 release
#### 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 #### Build 2009170
- New WLED logo on Welcome screen (#1164) - New WLED logo on Welcome screen (#1164)

View File

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

View File

@ -126,4 +126,11 @@
#define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit #define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit
// 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 #endif

View File

@ -144,7 +144,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
break; break;
} }
default: default:
DEBUG_PRINTLN("unknown E1.31 DMX mode"); DEBUG_PRINTLN(F("unknown E1.31 DMX mode"));
return; // nothing to do return; // nothing to do
break; break;
} }

View File

@ -193,7 +193,7 @@ bool applyPreset(byte index, bool loadBri = true);
void savePreset(byte index, bool persist = true); void savePreset(byte index, bool persist = true);
void loadMacro(byte index, char* m); void loadMacro(byte index, char* m);
void applyMacro(byte index); 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 //wled_serial.cpp
void handleSerial(); void handleSerial();
@ -205,10 +205,10 @@ void initServer();
void serveIndexOrWelcome(AsyncWebServerRequest *request); void serveIndexOrWelcome(AsyncWebServerRequest *request);
void serveIndex(AsyncWebServerRequest* request); void serveIndex(AsyncWebServerRequest* request);
String msgProcessor(const String& var); 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 settingsProcessor(const String& var);
String dmxProcessor(const String& var); String dmxProcessor(const String& var);
void serveSettings(AsyncWebServerRequest* request); void serveSettings(AsyncWebServerRequest* request, bool post = false);
//ws.cpp //ws.cpp
void handleWs(); void handleWs();

View File

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

View File

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

View File

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

View File

@ -4,69 +4,127 @@
/* /*
* Acquires time from NTP server * Acquires time from NTP server
*/ */
Timezone* tz;
TimeChangeRule UTCr = {Last, Sun, Mar, 1, 0}; // UTC #define TZ_UTC 0
Timezone tzUTC(UTCr, UTCr); #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 byte tzCurrent = TZ_INIT; //uninitialized
TimeChangeRule GMT = {Last, Sun, Oct, 2, 0}; // Standard Time
Timezone tzUK(BST, GMT);
TimeChangeRule CEST = {Last, Sun, Mar, 2, 120}; //Central European Summer Time void updateTimezone() {
TimeChangeRule CET = {Last, Sun, Oct, 3, 60}; //Central European Standard Time delete tz;
Timezone tzEUCentral(CEST, CET); TimeChangeRule tcrDaylight = {Last, Sun, Mar, 1, 0}; //UTC
TimeChangeRule tcrStandard = tcrDaylight; //UTC
TimeChangeRule EEST = {Last, Sun, Mar, 3, 180}; //Central European Summer Time switch (currentTimezone) {
TimeChangeRule EET = {Last, Sun, Oct, 4, 120}; //Central European Standard Time case TZ_UK : {
Timezone tzEUEastern(EEST, EET); 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 tzCurrent = currentTimezone;
TimeChangeRule EST = {First, Sun, Nov, 2, -300 }; //Standard time = UTC - 5 hours
Timezone tzUSEastern(EDT, EST);
TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 }; //Daylight time = UTC - 5 hours tz = new Timezone(tcrDaylight, tcrStandard);
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};
void handleNetworkTime() void handleNetworkTime()
{ {
@ -95,7 +153,7 @@ void sendNTPPacket()
#endif #endif
} }
DEBUG_PRINTLN("send NTP"); DEBUG_PRINTLN(F("send NTP"));
byte pbuf[NTP_PACKET_SIZE]; byte pbuf[NTP_PACKET_SIZE];
memset(pbuf, 0, NTP_PACKET_SIZE); memset(pbuf, 0, NTP_PACKET_SIZE);
@ -118,7 +176,7 @@ bool checkNTPResponse()
{ {
int cb = ntpUdp.parsePacket(); int cb = ntpUdp.parsePacket();
if (cb) { if (cb) {
DEBUG_PRINT("NTP recv, l="); DEBUG_PRINT(F("NTP recv, l="));
DEBUG_PRINTLN(cb); DEBUG_PRINTLN(cb);
byte pbuf[NTP_PACKET_SIZE]; byte pbuf[NTP_PACKET_SIZE];
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
@ -129,7 +187,7 @@ bool checkNTPResponse()
unsigned long secsSince1900 = highWord << 16 | lowWord; 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) unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
setTime(epoch); setTime(epoch);
DEBUG_PRINTLN(epoch); DEBUG_PRINTLN(epoch);
@ -141,8 +199,9 @@ bool checkNTPResponse()
void updateLocalTime() void updateLocalTime()
{ {
if (currentTimezone != tzCurrent) updateTimezone();
unsigned long tmc = now()+ utcOffsetSecs; unsigned long tmc = now()+ utcOffsetSecs;
localTime = timezones[currentTimezone]->toLocal(tmc); localTime = tz->toLocal(tmc);
} }
void getTimeString(char* out) void getTimeString(char* out)
@ -165,7 +224,8 @@ void getTimeString(char* out)
void setCountdown() 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; if (countdownTime - now() > 0) countdownOverTriggered = false;
} }

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,11 @@
#include "ArduinoJson-v6.h" #include "ArduinoJson-v6.h"
#include <Print.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"; constexpr const char* JSON_MIMETYPE = "application/json";

View File

@ -160,7 +160,7 @@ void WLED::setup()
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
strip.setBrightness(0); strip.setBrightness(0);
DEBUG_PRINT("LEDs inited. heap usage ~"); DEBUG_PRINT(F("LEDs inited. heap usage ~"));
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap()); DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifndef WLED_DISABLE_FILESYSTEM #ifndef WLED_DISABLE_FILESYSTEM
@ -170,7 +170,7 @@ void WLED::setup()
SPIFFS.begin(); SPIFFS.begin();
#endif #endif
DEBUG_PRINTLN("Load EEPROM"); DEBUG_PRINTLN(F("Load EEPROM"));
loadSettingsFromEEPROM(true); loadSettingsFromEEPROM(true);
beginStrip(); beginStrip();
userSetup(); userSetup();
@ -181,7 +181,7 @@ void WLED::setup()
if (macroBoot > 0) if (macroBoot > 0)
applyMacro(macroBoot); applyMacro(macroBoot);
Serial.println("Ada"); Serial.println(F("Ada"));
// generate module IDs // generate module IDs
escapedMac = WiFi.macAddress(); escapedMac = WiFi.macAddress();
@ -189,15 +189,15 @@ void WLED::setup()
escapedMac.toLowerCase(); escapedMac.toLowerCase();
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default 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); sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
} }
if (mqttDeviceTopic[0] == 0) { if (mqttDeviceTopic[0] == 0) {
strcpy(mqttDeviceTopic, "wled/"); strcpy_P(mqttDeviceTopic, PSTR("wled/"));
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6); sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
} }
if (mqttClientID[0] == 0) { if (mqttClientID[0] == 0) {
strcpy(mqttClientID, "WLED-"); strcpy_P(mqttClientID, PSTR("WLED-"));
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6); sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
} }
@ -209,7 +209,7 @@ void WLED::setup()
#ifdef ESP8266 #ifdef ESP8266
wifi_set_sleep_type(NONE_SLEEP_T); wifi_set_sleep_type(NONE_SLEEP_T);
#endif #endif
DEBUG_PRINTLN("Start ArduinoOTA"); DEBUG_PRINTLN(F("Start ArduinoOTA"));
}); });
if (strlen(cmDNS) > 0) if (strlen(cmDNS) > 0)
ArduinoOTA.setHostname(cmDNS); ArduinoOTA.setHostname(cmDNS);
@ -260,17 +260,17 @@ void WLED::initAP(bool resetAP)
return; return;
if (!apSSID[0] || resetAP) if (!apSSID[0] || resetAP)
strcpy(apSSID, "WLED-AP"); strcpy(apSSID, (const char*)F("WLED-AP"));
if (resetAP) if (resetAP)
strcpy(apPass, DEFAULT_AP_PASS); strcpy(apPass, DEFAULT_AP_PASS);
DEBUG_PRINT("Opening access point "); DEBUG_PRINT(F("Opening access point "));
DEBUG_PRINTLN(apSSID); DEBUG_PRINTLN(apSSID);
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0)); WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(apSSID, apPass, apChannel, apHide); WiFi.softAP(apSSID, apPass, apChannel, apHide);
if (!apActive) // start captive portal if AP active if (!apActive) // start captive portal if AP active
{ {
DEBUG_PRINTLN("Init AP interfaces"); DEBUG_PRINTLN(F("Init AP interfaces"));
server.begin(); server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort) { if (udpPort > 0 && udpPort != ntpLocalPort) {
udpConnected = notifierUdp.begin(udpPort); udpConnected = notifierUdp.begin(udpPort);
@ -305,7 +305,7 @@ void WLED::initConnection()
lastReconnectAttempt = millis(); lastReconnectAttempt = millis();
if (!WLED_WIFI_CONFIGURED) { if (!WLED_WIFI_CONFIGURED) {
DEBUG_PRINT("No connection configured. "); DEBUG_PRINT(F("No connection configured. "));
if (!apActive) if (!apActive)
initAP(); // instantly go to ap mode initAP(); // instantly go to ap mode
return; return;
@ -313,14 +313,14 @@ void WLED::initConnection()
if (apBehavior == AP_BEHAVIOR_ALWAYS) { if (apBehavior == AP_BEHAVIOR_ALWAYS) {
initAP(); initAP();
} else { } else {
DEBUG_PRINTLN("Access point disabled."); DEBUG_PRINTLN(F("Access point disabled."));
WiFi.softAPdisconnect(true); WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
} }
} }
showWelcomePage = false; showWelcomePage = false;
DEBUG_PRINT("Connecting to "); DEBUG_PRINT(F("Connecting to "));
DEBUG_PRINT(clientSSID); DEBUG_PRINT(clientSSID);
DEBUG_PRINTLN("..."); DEBUG_PRINTLN("...");
@ -366,7 +366,7 @@ void WLED::initConnection()
void WLED::initInterfaces() void WLED::initInterfaces()
{ {
DEBUG_PRINTLN("Init STA interfaces"); DEBUG_PRINTLN(F("Init STA interfaces"));
if (hueIP[0] == 0) { if (hueIP[0] == 0) {
hueIP[0] = WiFi.localIP()[0]; hueIP[0] = WiFi.localIP()[0];
@ -393,7 +393,7 @@ void WLED::initInterfaces()
MDNS.begin(cmDNS); MDNS.begin(cmDNS);
#endif #endif
DEBUG_PRINTLN("mDNS started"); DEBUG_PRINTLN(F("mDNS started"));
MDNS.addService("http", "tcp", 80); MDNS.addService("http", "tcp", 80);
MDNS.addService("wled", "tcp", 80); MDNS.addService("wled", "tcp", 80);
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str()); MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
@ -431,7 +431,7 @@ void WLED::handleConnection()
if (millis() - heapTime > 5000) { if (millis() - heapTime > 5000) {
uint32_t heap = ESP.getFreeHeap(); uint32_t heap = ESP.getFreeHeap();
if (heap < 9000 && lastHeap < 9000) { if (heap < 9000 && lastHeap < 9000) {
DEBUG_PRINT("Heap too low! "); DEBUG_PRINT(F("Heap too low! "));
DEBUG_PRINTLN(heap); DEBUG_PRINTLN(heap);
forceReconnect = true; forceReconnect = true;
} }
@ -450,7 +450,7 @@ void WLED::handleConnection()
#endif #endif
if (stac != stacO) { if (stac != stacO) {
stacO = stac; stacO = stac;
DEBUG_PRINT("Connected AP clients: "); DEBUG_PRINT(F("Connected AP clients: "));
DEBUG_PRINTLN(stac); DEBUG_PRINTLN(stac);
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
if (stac) if (stac)
@ -461,7 +461,7 @@ void WLED::handleConnection()
} }
} }
if (forceReconnect) { if (forceReconnect) {
DEBUG_PRINTLN("Forcing reconnect."); DEBUG_PRINTLN(F("Forcing reconnect."));
initConnection(); initConnection();
interfacesInited = false; interfacesInited = false;
forceReconnect = false; forceReconnect = false;
@ -470,7 +470,7 @@ void WLED::handleConnection()
} }
if (!WLED_CONNECTED) { if (!WLED_CONNECTED) {
if (interfacesInited) { if (interfacesInited) {
DEBUG_PRINTLN("Disconnected!"); DEBUG_PRINTLN(F("Disconnected!"));
interfacesInited = false; interfacesInited = false;
initConnection(); initConnection();
} }
@ -480,7 +480,7 @@ void WLED::handleConnection()
initAP(); initAP();
} else if (!interfacesInited) { // newly connected } else if (!interfacesInited) { // newly connected
DEBUG_PRINTLN(""); DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: "); DEBUG_PRINT(F("Connected! IP address: "));
DEBUG_PRINTLN(WiFi.localIP()); DEBUG_PRINTLN(WiFi.localIP());
initInterfaces(); initInterfaces();
userConnected(); userConnected();
@ -491,7 +491,7 @@ void WLED::handleConnection()
dnsServer.stop(); dnsServer.stop();
WiFi.softAPdisconnect(true); WiFi.softAPdisconnect(true);
apActive = false; 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) // version code in format yymmddb (b = daily build)
#define VERSION 2009170 #define VERSION 2009200
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS). // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
@ -87,6 +87,8 @@
#include "src/dependencies/e131/ESPAsyncE131.h" #include "src/dependencies/e131/ESPAsyncE131.h"
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h" #include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
#define ARDUINOJSON_DECODE_UNICODE 0
#include "src/dependencies/json/AsyncJson-v6.h" #include "src/dependencies/json/AsyncJson-v6.h"
#include "src/dependencies/json/ArduinoJson-v6.h" #include "src/dependencies/json/ArduinoJson-v6.h"

View File

@ -734,7 +734,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; index-=1;
if (index > 15) return; 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) { if (!isIp(hostH) && hostH.indexOf("wled.me") < 0 && hostH.indexOf(cmDNS) < 0) {
DEBUG_PRINTLN("Captive portal"); DEBUG_PRINTLN("Captive portal");
AsyncWebServerResponse *response = request->beginResponse(302); 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); request->send(response);
return true; return true;
} }
@ -35,9 +35,9 @@ bool captivePortal(AsyncWebServerRequest *request)
void initServer() void initServer()
{ {
//CORS compatiblity //CORS compatiblity
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*");
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveview); request->send_P(200, "text/html", PAGE_liveview);
@ -64,45 +64,12 @@ void initServer()
}); });
server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request){ 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; doReboot = true;
}); });
server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){ server.on("/settings", HTTP_POST, [](AsyncWebServerRequest *request){
if (!(wifiLock && otaLock)) handleSettingsSet(request, 1); serveSettings(request, true);
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("/json", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/json", HTTP_GET, [](AsyncWebServerRequest *request){
@ -112,18 +79,18 @@ void initServer()
AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) { AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request) {
bool verboseResponse = false; bool verboseResponse = false;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(8192); DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject)); DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
JsonObject root = jsonBuffer.as<JsonObject>(); JsonObject root = jsonBuffer.as<JsonObject>();
if (error || root.isNull()) { if (error || root.isNull()) {
request->send(400, "application/json", "{\"error\":10}"); return; request->send(400, "application/json", F("{\"error\":9}")); return;
} }
verboseResponse = deserializeState(root); verboseResponse = deserializeState(root);
} }
if (verboseResponse) { //if JSON contains "v" if (verboseResponse) { //if JSON contains "v"
serveJson(request); return; serveJson(request); return;
} }
request->send(200, "application/json", "{\"success\":true}"); request->send(200, "application/json", F("{\"success\":true}"));
}); });
server.addHandler(handler); server.addHandler(handler);
@ -181,7 +148,7 @@ void initServer()
doReboot = true; doReboot = true;
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index){ if(!index){
DEBUG_PRINTLN("OTA Update Start"); DEBUG_PRINTLN(F("OTA Update Start"));
#ifdef ESP8266 #ifdef ESP8266
Update.runAsync(true); Update.runAsync(true);
#endif #endif
@ -190,9 +157,9 @@ void initServer()
if(!Update.hasError()) Update.write(data, len); if(!Update.hasError()) Update.write(data, len);
if(final){ if(final){
if(Update.end(true)){ if(Update.end(true)){
DEBUG_PRINTLN("Update Success"); DEBUG_PRINTLN(F("Update Success"));
} else { } 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); 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); request->send(response);
} }
@ -283,19 +250,23 @@ String msgProcessor(const String& var)
{ {
if (var == "MSG") { if (var == "MSG") {
String messageBody = messageHead; String messageBody = messageHead;
messageBody += "</h2>"; messageBody += F("</h2>");
messageBody += messageSub; messageBody += messageSub;
uint32_t optt = optionType; uint32_t optt = optionType;
if (optt < 60) //redirect to settings after optionType seconds 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 } else if (optt < 120) //redirect back after optionType-60 seconds, unused
{ {
//messageBody += "<script>setTimeout(B," + String((optt-60)*1000) + ")</script>"; //messageBody += "<script>setTimeout(B," + String((optt-60)*1000) + ")</script>";
} else if (optt < 180) //reload parent after optionType-120 seconds } 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) } else if (optt == 253)
{ {
messageBody += F("<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"); //button to settings 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; messageHead = headl;
messageSub = subl; messageSub = subl;
@ -359,7 +330,7 @@ String dmxProcessor(const String& var)
} }
void serveSettings(AsyncWebServerRequest* request) void serveSettings(AsyncWebServerRequest* request, bool post)
{ {
byte subPage = 0; byte subPage = 0;
const String& url = request->url(); const String& url = request->url();
@ -381,6 +352,31 @@ void serveSettings(AsyncWebServerRequest* request)
serveMessage(request, 500, "Access Denied", F("Please unlock OTA in security settings!"), 254); return; 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 #ifdef WLED_DISABLE_MOBILE_UI //disable welcome page if not enough storage
if (subPage == 255) {serveIndex(request); return;} if (subPage == 255) {serveIndex(request); return;}
#endif #endif

View File

@ -29,7 +29,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
{ {
bool verboseResponse = false; bool verboseResponse = false;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument jsonBuffer(8192); DynamicJsonDocument jsonBuffer(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(jsonBuffer, data, len); DeserializationError error = deserializeJson(jsonBuffer, data, len);
JsonObject root = jsonBuffer.as<JsonObject>(); JsonObject root = jsonBuffer.as<JsonObject>();
if (error || root.isNull()) return; if (error || root.isNull()) return;
@ -57,7 +57,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
if((info->index + len) == info->len){ if((info->index + len) == info->len){
if(info->final){ if(info->final){
if(info->message_opcode == WS_TEXT) { 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; AsyncWebSocketMessageBuffer * buffer;
{ //scope JsonDocument so it releases its buffer { //scope JsonDocument so it releases its buffer
DynamicJsonDocument doc(8192); DynamicJsonDocument doc(JSON_BUFFER_SIZE);
JsonObject state = doc.createNestedObject("state"); JsonObject state = doc.createNestedObject("state");
serializeState(state); serializeState(state);
JsonObject info = doc.createNestedObject("info"); JsonObject info = doc.createNestedObject("info");

View File

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