Merge pull request #1193 from Aircoookie/merge-fs2

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -49,7 +49,11 @@
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of /* 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

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

View File

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

View File

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

View File

@ -137,14 +137,14 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / 3; uint16_t ledsInFirstUniverse = (MAX_CHANNELS_PER_UNIVERSE - DMXAddress) / 3;
previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * MAX_LEDS_PER_UNIVERSE; previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * MAX_LEDS_PER_UNIVERSE;
} }
uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset) / 3; uint16_t ledsTotal = previousLeds + (dmxChannels - dmxOffset +1) / 3;
for (uint16_t i = previousLeds; i < ledsTotal; i++) { for (uint16_t i = previousLeds; i < ledsTotal; i++) {
setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], 0); setRealtimePixel(i, e131_data[dmxOffset++], e131_data[dmxOffset++], e131_data[dmxOffset++], 0);
} }
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

@ -21,6 +21,7 @@ void updateBlynk();
//button.cpp //button.cpp
void shortPressAction(); void shortPressAction();
bool isButtonPressed();
void handleButton(); void handleButton();
void handleIO(); void handleIO();
@ -197,7 +198,7 @@ bool applyPreset(byte index, bool loadBri = true);
void savePreset(byte index, bool persist = true, const char* pname = nullptr, byte prio = 50, JsonObject saveobj = JsonObject()); void savePreset(byte index, bool persist = true, const char* pname = nullptr, byte prio = 50, JsonObject saveobj = JsonObject());
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();
@ -209,10 +210,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, root["n"], root["p"] | 50, root["o"].as<JsonObject>()); if (ps >= 0) savePreset(ps, persistSaves, root["n"], root["p"] | 50, root["o"].as<JsonObject>());
return stateResponse; return stateResponse;
@ -232,12 +232,12 @@ bool deserializeState(JsonObject root)
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset) void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset)
{ {
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;
if (!forPreset) root["len"] = seg.stop - seg.start; if (!forPreset) 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,52 +263,52 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
} }
} }
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, bool forPreset) void serializeState(JsonObject root, bool forPreset)
{ {
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
if (!forPreset) { if (!forPreset) {
if (errorFlag) root["error"] = errorFlag; if (errorFlag) root["error"] = errorFlag;
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");
udpn["send"] = notifyDirect;
udpn["recv"] = receiveNotifications;
root["lor"] = realtimeOverride; JsonObject udpn = root.createNestedObject("udpn");
udpn[F("send")] = notifyDirect;
udpn[F("recv")] = receiveNotifications;
root[F("lor")] = realtimeOverride;
} }
root["mainseg"] = strip.getMainSegmentId(); root[F("mainseg")] = strip.getMainSegmentId();
JsonArray seg = root.createNestedArray("seg"); JsonArray seg = root.createNestedArray("seg");
for (byte s = 0; s < strip.getMaxSegments(); s++) for (byte s = 0; s < strip.getMaxSegments(); s++)
@ -344,61 +344,62 @@ 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["signal"] = getSignalQuality(qrssi); wifi_info[F("rssi")] = qrssi;
wifi_info["channel"] = WiFi.channel(); wifi_info[F("signal")] = getSignalQuality(qrssi);
wifi_info[F("channel")] = WiFi.channel();
JsonObject fs_info = root.createNestedObject("fs"); JsonObject fs_info = root.createNestedObject("fs");
FSInfo fsi; FSInfo fsi;
@ -408,30 +409,31 @@ void serializeInfo(JsonObject root)
#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);
byte os = 0; byte os = 0;
@ -459,11 +461,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)
@ -477,11 +479,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;
} }
@ -490,7 +492,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)
@ -506,8 +508,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);
} }
} }
@ -529,7 +531,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;
@ -538,7 +541,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,32 @@ 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'); char cmd = req.charAt(pos+3);
if (cmd == '2') presetCyclingEnabled = !presetCyclingEnabled;
else presetCyclingEnabled = (cmd != '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 +508,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 +536,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 +560,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 +605,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 +623,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 +631,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 +647,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 +665,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 +706,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;

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

@ -94,8 +94,13 @@ void WLED::loop()
} }
yield(); yield();
if (!offMode) if (!offMode)
strip.service(); strip.service();
#ifdef ESP8266
else if (!noWifiSleep)
delay(1); //required to make sure ESP enters modem sleep (see #1184)
#endif
} }
yield(); yield();
#ifdef ESP8266 #ifdef ESP8266
@ -168,7 +173,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
@ -178,7 +183,7 @@ void WLED::setup()
WLED_FS.begin(); WLED_FS.begin();
#endif #endif
DEBUG_PRINTLN("Load EEPROM"); DEBUG_PRINTLN(F("Load EEPROM"));
loadSettingsFromEEPROM(true); loadSettingsFromEEPROM(true);
beginStrip(); beginStrip();
userSetup(); userSetup();
@ -189,7 +194,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();
@ -197,15 +202,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);
} }
@ -217,7 +222,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);
@ -254,8 +259,8 @@ void WLED::beginStrip()
#endif #endif
// disable button if it is "pressed" unintentionally // disable button if it is "pressed" unintentionally
#ifdef BTNPIN #if defined(BTNPIN) || defined(TOUCHPIN)
if (digitalRead(BTNPIN) == LOW) if (isButtonPressed())
buttonEnabled = false; buttonEnabled = false;
#else #else
buttonEnabled = false; buttonEnabled = false;
@ -268,17 +273,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);
@ -313,7 +318,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;
@ -321,14 +326,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("...");
@ -374,7 +379,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];
@ -401,7 +406,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());
@ -439,7 +444,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;
} }
@ -458,7 +463,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)
@ -469,7 +474,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;
@ -478,7 +483,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();
} }
@ -488,7 +493,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();
@ -499,7 +504,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 2009100 #define VERSION 2009202
// ESP8266-01 (blue) got too little storage space to work with WLED. 0.10.2 is the last release supporting this unit. // ESP8266-01 (blue) got too little storage space to work with WLED. 0.10.2 is the last release supporting this unit.

View File

@ -758,7 +758,7 @@ void applyMacro(byte index)
} }
void saveMacro(byte index, String mc, bool persist) //only commit on single save, not in settings void saveMacro(byte index, const String& mc, bool persist) //only commit on single save, not in settings
{ {
index-=1; 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();
@ -380,6 +351,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;}

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>"));
} }