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
#### Build 2009200
- Increased available heap memory by 4kB
- Use F() macro for the majority of strings
- Restructure timezone code
- Restructured settings saved code
- Updated ArduinoJSON to 6.16.1
#### Build 2009170
- New WLED logo on Welcome screen (#1164)

View File

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

View File

@ -126,4 +126,11 @@
#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

View File

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

View File

@ -193,7 +193,7 @@ bool applyPreset(byte index, bool loadBri = true);
void savePreset(byte index, bool persist = true);
void loadMacro(byte index, char* m);
void applyMacro(byte index);
void saveMacro(byte index, String mc, bool persist = true); //only commit on single save, not in settings
void saveMacro(byte index, const String& mc, bool persist = true); //only commit on single save, not in settings
//wled_serial.cpp
void handleSerial();
@ -205,10 +205,10 @@ void initServer();
void serveIndexOrWelcome(AsyncWebServerRequest *request);
void serveIndex(AsyncWebServerRequest* request);
String msgProcessor(const String& var);
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255);
void serveMessage(AsyncWebServerRequest* request, uint16_t code, const String& headl, const String& subl="", byte optionT=255);
String settingsProcessor(const String& var);
String dmxProcessor(const String& var);
void serveSettings(AsyncWebServerRequest* request);
void serveSettings(AsyncWebServerRequest* request, bool post = false);
//ws.cpp
void handleWs();

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -160,7 +160,7 @@ void WLED::setup()
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
strip.setBrightness(0);
DEBUG_PRINT("LEDs inited. heap usage ~");
DEBUG_PRINT(F("LEDs inited. heap usage ~"));
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifndef WLED_DISABLE_FILESYSTEM
@ -170,7 +170,7 @@ void WLED::setup()
SPIFFS.begin();
#endif
DEBUG_PRINTLN("Load EEPROM");
DEBUG_PRINTLN(F("Load EEPROM"));
loadSettingsFromEEPROM(true);
beginStrip();
userSetup();
@ -181,7 +181,7 @@ void WLED::setup()
if (macroBoot > 0)
applyMacro(macroBoot);
Serial.println("Ada");
Serial.println(F("Ada"));
// generate module IDs
escapedMac = WiFi.macAddress();
@ -189,15 +189,15 @@ void WLED::setup()
escapedMac.toLowerCase();
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
{
strcpy(cmDNS, "wled-");
strcpy_P(cmDNS, PSTR("wled-"));
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttDeviceTopic[0] == 0) {
strcpy(mqttDeviceTopic, "wled/");
strcpy_P(mqttDeviceTopic, PSTR("wled/"));
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttClientID[0] == 0) {
strcpy(mqttClientID, "WLED-");
strcpy_P(mqttClientID, PSTR("WLED-"));
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
}
@ -209,7 +209,7 @@ void WLED::setup()
#ifdef ESP8266
wifi_set_sleep_type(NONE_SLEEP_T);
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
DEBUG_PRINTLN(F("Start ArduinoOTA"));
});
if (strlen(cmDNS) > 0)
ArduinoOTA.setHostname(cmDNS);
@ -260,17 +260,17 @@ void WLED::initAP(bool resetAP)
return;
if (!apSSID[0] || resetAP)
strcpy(apSSID, "WLED-AP");
strcpy(apSSID, (const char*)F("WLED-AP"));
if (resetAP)
strcpy(apPass, DEFAULT_AP_PASS);
DEBUG_PRINT("Opening access point ");
DEBUG_PRINT(F("Opening access point "));
DEBUG_PRINTLN(apSSID);
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(apSSID, apPass, apChannel, apHide);
if (!apActive) // start captive portal if AP active
{
DEBUG_PRINTLN("Init AP interfaces");
DEBUG_PRINTLN(F("Init AP interfaces"));
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort) {
udpConnected = notifierUdp.begin(udpPort);
@ -305,7 +305,7 @@ void WLED::initConnection()
lastReconnectAttempt = millis();
if (!WLED_WIFI_CONFIGURED) {
DEBUG_PRINT("No connection configured. ");
DEBUG_PRINT(F("No connection configured. "));
if (!apActive)
initAP(); // instantly go to ap mode
return;
@ -313,14 +313,14 @@ void WLED::initConnection()
if (apBehavior == AP_BEHAVIOR_ALWAYS) {
initAP();
} else {
DEBUG_PRINTLN("Access point disabled.");
DEBUG_PRINTLN(F("Access point disabled."));
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
}
}
showWelcomePage = false;
DEBUG_PRINT("Connecting to ");
DEBUG_PRINT(F("Connecting to "));
DEBUG_PRINT(clientSSID);
DEBUG_PRINTLN("...");
@ -366,7 +366,7 @@ void WLED::initConnection()
void WLED::initInterfaces()
{
DEBUG_PRINTLN("Init STA interfaces");
DEBUG_PRINTLN(F("Init STA interfaces"));
if (hueIP[0] == 0) {
hueIP[0] = WiFi.localIP()[0];
@ -393,7 +393,7 @@ void WLED::initInterfaces()
MDNS.begin(cmDNS);
#endif
DEBUG_PRINTLN("mDNS started");
DEBUG_PRINTLN(F("mDNS started"));
MDNS.addService("http", "tcp", 80);
MDNS.addService("wled", "tcp", 80);
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
@ -431,7 +431,7 @@ void WLED::handleConnection()
if (millis() - heapTime > 5000) {
uint32_t heap = ESP.getFreeHeap();
if (heap < 9000 && lastHeap < 9000) {
DEBUG_PRINT("Heap too low! ");
DEBUG_PRINT(F("Heap too low! "));
DEBUG_PRINTLN(heap);
forceReconnect = true;
}
@ -450,7 +450,7 @@ void WLED::handleConnection()
#endif
if (stac != stacO) {
stacO = stac;
DEBUG_PRINT("Connected AP clients: ");
DEBUG_PRINT(F("Connected AP clients: "));
DEBUG_PRINTLN(stac);
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
if (stac)
@ -461,7 +461,7 @@ void WLED::handleConnection()
}
}
if (forceReconnect) {
DEBUG_PRINTLN("Forcing reconnect.");
DEBUG_PRINTLN(F("Forcing reconnect."));
initConnection();
interfacesInited = false;
forceReconnect = false;
@ -470,7 +470,7 @@ void WLED::handleConnection()
}
if (!WLED_CONNECTED) {
if (interfacesInited) {
DEBUG_PRINTLN("Disconnected!");
DEBUG_PRINTLN(F("Disconnected!"));
interfacesInited = false;
initConnection();
}
@ -480,7 +480,7 @@ void WLED::handleConnection()
initAP();
} else if (!interfacesInited) { // newly connected
DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: ");
DEBUG_PRINT(F("Connected! IP address: "));
DEBUG_PRINTLN(WiFi.localIP());
initInterfaces();
userConnected();
@ -491,7 +491,7 @@ void WLED::handleConnection()
dnsServer.stop();
WiFi.softAPdisconnect(true);
apActive = false;
DEBUG_PRINTLN("Access point disabled.");
DEBUG_PRINTLN(F("Access point disabled."));
}
}
}

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 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).
@ -87,6 +87,8 @@
#include "src/dependencies/e131/ESPAsyncE131.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/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;
if (index > 15) return;

View File

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

View File

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

View File

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