Merge branch 'master' into toki
This commit is contained in:
commit
9f13763637
@ -16,7 +16,7 @@ This file should be placed in the same directory as `platformio.ini`.
|
||||
### Define Your Options
|
||||
|
||||
* `USERMOD_ROTARY_ENCODER_UI` - define this to have this user mod included wled00\usermods_list.cpp
|
||||
* `USERMOD_FOUR_LINE_DISLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details)
|
||||
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details)
|
||||
* `ENCODER_DT_PIN` - The encoders DT pin, defaults to 12
|
||||
* `ENCODER_CLK_PIN` - The encoders CLK pin, defaults to 14
|
||||
* `ENCODER_SW_PIN` - The encoders SW pin, defaults to 13
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define ENCODER_SW_PIN 13
|
||||
#endif
|
||||
|
||||
#ifndef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifndef USERMOD_FOUR_LINE_DISPLAY
|
||||
// These constants won't be defined if we aren't using FourLineDisplay.
|
||||
#define FLD_LINE_3_BRIGHTNESS 0
|
||||
#define FLD_LINE_3_EFFECT_SPEED 0
|
||||
@ -62,7 +62,7 @@ private:
|
||||
unsigned char button_state = HIGH;
|
||||
unsigned char prev_button_state = HIGH;
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
FourLineDisplayUsermod *display;
|
||||
#else
|
||||
void* display = nullptr;
|
||||
@ -96,7 +96,7 @@ public:
|
||||
modes_alpha_indexes = modeSortUsermod->getModesAlphaIndexes();
|
||||
palettes_alpha_indexes = modeSortUsermod->getPalettesAlphaIndexes();
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
// This Usermod uses FourLineDisplayUsermod for the best experience.
|
||||
// But it's optional. But you want it.
|
||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||
@ -248,7 +248,7 @@ public:
|
||||
}
|
||||
|
||||
boolean changeState(const char *stateName, byte lineThreeMode, byte markedLine) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display != nullptr) {
|
||||
if (display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
@ -272,7 +272,7 @@ public:
|
||||
}
|
||||
|
||||
void changeBrightness(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
@ -288,7 +288,7 @@ public:
|
||||
}
|
||||
|
||||
void changeEffect(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
@ -305,7 +305,7 @@ public:
|
||||
}
|
||||
|
||||
void changeEffectSpeed(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
@ -321,7 +321,7 @@ public:
|
||||
}
|
||||
|
||||
void changeEffectIntensity(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
@ -337,7 +337,7 @@ public:
|
||||
}
|
||||
|
||||
void changePalette(bool increase) {
|
||||
#ifdef USERMOD_FOUR_LINE_DISLAY
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
if (display && display->wakeDisplay()) {
|
||||
// Throw away wake up input
|
||||
return;
|
||||
|
@ -6,105 +6,210 @@
|
||||
|
||||
#define WLED_DEBOUNCE_THRESHOLD 50 //only consider button input of at least 50ms as valid (debouncing)
|
||||
|
||||
void shortPressAction()
|
||||
void shortPressAction(uint8_t b)
|
||||
{
|
||||
if (!macroButton)
|
||||
if (!macroButton[b])
|
||||
{
|
||||
toggleOnOff();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
} else {
|
||||
applyPreset(macroButton);
|
||||
applyPreset(macroButton[b]);
|
||||
}
|
||||
}
|
||||
|
||||
bool isButtonPressed()
|
||||
bool isButtonPressed(uint8_t i)
|
||||
{
|
||||
if (btnPin>=0 && digitalRead(btnPin) == LOW) return true;
|
||||
#ifdef TOUCHPIN
|
||||
if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true;
|
||||
#endif
|
||||
if (btnPin[i]<0) return false;
|
||||
switch (buttonType[i]) {
|
||||
case BTN_TYPE_NONE:
|
||||
case BTN_TYPE_RESERVED:
|
||||
break;
|
||||
case BTN_TYPE_PUSH:
|
||||
case BTN_TYPE_SWITCH:
|
||||
if (digitalRead(btnPin[i]) == LOW) return true;
|
||||
break;
|
||||
case BTN_TYPE_PUSH_ACT_HIGH:
|
||||
case BTN_TYPE_SWITCH_ACT_HIGH:
|
||||
if (digitalRead(btnPin[i]) == HIGH) return true;
|
||||
break;
|
||||
case BTN_TYPE_TOUCH:
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (touchRead(btnPin[i]) <= touchThreshold) return true;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void handleSwitch()
|
||||
void handleSwitch(uint8_t b)
|
||||
{
|
||||
if (buttonPressedBefore != isButtonPressed()) {
|
||||
buttonPressedTime = millis();
|
||||
buttonPressedBefore = !buttonPressedBefore;
|
||||
if (buttonPressedBefore[b] != isButtonPressed(b)) {
|
||||
buttonPressedTime[b] = millis();
|
||||
buttonPressedBefore[b] = !buttonPressedBefore[b];
|
||||
}
|
||||
|
||||
if (buttonLongPressed == buttonPressedBefore) return;
|
||||
if (buttonLongPressed[b] == buttonPressedBefore[b]) return;
|
||||
|
||||
if (millis() - buttonPressedTime > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
|
||||
if (buttonPressedBefore) { //LOW, falling edge, switch closed
|
||||
if (macroButton) applyPreset(macroButton);
|
||||
if (millis() - buttonPressedTime[b] > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
|
||||
if (buttonPressedBefore[b]) { //LOW, falling edge, switch closed
|
||||
if (macroButton[b]) applyPreset(macroButton[b]);
|
||||
else { //turn on
|
||||
if (!bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
|
||||
}
|
||||
} else { //HIGH, rising edge, switch opened
|
||||
if (macroLongPress) applyPreset(macroLongPress);
|
||||
if (macroLongPress[b]) applyPreset(macroLongPress[b]);
|
||||
else { //turn off
|
||||
if (bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);}
|
||||
}
|
||||
}
|
||||
buttonLongPressed = buttonPressedBefore; //save the last "long term" switch state
|
||||
buttonLongPressed[b] = buttonPressedBefore[b]; //save the last "long term" switch state
|
||||
}
|
||||
}
|
||||
|
||||
void handleAnalog(uint8_t b)
|
||||
{
|
||||
static uint8_t oldRead[WLED_MAX_BUTTONS];
|
||||
#ifdef ESP8266
|
||||
uint16_t aRead = analogRead(A0) >> 2; // convert 10bit read to 8bit
|
||||
#else
|
||||
uint16_t aRead = analogRead(btnPin[b]) >> 4; // convert 12bit read to 8bit
|
||||
#endif
|
||||
// remove noise & reduce frequency of UI updates
|
||||
aRead &= 0xFC;
|
||||
|
||||
if (oldRead[b] == aRead) return; // no change in reading
|
||||
oldRead[b] = aRead;
|
||||
|
||||
// if no macro for "short press" and "long press" is defined use brightness control
|
||||
if (!macroButton[b] && !macroLongPress[b]) {
|
||||
// if "double press" macro defines which option to change
|
||||
if (macroDoublePress[b] >= 250) {
|
||||
// global brightness
|
||||
if (aRead == 0) {
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
} else{
|
||||
bri = aRead;
|
||||
}
|
||||
} else if (macroDoublePress[b] == 249) {
|
||||
// effect speed
|
||||
effectSpeed = aRead;
|
||||
effectChanged = true;
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isSelected()) continue;
|
||||
seg.speed = effectSpeed;
|
||||
}
|
||||
} else if (macroDoublePress[b] == 248) {
|
||||
// effect intensity
|
||||
effectIntensity = aRead;
|
||||
effectChanged = true;
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isSelected()) continue;
|
||||
seg.intensity = effectIntensity;
|
||||
}
|
||||
} else if (macroDoublePress[b] == 247) {
|
||||
// selected palette
|
||||
effectPalette = map(aRead, 0, 252, 0, strip.getPaletteCount()-1);
|
||||
effectChanged = true;
|
||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
||||
if (!seg.isSelected()) continue;
|
||||
seg.palette = effectPalette;
|
||||
}
|
||||
} else if (macroDoublePress[b] == 200) {
|
||||
// primary color, hue, full saturation
|
||||
colorHStoRGB(aRead*256,255,col);
|
||||
} else {
|
||||
// otherwise use "double press" for segment selection
|
||||
//uint8_t mainSeg = strip.getMainSegmentId();
|
||||
WS2812FX::Segment& seg = strip.getSegment(macroDoublePress[b]);
|
||||
if (aRead == 0) {
|
||||
seg.setOption(SEG_OPTION_ON, 0); // off
|
||||
} else {
|
||||
seg.setOpacity(aRead, macroDoublePress[b]);
|
||||
seg.setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
// this will notify clients of update (websockets,mqtt,etc)
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
updateInterfaces(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
} else {
|
||||
//TODO:
|
||||
// we can either trigger a preset depending on the level (between short and long entries)
|
||||
// or use it for RGBW direct control
|
||||
}
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
|
||||
void handleButton()
|
||||
{
|
||||
if (btnPin<0 || buttonType < BTN_TYPE_PUSH) return;
|
||||
static unsigned long lastRead = 0UL;
|
||||
|
||||
for (uint8_t b=0; b<WLED_MAX_BUTTONS; b++) {
|
||||
#ifdef ESP8266
|
||||
if ((btnPin[b]<0 && buttonType[b] != BTN_TYPE_ANALOG) || buttonType[b] == BTN_TYPE_NONE) continue;
|
||||
#else
|
||||
if (btnPin[b]<0 || buttonType[b] == BTN_TYPE_NONE) continue;
|
||||
#endif
|
||||
|
||||
if (buttonType == BTN_TYPE_SWITCH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NO gpio0)
|
||||
handleSwitch(); return;
|
||||
}
|
||||
if (buttonType[b] == BTN_TYPE_ANALOG && millis() - lastRead > 250) { // button is not a button but a potentiometer
|
||||
if (b+1 == WLED_MAX_BUTTONS) lastRead = millis();
|
||||
handleAnalog(b); continue;
|
||||
}
|
||||
|
||||
//momentary button logic
|
||||
if (isButtonPressed()) //pressed
|
||||
{
|
||||
if (!buttonPressedBefore) buttonPressedTime = millis();
|
||||
buttonPressedBefore = true;
|
||||
if (buttonType[b] == BTN_TYPE_SWITCH || buttonType[b] == BTN_TYPE_SWITCH_ACT_HIGH) { //button is not momentary, but switch. This is only suitable on pins whose on-boot state does not matter (NOT gpio0)
|
||||
handleSwitch(b); continue;
|
||||
}
|
||||
|
||||
if (millis() - buttonPressedTime > 600) //long press
|
||||
//momentary button logic
|
||||
if (isButtonPressed(b)) //pressed
|
||||
{
|
||||
if (!buttonLongPressed)
|
||||
{
|
||||
if (macroLongPress) {applyPreset(macroLongPress);}
|
||||
else _setRandomColor(false,true);
|
||||
if (!buttonPressedBefore[b]) buttonPressedTime[b] = millis();
|
||||
buttonPressedBefore[b] = true;
|
||||
|
||||
buttonLongPressed = true;
|
||||
if (millis() - buttonPressedTime[b] > 600) //long press
|
||||
{
|
||||
if (!buttonLongPressed[b])
|
||||
{
|
||||
if (macroLongPress[b]) {applyPreset(macroLongPress[b]);}
|
||||
else _setRandomColor(false,true);
|
||||
|
||||
buttonLongPressed[b] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isButtonPressed() && buttonPressedBefore) //released
|
||||
{
|
||||
long dur = millis() - buttonPressedTime;
|
||||
if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore = false; return;} //too short "press", debounce
|
||||
bool doublePress = buttonWaitTime;
|
||||
buttonWaitTime = 0;
|
||||
|
||||
if (dur > 6000) //long press
|
||||
else if (!isButtonPressed(b) && buttonPressedBefore[b]) //released
|
||||
{
|
||||
WLED::instance().initAP(true);
|
||||
}
|
||||
else if (!buttonLongPressed) { //short press
|
||||
if (macroDoublePress)
|
||||
{
|
||||
if (doublePress) applyPreset(macroDoublePress);
|
||||
else buttonWaitTime = millis();
|
||||
} else shortPressAction();
|
||||
}
|
||||
buttonPressedBefore = false;
|
||||
buttonLongPressed = false;
|
||||
}
|
||||
long dur = millis() - buttonPressedTime[b];
|
||||
if (dur < WLED_DEBOUNCE_THRESHOLD) {buttonPressedBefore[b] = false; continue;} //too short "press", debounce
|
||||
bool doublePress = buttonWaitTime[b];
|
||||
buttonWaitTime[b] = 0;
|
||||
|
||||
if (buttonWaitTime && millis() - buttonWaitTime > 450 && !buttonPressedBefore)
|
||||
{
|
||||
buttonWaitTime = 0;
|
||||
shortPressAction();
|
||||
if (dur > 6000 && b==0) //long press on button 0
|
||||
{
|
||||
WLED::instance().initAP(true);
|
||||
}
|
||||
else if (!buttonLongPressed[b]) { //short press
|
||||
if (macroDoublePress[b])
|
||||
{
|
||||
if (doublePress) applyPreset(macroDoublePress[b]);
|
||||
else buttonWaitTime[b] = millis();
|
||||
} else shortPressAction(b);
|
||||
}
|
||||
buttonPressedBefore[b] = false;
|
||||
buttonLongPressed[b] = false;
|
||||
}
|
||||
|
||||
if (buttonWaitTime[b] && millis() - buttonWaitTime[b] > 450 && !buttonPressedBefore[b])
|
||||
{
|
||||
buttonWaitTime[b] = 0;
|
||||
shortPressAction(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +233,8 @@ void handleIO()
|
||||
{
|
||||
if (!offMode) {
|
||||
#ifdef ESP8266
|
||||
//turn off built-in LED if strip is turned off
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be reinitialised on On
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
#endif
|
||||
|
141
wled00/cfg.cpp
141
wled00/cfg.cpp
@ -62,7 +62,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonArray ap_ip = ap["ip"];
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
apIP[i] = ap_ip;
|
||||
}*/
|
||||
}
|
||||
*/
|
||||
|
||||
noWifiSleep = doc[F("wifi")][F("sleep")] | !noWifiSleep; // inverted
|
||||
noWifiSleep = !noWifiSleep;
|
||||
@ -89,13 +90,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
for (JsonObject elm : ins) {
|
||||
if (s >= WLED_MAX_BUSSES) break;
|
||||
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||
JsonArray pinArr = elm[F("pin")];
|
||||
JsonArray pinArr = elm["pin"];
|
||||
if (pinArr.size() == 0) continue;
|
||||
pins[0] = pinArr[0];
|
||||
uint8_t i = 0;
|
||||
for (int p : pinArr) {
|
||||
pins[i] = p;
|
||||
i++;
|
||||
pins[i++] = p;
|
||||
if (i>4) break;
|
||||
}
|
||||
|
||||
@ -123,22 +123,47 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
}
|
||||
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
|
||||
|
||||
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
|
||||
CJSON(buttonType, hw_btn_ins_0["type"]);
|
||||
int hw_btn_pin = hw_btn_ins_0[F("pin")][0] | -2; //-2 = not present in doc, keep current. -1 = disable
|
||||
if (hw_btn_pin > -2) {
|
||||
if (pinManager.allocatePin(hw_btn_pin,false)) {
|
||||
btnPin = hw_btn_pin;
|
||||
pinMode(btnPin, INPUT_PULLUP);
|
||||
} else {
|
||||
btnPin = -1;
|
||||
// read multiple button configuration
|
||||
JsonArray hw_btn_ins = hw[F("btn")][F("ins")];
|
||||
if (!hw_btn_ins.isNull()) {
|
||||
uint8_t s = 0;
|
||||
for (JsonObject btn : hw_btn_ins) {
|
||||
CJSON(buttonType[s], btn["type"]);
|
||||
int8_t pin = btn[F("pin")][0] | -1;
|
||||
if (pin > -1) {
|
||||
if (pinManager.allocatePin(pin,false)) {
|
||||
btnPin[s] = pin;
|
||||
pinMode(btnPin[s], INPUT_PULLUP);
|
||||
} else {
|
||||
btnPin[s] = -1;
|
||||
}
|
||||
}
|
||||
JsonArray hw_btn_ins_0_macros = btn[F("macros")];
|
||||
CJSON(macroButton[s], hw_btn_ins_0_macros[0]);
|
||||
CJSON(macroLongPress[s],hw_btn_ins_0_macros[1]);
|
||||
CJSON(macroDoublePress[s], hw_btn_ins_0_macros[2]);
|
||||
if (++s >= WLED_MAX_BUTTONS) break; // max buttons reached
|
||||
}
|
||||
// clear remaining buttons
|
||||
for (; s<WLED_MAX_BUTTONS; s++) {
|
||||
btnPin[s] = -1;
|
||||
buttonType[s] = BTN_TYPE_NONE;
|
||||
macroButton[s] = 0;
|
||||
macroLongPress[s] = 0;
|
||||
macroDoublePress[s] = 0;
|
||||
}
|
||||
} else {
|
||||
// new install/missing configuration (button 0 has defaults)
|
||||
if (fromFS)
|
||||
for (uint8_t s=1; s<WLED_MAX_BUTTONS; s++) {
|
||||
btnPin[s] = -1;
|
||||
buttonType[s] = BTN_TYPE_NONE;
|
||||
macroButton[s] = 0;
|
||||
macroLongPress[s] = 0;
|
||||
macroDoublePress[s] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
|
||||
CJSON(macroButton, hw_btn_ins_0_macros[0]);
|
||||
CJSON(macroLongPress,hw_btn_ins_0_macros[1]);
|
||||
CJSON(macroDoublePress, hw_btn_ins_0_macros[2]);
|
||||
CJSON(touchThreshold,hw[F("btn")][F("tt")]);
|
||||
|
||||
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||
if (hw_ir_pin > -2) {
|
||||
@ -164,7 +189,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
rlyMde = !relay["rev"];
|
||||
}
|
||||
|
||||
//int hw_status_pin = hw[F("status")][F("pin")]; // -1
|
||||
//int hw_status_pin = hw[F("status")]["pin"]; // -1
|
||||
|
||||
JsonObject light = doc[F("light")];
|
||||
CJSON(briMultiplier, light[F("scale-bri")]);
|
||||
@ -179,7 +204,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
JsonObject light_tr = light[F("tr")];
|
||||
CJSON(fadeTransition, light_tr[F("mode")]);
|
||||
int tdd = light_tr[F("dur")] | -1;
|
||||
int tdd = light_tr["dur"] | -1;
|
||||
if (tdd >= 0) transitionDelayDefault = tdd * 100;
|
||||
CJSON(strip.paletteFade, light_tr["pal"]);
|
||||
|
||||
@ -203,7 +228,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(presetCycleMin, def_cy[F("range")][0]);
|
||||
CJSON(presetCycleMax, def_cy[F("range")][1]);
|
||||
|
||||
tdd = def_cy[F("dur")] | -1;
|
||||
tdd = def_cy["dur"] | -1;
|
||||
if (tdd > 0) presetCycleTime = tdd;
|
||||
|
||||
JsonObject interfaces = doc["if"];
|
||||
@ -255,6 +280,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(macroAlexaOn, interfaces[F("va")][F("macros")][0]);
|
||||
CJSON(macroAlexaOff, interfaces[F("va")][F("macros")][1]);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
||||
tdd = strnlen(apikey, 36);
|
||||
if (tdd > 20 || tdd == 0)
|
||||
@ -263,7 +289,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonObject if_blynk = interfaces["blynk"];
|
||||
getStringFromJson(blynkHost, if_blynk[F("host")], 33);
|
||||
CJSON(blynkPort, if_blynk["port"]);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces["mqtt"];
|
||||
CJSON(mqttEnabled, if_mqtt["en"]);
|
||||
getStringFromJson(mqttServer, if_mqtt[F("broker")], 33);
|
||||
@ -274,7 +302,9 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], 33); // "wled/test"
|
||||
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], 33); // ""
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
JsonObject if_hue = interfaces[F("hue")];
|
||||
CJSON(huePollingEnabled, if_hue["en"]);
|
||||
CJSON(huePollLightId, if_hue["id"]);
|
||||
@ -290,6 +320,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
for (byte i = 0; i < 4; i++)
|
||||
CJSON(hueIP[i], if_hue_ip[i]);
|
||||
#endif
|
||||
|
||||
JsonObject if_ntp = interfaces[F("ntp")];
|
||||
CJSON(ntpEnabled, if_ntp["en"]);
|
||||
@ -306,7 +337,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(countdownMode, ol[F("cntdwn")]);
|
||||
if (prev != overlayDefault) overlayCurrent = overlayDefault;
|
||||
|
||||
CJSON(overlayMin, ol[F("min")]);
|
||||
CJSON(overlayMin, ol["min"]);
|
||||
CJSON(overlayMax, ol[F("max")]);
|
||||
CJSON(analogClock12pixel, ol[F("o12pix")]);
|
||||
CJSON(analogClock5MinuteMarks, ol[F("o5m")]);
|
||||
@ -331,7 +362,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (it > 9) break;
|
||||
if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset
|
||||
CJSON(timerHours[it], timer[F("hour")]);
|
||||
CJSON(timerMinutes[it], timer[F("min")]);
|
||||
CJSON(timerMinutes[it], timer["min"]);
|
||||
CJSON(timerMacro[it], timer[F("macro")]);
|
||||
|
||||
byte dowPrev = timerWeekday[it];
|
||||
@ -377,6 +408,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN(F("Starting usermod config."));
|
||||
JsonObject usermods_settings = doc["um"];
|
||||
if (!usermods_settings.isNull()) usermods.readFromConfig(usermods_settings);
|
||||
|
||||
@ -490,21 +522,34 @@ void serializeConfig() {
|
||||
ins["type"] = bus->getType();
|
||||
}
|
||||
|
||||
// button(s)
|
||||
JsonObject hw_btn = hw.createNestedObject("btn");
|
||||
|
||||
hw_btn["max"] = WLED_MAX_BUTTONS; // just information about max number of buttons (not actually used)
|
||||
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
|
||||
|
||||
// button BTNPIN
|
||||
// there is always at least one button
|
||||
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
hw_btn_ins_0["type"] = buttonType;
|
||||
|
||||
hw_btn_ins_0["type"] = buttonType[0];
|
||||
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
hw_btn_ins_0_pin.add(btnPin);
|
||||
|
||||
hw_btn_ins_0_pin.add(btnPin[0]);
|
||||
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
|
||||
hw_btn_ins_0_macros.add(macroButton);
|
||||
hw_btn_ins_0_macros.add(macroLongPress);
|
||||
hw_btn_ins_0_macros.add(macroDoublePress);
|
||||
hw_btn_ins_0_macros.add(macroButton[0]);
|
||||
hw_btn_ins_0_macros.add(macroLongPress[0]);
|
||||
hw_btn_ins_0_macros.add(macroDoublePress[0]);
|
||||
|
||||
// additional buttons
|
||||
for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) {
|
||||
//if (btnPin[i]<0) continue;
|
||||
hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
hw_btn_ins_0["type"] = buttonType[i];
|
||||
hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
hw_btn_ins_0_pin.add(btnPin[i]);
|
||||
hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
|
||||
hw_btn_ins_0_macros.add(macroButton[i]);
|
||||
hw_btn_ins_0_macros.add(macroLongPress[i]);
|
||||
hw_btn_ins_0_macros.add(macroDoublePress[i]);
|
||||
}
|
||||
hw_btn[F("tt")] = touchThreshold;
|
||||
|
||||
JsonObject hw_ir = hw.createNestedObject("ir");
|
||||
hw_ir["pin"] = irPin;
|
||||
@ -527,12 +572,12 @@ void serializeConfig() {
|
||||
|
||||
JsonObject light_tr = light.createNestedObject("tr");
|
||||
light_tr[F("mode")] = fadeTransition;
|
||||
light_tr[F("dur")] = transitionDelayDefault / 100;
|
||||
light_tr["dur"] = transitionDelayDefault / 100;
|
||||
light_tr["pal"] = strip.paletteFade;
|
||||
|
||||
JsonObject light_nl = light.createNestedObject("nl");
|
||||
light_nl[F("mode")] = nightlightMode;
|
||||
light_nl[F("dur")] = nightlightDelayMinsDefault;
|
||||
light_nl["dur"] = nightlightDelayMinsDefault;
|
||||
light_nl[F("tbri")] = nightlightTargetBri;
|
||||
light_nl[F("macro")] = macroNl;
|
||||
|
||||
@ -549,7 +594,7 @@ void serializeConfig() {
|
||||
JsonArray def_cy_range = def_cy.createNestedArray(F("range"));
|
||||
def_cy_range.add(presetCycleMin);
|
||||
def_cy_range.add(presetCycleMax);
|
||||
def_cy[F("dur")] = presetCycleTime;
|
||||
def_cy["dur"] = presetCycleTime;
|
||||
}
|
||||
|
||||
JsonObject interfaces = doc.createNestedObject("if");
|
||||
@ -561,7 +606,7 @@ void serializeConfig() {
|
||||
JsonObject if_sync_recv = if_sync.createNestedObject("recv");
|
||||
if_sync_recv["bri"] = receiveNotificationBrightness;
|
||||
if_sync_recv["col"] = receiveNotificationColor;
|
||||
if_sync_recv[F("fx")] = receiveNotificationEffects;
|
||||
if_sync_recv["fx"] = receiveNotificationEffects;
|
||||
|
||||
JsonObject if_sync_send = if_sync.createNestedObject("send");
|
||||
if_sync_send[F("dir")] = notifyDirect;
|
||||
@ -596,11 +641,15 @@ void serializeConfig() {
|
||||
JsonArray if_va_macros = if_va.createNestedArray("macros");
|
||||
if_va_macros.add(macroAlexaOn);
|
||||
if_va_macros.add(macroAlexaOff);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
JsonObject if_blynk = interfaces.createNestedObject("blynk");
|
||||
if_blynk[F("token")] = strlen(blynkApiKey) ? "Hidden":"";
|
||||
if_blynk[F("host")] = blynkHost;
|
||||
if_blynk["port"] = blynkPort;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||
if_mqtt["en"] = mqttEnabled;
|
||||
if_mqtt[F("broker")] = mqttServer;
|
||||
@ -612,7 +661,9 @@ void serializeConfig() {
|
||||
JsonObject if_mqtt_topics = if_mqtt.createNestedObject(F("topics"));
|
||||
if_mqtt_topics[F("device")] = mqttDeviceTopic;
|
||||
if_mqtt_topics[F("group")] = mqttGroupTopic;
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
JsonObject if_hue = interfaces.createNestedObject("hue");
|
||||
if_hue["en"] = huePollingEnabled;
|
||||
if_hue["id"] = huePollLightId;
|
||||
@ -627,6 +678,7 @@ void serializeConfig() {
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
if_hue_ip.add(hueIP[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
JsonObject if_ntp = interfaces.createNestedObject("ntp");
|
||||
if_ntp["en"] = ntpEnabled;
|
||||
@ -641,7 +693,7 @@ void serializeConfig() {
|
||||
ol[F("clock")] = overlayDefault;
|
||||
ol[F("cntdwn")] = countdownMode;
|
||||
|
||||
ol[F("min")] = overlayMin;
|
||||
ol["min"] = overlayMin;
|
||||
ol[F("max")] = overlayMax;
|
||||
ol[F("o12pix")] = analogClock12pixel;
|
||||
ol[F("o5m")] = analogClock5MinuteMarks;
|
||||
@ -662,7 +714,7 @@ void serializeConfig() {
|
||||
JsonObject timers_ins0 = timers_ins.createNestedObject();
|
||||
timers_ins0["en"] = (timerWeekday[i] & 0x01);
|
||||
timers_ins0[F("hour")] = timerHours[i];
|
||||
timers_ins0[F("min")] = timerMinutes[i];
|
||||
timers_ins0["min"] = timerMinutes[i];
|
||||
timers_ins0[F("macro")] = timerMacro[i];
|
||||
timers_ins0[F("dow")] = timerWeekday[i] >> 1;
|
||||
}
|
||||
@ -684,7 +736,6 @@ void serializeConfig() {
|
||||
for (byte i = 0; i < 15; i++)
|
||||
dmx_fixmap.add(DMXFixtureMap[i]);
|
||||
#endif
|
||||
//}
|
||||
|
||||
JsonObject usermods_settings = doc.createNestedObject("um");
|
||||
usermods.addToConfig(usermods_settings);
|
||||
@ -711,15 +762,21 @@ bool deserializeConfigSec() {
|
||||
|
||||
JsonObject interfaces = doc["if"];
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
||||
int tdd = strnlen(apikey, 36);
|
||||
if (tdd > 20 || tdd == 0)
|
||||
getStringFromJson(blynkApiKey, apikey, 36);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces["mqtt"];
|
||||
getStringFromJson(mqttPass, if_mqtt["psk"], 41);
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
getStringFromJson(hueApiKey, interfaces[F("hue")][F("key")], 47);
|
||||
#endif
|
||||
|
||||
JsonObject ota = doc["ota"];
|
||||
getStringFromJson(otaPass, ota[F("pwd")], 33);
|
||||
@ -746,12 +803,18 @@ void serializeConfigSec() {
|
||||
ap["psk"] = apPass;
|
||||
|
||||
JsonObject interfaces = doc.createNestedObject("if");
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
JsonObject if_blynk = interfaces.createNestedObject("blynk");
|
||||
if_blynk[F("token")] = blynkApiKey;
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||
if_mqtt["psk"] = mqttPass;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
JsonObject if_hue = interfaces.createNestedObject("hue");
|
||||
if_hue[F("key")] = hueApiKey;
|
||||
#endif
|
||||
|
||||
JsonObject ota = doc.createNestedObject("ota");
|
||||
ota[F("pwd")] = otaPass;
|
||||
|
@ -31,39 +31,47 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WLED_MAX_BUTTONS
|
||||
#ifdef ESP8266
|
||||
#define WLED_MAX_BUTTONS 2
|
||||
#else
|
||||
#define WLED_MAX_BUTTONS 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Usermod IDs
|
||||
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
|
||||
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
|
||||
#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h"
|
||||
#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h"
|
||||
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
|
||||
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
|
||||
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
|
||||
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
|
||||
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
|
||||
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
|
||||
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
|
||||
#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h"
|
||||
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
|
||||
#define USERMOD_ID_RTC 13 //Usermod "usermod_rtc.h"
|
||||
#define USERMOD_ID_ELEKSTUBE_IPS 14 //Usermod "usermod_elekstube_ips.h"
|
||||
#define USERMOD_ID_MULTI_RELAY 101 //Usermod "usermod_multi_relay.h"
|
||||
#define USERMOD_ID_ANIMATED_STAIRCASE 102 //Usermod "Animated_Staircase.h"
|
||||
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
|
||||
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
|
||||
#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h"
|
||||
#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h"
|
||||
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
|
||||
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
|
||||
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
|
||||
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
|
||||
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
|
||||
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
|
||||
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
|
||||
#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h"
|
||||
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
|
||||
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
|
||||
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
|
||||
#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h"
|
||||
#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
||||
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
||||
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||
|
||||
//Notifier callMode
|
||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
||||
#define NOTIFIER_CALL_MODE_BUTTON 2
|
||||
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
|
||||
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
|
||||
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
|
||||
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define NOTIFIER_CALL_MODE_HUE 7
|
||||
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
||||
#define NOTIFIER_CALL_MODE_BLYNK 9
|
||||
@ -150,9 +158,11 @@
|
||||
#define BTN_TYPE_NONE 0
|
||||
#define BTN_TYPE_RESERVED 1
|
||||
#define BTN_TYPE_PUSH 2
|
||||
#define BTN_TYPE_PUSH_ACT_HIGH 3 //not implemented
|
||||
#define BTN_TYPE_PUSH_ACT_HIGH 3
|
||||
#define BTN_TYPE_SWITCH 4
|
||||
#define BTN_TYPE_SWITCH_ACT_HIGH 5 //not implemented
|
||||
#define BTN_TYPE_SWITCH_ACT_HIGH 5
|
||||
#define BTN_TYPE_TOUCH 6
|
||||
#define BTN_TYPE_ANALOG 7
|
||||
|
||||
//Ethernet board types
|
||||
#define WLED_NUM_ETH_TYPES 5
|
||||
@ -205,7 +215,7 @@
|
||||
// maximum number of LEDs - more than 1500 LEDs (or 500 DMA "LEDPIN 3" driven ones) will cause a low memory condition on ESP8266
|
||||
#ifndef MAX_LEDS
|
||||
#ifdef ESP8266
|
||||
#define MAX_LEDS 8192 //rely on memory limit to limit this to 1600 LEDs
|
||||
#define MAX_LEDS 1664 // can't rely on memory limit to limit this to 1600 LEDs
|
||||
#else
|
||||
#define MAX_LEDS 8192
|
||||
#endif
|
||||
@ -245,7 +255,7 @@
|
||||
#ifdef ESP8266
|
||||
#define JSON_BUFFER_SIZE 9216
|
||||
#else
|
||||
#define JSON_BUFFER_SIZE 16384
|
||||
#define JSON_BUFFER_SIZE 20480
|
||||
#endif
|
||||
|
||||
// Maximum size of node map (list of other WLED instances)
|
||||
|
@ -1,356 +1,408 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<title>LED Settings</title>
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxM=5000,maxPB=4096,bquot=0; //maximum bytes for LED allocation: 5kB for 8266, 32kB for 32
|
||||
function H()
|
||||
{
|
||||
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
}
|
||||
function off(n){
|
||||
d.getElementsByName(n)[0].value = -1;
|
||||
}
|
||||
function bLimits(b,p,m) {
|
||||
maxB = b; maxM = m; maxPB = p;
|
||||
}
|
||||
function trySubmit(event) {
|
||||
event.preventDefault();
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2);
|
||||
|
||||
//check for pin conflicts
|
||||
if (nm=="L0" || nm=="L1" || nm=="RL" || nm=="BT" || nm=="IR" || nm=="AX")
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].focus();return;}
|
||||
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert("Usermod pin conflict!");LCs[i].focus();return;}
|
||||
for (j=i+1; j<LCs.length; j++)
|
||||
{
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
if (n2=="L0" || n2=="L1" || n2=="RL" || n2=="BT" || n2=="IR" || n2=="AX")
|
||||
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {alert("Pin conflict!");LCs[i].focus();return;}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (maxM < 10000) msg += " Consider using an ESP32."; alert(msg); return;}
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
if (d.Sf.reportValidity()) d.Sf.submit();
|
||||
}
|
||||
function S(){GetV();setABL();}
|
||||
function enABL()
|
||||
{
|
||||
var en = d.getElementById('able').checked;
|
||||
d.Sf.LA.value = (en) ? laprev:0;
|
||||
d.getElementById('abl').style.display = (en) ? 'inline':'none';
|
||||
d.getElementById('psu2').style.display = (en) ? 'inline':'none';
|
||||
if (d.Sf.LA.value > 0) setABL();
|
||||
}
|
||||
function enLA()
|
||||
{
|
||||
var val = d.Sf.LAsel.value;
|
||||
d.Sf.LA.value = val;
|
||||
d.getElementById('LAdis').style.display = (val == 50) ? 'inline':'none';
|
||||
UI();
|
||||
}
|
||||
function setABL()
|
||||
{
|
||||
d.getElementById('able').checked = true;
|
||||
d.Sf.LAsel.value = 50;
|
||||
switch (parseInt(d.Sf.LA.value)) {
|
||||
case 0: d.getElementById('able').checked = false; enABL(); break;
|
||||
case 30: d.Sf.LAsel.value = 30; break;
|
||||
case 35: d.Sf.LAsel.value = 35; break;
|
||||
case 55: d.Sf.LAsel.value = 55; break;
|
||||
case 255: d.Sf.LAsel.value = 255; break;
|
||||
default: d.getElementById('LAdis').style.display = 'inline';
|
||||
}
|
||||
d.getElementById('m1').innerHTML = maxM;
|
||||
UI();
|
||||
}
|
||||
//returns mem usage
|
||||
function getMem(type, len, p0) {
|
||||
//len = parseInt(len);
|
||||
if (type < 32) {
|
||||
if (maxM < 10000 && p0 ==3) { //8266 DMA uses 5x the mem
|
||||
if (type > 29) return len*20; //RGBW
|
||||
return len*15;
|
||||
} else if (maxM >= 10000) //ESP32 RMT uses double buffer?
|
||||
{
|
||||
if (type > 29) return len*8; //RGBW
|
||||
return len*6;
|
||||
}
|
||||
if (type > 29) return len*4; //RGBW
|
||||
return len*3;
|
||||
}
|
||||
if (type > 31 && type < 48) return 5;
|
||||
if (type == 44 || type == 45) return len*4; //RGBW
|
||||
return len*3;
|
||||
}
|
||||
function UI()
|
||||
{
|
||||
var isRGBW = false, memu = 0;
|
||||
|
||||
d.getElementById('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none';
|
||||
|
||||
if (d.Sf.LA.value == 255) laprev = 12;
|
||||
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
|
||||
|
||||
var s = d.getElementsByTagName("select");
|
||||
for (i=0; i<s.length; i++) {
|
||||
if (s[i].name.substring(0,2)=="LT") {
|
||||
n=s[i].name.substring(2);
|
||||
var type = s[i].value;
|
||||
d.getElementById("p0d"+n).innerHTML = (type > 49) ? "Data pin:" : (type >41) ? "Pins:" : "Pin:";
|
||||
d.getElementById("p1d"+n).innerHTML = (type > 49) ? "Clk:" : "";
|
||||
var LK = d.getElementsByName("L1"+n)[0];
|
||||
|
||||
memu += getMem(type, d.getElementsByName("LC"+n)[0].value, d.getElementsByName("L0"+n)[0].value);
|
||||
|
||||
for (p=1; p<5; p++) {
|
||||
var LK = d.getElementsByName("L"+p+n)[0];
|
||||
if (!LK) continue;
|
||||
if ((type>49 && p==1) || (type>41 && type < 50 && (p+40 < type))) // TYPE_xxxx values from const.h
|
||||
{
|
||||
LK.style.display = "inline";
|
||||
LK.required = true;
|
||||
} else {
|
||||
LK.style.display = "none";
|
||||
LK.required = false;
|
||||
LK.value="";
|
||||
}
|
||||
}
|
||||
if (type == 30 || type == 31 || (type > 40 && type < 46 && type != 43)) isRGBW = true;
|
||||
d.getElementById("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline";
|
||||
d.getElementById("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:";
|
||||
}
|
||||
}
|
||||
|
||||
var myC = d.querySelectorAll('.wc'),
|
||||
l = myC.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
myC[i].style.display = (isRGBW) ? 'inline':'none';
|
||||
}
|
||||
|
||||
if (d.activeElement == d.getElementsByName("LC")[0]) {
|
||||
var o = d.getElementsByClassName("iST");
|
||||
var i = o.length;
|
||||
if (i == 1) d.getElementsByName("LC0")[0].value = d.getElementsByName("LC")[0].value;
|
||||
}
|
||||
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
var sLC = 0, maxLC = 0;
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2);
|
||||
if (nm=="LC" && LCs[i].name != "LC") {var c = parseInt(LCs[i].value,10); if (c) {sLC+=c; if (c>maxLC) maxLC = c;} continue;}
|
||||
}
|
||||
|
||||
d.getElementById('m0').innerHTML = memu;
|
||||
bquot = memu / maxM * 100;
|
||||
d.getElementById('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? bquot > 90 ? "red":"orange":"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`;
|
||||
d.getElementById('ledwarning').style.display = (maxLC > 800 || bquot > 80) ? 'inline':'none';
|
||||
//TODO add warning "Recommended pins on ESP8266 are 1 and 2 (3 only with low LED count)"
|
||||
//TODO add overmemory warning
|
||||
//TODO block disallowed pins 6-11
|
||||
d.getElementById('wreason').innerHTML = (bquot > 80) ? "than 60%% of max. LED memory" : "800 LEDs per pin";
|
||||
|
||||
//var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
|
||||
var val = Math.ceil((100 + sLC * laprev)/500)/2;
|
||||
val = (val > 5) ? Math.ceil(val) : val;
|
||||
var s = "";
|
||||
var is12V = (d.Sf.LAsel.value == 30);
|
||||
var isWS2815 = (d.Sf.LAsel.value == 255);
|
||||
if (val < 1.02 && !is12V && !isWS2815)
|
||||
{
|
||||
s = "ESP 5V pin with 1A USB supply";
|
||||
} else
|
||||
{
|
||||
s += is12V ? "12V ": isWS2815 ? "WS2815 12V " : "5V ";
|
||||
s += val;
|
||||
s += "A supply connected to LEDs";
|
||||
}
|
||||
var val2 = Math.ceil((100 + sLC * laprev)/1500)/2;
|
||||
val2 = (val2 > 5) ? Math.ceil(val2) : val2;
|
||||
var s2 = "(for most effects, ~";
|
||||
s2 += val2;
|
||||
s2 += "A is enough)<br>";
|
||||
d.getElementById('psu').innerHTML = s;
|
||||
d.getElementById('psu2').innerHTML = isWS2815 ? "" : s2;
|
||||
}
|
||||
function lastEnd(i) {
|
||||
if (i<1) return 0;
|
||||
v = parseInt(d.getElementsByName("LS"+(i-1))[0].value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
||||
if (isNaN(v)) return 0;
|
||||
return v;
|
||||
}
|
||||
function addLEDs(n)
|
||||
{
|
||||
if (n>1) {maxB=n; d.getElementById("+").style.display="inline"; return;}
|
||||
|
||||
var o = d.getElementsByClassName("iST");
|
||||
var i = o.length;
|
||||
|
||||
if ((n==1 && i>=maxB) || (n==-1 && i==0)) return;
|
||||
|
||||
var f = d.getElementById("mLC");
|
||||
if (n==1) {
|
||||
var cn = `<div class="iST">
|
||||
${i>0?'<hr style="width:260px">':''}
|
||||
${i+1}:
|
||||
<select name="LT${i}" onchange="UI()">
|
||||
<option value="22">WS281x</option>
|
||||
<option value="30">SK6812 RGBW</option>
|
||||
<option value="31">TM1814</option>
|
||||
<option value="24">400kHz</option>
|
||||
<option value="50">WS2801</option>
|
||||
<option value="51">APA102</option>
|
||||
<option value="52">LPD8806</option>
|
||||
<option value="53">P9813</option>
|
||||
<option value="41">PWM White</option>
|
||||
<option value="42">PWM WWCW</option>
|
||||
<option value="43">PWM RGB</option>
|
||||
<option value="44">PWM RGBW</option>
|
||||
<option value="45">PWM RGBWC</option>
|
||||
</select>
|
||||
Color Order:
|
||||
<select name="CO${i}">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
<option value="3">RBG</option>
|
||||
<option value="4">BGR</option>
|
||||
<option value="5">GBR</option>
|
||||
</select><br>
|
||||
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:35px" oninput="UI()"/>
|
||||
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:35px"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:35px"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:35px"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:35px"/>
|
||||
<br>
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" min="0" max="8191" value="${lastEnd(i)}" required />
|
||||
<div id="dig${i}" style="display:inline">
|
||||
Count: <input type="number" name="LC${i}" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br>
|
||||
Skip 1<sup>st</sup> LED: <input id="sl${i}" type="checkbox" name="SL${i}">
|
||||
</div>
|
||||
Reverse: <input type="checkbox" name="CV${i}"><br>
|
||||
</div>`;
|
||||
f.insertAdjacentHTML("beforeend", cn);
|
||||
}
|
||||
if (n==-1) {
|
||||
o[--i].remove();--i;
|
||||
}
|
||||
|
||||
d.getElementById("+").style.display = (i<maxB-1) ? "inline":"none";
|
||||
d.getElementById("-").style.display = (i>0) ? "inline":"none";
|
||||
|
||||
UI();
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
//d.um_p=[];addLEDs(3);d.Sf.LC.value=250;addLEDs(1);d.Sf.L00.value=2;d.Sf.L10.value=0;d.Sf.LC0.value=250;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=0;d.Sf.LS0.checked=0;d.Sf.MA.value=5400;d.Sf.LA.value=55;d.getElementsByClassName("pow")[0].innerHTML="350mA";d.Sf.CA.value=40;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=3;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=64;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RV.checked=0;d.Sf.SL.checked=0;d.Sf.RL.value=12;d.Sf.RM.checked=0;d.Sf.BT.value=-1;d.Sf.IR.value=-1;d.Sf.AX.value=-1;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import url("style.css");
|
||||
</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post" onsubmit="trySubmit(event)">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>LED & Hardware setup</h2>
|
||||
Total LED count: <input name="LC" type="number" min="1" max="8192" oninput="UI()" required><br>
|
||||
<i>Recommended power supply for brightest white:</i><br>
|
||||
<b><span id="psu">?</span></b><br>
|
||||
<span id="psu2"><br></span>
|
||||
<br>
|
||||
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
|
||||
<div id="abl">
|
||||
Maximum Current: <input name="MA" type="number" min="250" max="65000" oninput="UI()" required> mA<br>
|
||||
<div id="ampwarning" style="color: orange; display: none;">
|
||||
⚠ Your power supply provides high current.<br>
|
||||
To improve the safety of your setup,<br>
|
||||
please use thick cables,<br>
|
||||
multiple power injection points and a fuse!<br>
|
||||
</div>
|
||||
<i>Automatically limits brightness to stay close to the limit.<br>
|
||||
Keep at <1A if powering LEDs directly from the ESP 5V pin!<br>
|
||||
If you are using an external power supply, enter its rating.<br>
|
||||
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
|
||||
LED voltage (Max. current for a single LED):<br>
|
||||
<select name="LAsel" onchange="enLA()">
|
||||
<option value="55" selected>5V default (55mA)</option>
|
||||
<option value="35">5V efficient (35mA)</option>
|
||||
<option value="30">12V (30mA)</option>
|
||||
<option value="255">WS2815 (12mA)</option>
|
||||
<option value="50">Custom</option>
|
||||
</select><br>
|
||||
<span id="LAdis" style="display: none;">Custom max. current per LED: <input name="LA" type="number" min="0" max="255" id="la" oninput="UI()" required> mA<br></span>
|
||||
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
|
||||
</div>
|
||||
<h3>Hardware setup</h3>
|
||||
<div id="mLC">LED outputs:</div>
|
||||
<button type="button" id="+" onclick="addLEDs(1)" style="display:none;border-radius:20px;height:36px;">+</button>
|
||||
<button type="button" id="-" onclick="addLEDs(-1)" style="display:none;border-radius:20px;width:36px;height:36px;">-</button><br>
|
||||
LED Memory Usage: <span id="m0">0</span> / <span id="m1">?</span> B<br>
|
||||
<div id="dbar" style="display:inline-block; width: 100px; height: 10px; border-radius: 20px;"></div><br>
|
||||
<div id="ledwarning" style="color: orange; display: none;">
|
||||
⚠ You might run into stability or lag issues.<br>
|
||||
Use less than <span id="wreason">800 LEDs per pin</span> for the best experience!<br>
|
||||
</div>
|
||||
Button pin: <input type="number" min="-1" max="40" name="BT" onchange="UI()"><span style="cursor: pointer;" onclick="off('BT')"> ×</span><br>
|
||||
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()"><span style="cursor: pointer;" onclick="off('IR')"> ×</span><br>
|
||||
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
||||
Active high <input type="checkbox" name="RM">
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br><br>
|
||||
Apply preset <input name="BP" type="number" min="0" max="250" required> at boot (0 uses defaults)
|
||||
<br>- <i>or</i> -<br>
|
||||
Set current preset cycle setting as boot default: <input type="checkbox" name="PC"><br><br>
|
||||
Use Gamma correction for color: <input type="checkbox" name="GC"> (strongly recommended)<br>
|
||||
Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br><br>
|
||||
Brightness factor: <input name="BF" type="number" min="1" max="255" required> %
|
||||
<h3>Transitions</h3>
|
||||
Crossfade: <input type="checkbox" name="TF"><br>
|
||||
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
|
||||
Enable Palette transitions: <input type="checkbox" name="PF">
|
||||
<h3>Timed light</h3>
|
||||
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
|
||||
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
|
||||
Mode:
|
||||
<select name="TW">
|
||||
<option value="0">Wait and set</option>
|
||||
<option value="1">Fade</option>
|
||||
<option value="2">Fade Color</option>
|
||||
<option value="3">Sunrise</option>
|
||||
</select>
|
||||
<h3>Advanced</h3>
|
||||
Palette blending:
|
||||
<select name="PB">
|
||||
<option value="0">Linear (wrap if moving)</option>
|
||||
<option value="1">Linear (always wrap)</option>
|
||||
<option value="2">Linear (never wrap)</option>
|
||||
<option value="3">None (not recommended)</option>
|
||||
</select><br>
|
||||
<span class="wc">
|
||||
Auto-calculate white channel from RGB:<br>
|
||||
<select name="AW">
|
||||
<option value=0>None</option>
|
||||
<option value=1>Brighter</option>
|
||||
<option value=2>Accurate</option>
|
||||
<option value=3>Dual</option>
|
||||
<option value=4>Legacy</option>
|
||||
</select>
|
||||
<br></span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=500">
|
||||
<title>LED Settings</title>
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxM=5000,maxPB=4096,bquot=0; //maximum bytes for LED allocation: 5kB for 8266, 32kB for 32
|
||||
function H()
|
||||
{
|
||||
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
function off(n){
|
||||
d.getElementsByName(n)[0].value = -1;
|
||||
}
|
||||
function bLimits(b,p,m) {
|
||||
maxB = b; maxM = m; maxPB = p;
|
||||
}
|
||||
function pinsOK() {
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2);
|
||||
//check for pin conflicts
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert(`Sorry, pins ${JSON.stringify(d.um_p)} can't be used.`);LCs[i].value="";LCs[i].focus();return false;}
|
||||
else if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].value="";LCs[i].focus();return false;}
|
||||
for (j=i+1; j<LCs.length; j++)
|
||||
{
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4" || n2=="RL" || n2=="BT" || n2=="IR")
|
||||
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {alert(`Pin conflict between ${nm}/${n2}!`);LCs[j].value="";LCs[j].focus();return false;}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function trySubmit(e) {
|
||||
e.preventDefault();
|
||||
if (!pinsOK()) {e.stopPropagation();return false;} // Prevent form submission and contact with server
|
||||
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (maxM < 10000) msg += "\n\rConsider using an ESP32."; alert(msg);}
|
||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||
}
|
||||
function S(){GetV();setABL();}
|
||||
function enABL()
|
||||
{
|
||||
var en = gId('able').checked;
|
||||
d.Sf.LA.value = (en) ? laprev:0;
|
||||
gId('abl').style.display = (en) ? 'inline':'none';
|
||||
gId('psu2').style.display = (en) ? 'inline':'none';
|
||||
if (d.Sf.LA.value > 0) setABL();
|
||||
}
|
||||
function enLA()
|
||||
{
|
||||
var val = d.Sf.LAsel.value;
|
||||
d.Sf.LA.value = val;
|
||||
gId('LAdis').style.display = (val == 50) ? 'inline':'none';
|
||||
UI();
|
||||
}
|
||||
function setABL()
|
||||
{
|
||||
gId('able').checked = true;
|
||||
d.Sf.LAsel.value = 50;
|
||||
switch (parseInt(d.Sf.LA.value)) {
|
||||
case 0: gId('able').checked = false; enABL(); break;
|
||||
case 30: d.Sf.LAsel.value = 30; break;
|
||||
case 35: d.Sf.LAsel.value = 35; break;
|
||||
case 55: d.Sf.LAsel.value = 55; break;
|
||||
case 255: d.Sf.LAsel.value = 255; break;
|
||||
default: gId('LAdis').style.display = 'inline';
|
||||
}
|
||||
gId('m1').innerHTML = maxM;
|
||||
d.getElementsByName("Sf")[0].addEventListener("submit", trySubmit);
|
||||
UI();
|
||||
}
|
||||
//returns mem usage
|
||||
function getMem(type, len, p0) {
|
||||
if (type < 32) {
|
||||
if (maxM < 10000 && p0==3) { //8266 DMA uses 5x the mem
|
||||
if (type > 29) return len*20; //RGBW
|
||||
return len*15;
|
||||
} else if (maxM >= 10000) //ESP32 RMT uses double buffer?
|
||||
{
|
||||
if (type > 29) return len*8; //RGBW
|
||||
return len*6;
|
||||
}
|
||||
if (type > 29) return len*4; //RGBW
|
||||
return len*3;
|
||||
}
|
||||
if (type > 31 && type < 48) return 5;
|
||||
if (type == 44 || type == 45) return len*4; //RGBW
|
||||
return len*3;
|
||||
}
|
||||
function UI(change=false)
|
||||
{
|
||||
var isRGBW = false, memu = 0;
|
||||
|
||||
gId('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none';
|
||||
|
||||
if (d.Sf.LA.value == 255) laprev = 12;
|
||||
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
|
||||
|
||||
var s = d.getElementsByTagName("select");
|
||||
for (i=0; i<s.length; i++) {
|
||||
if (s[i].name.substring(0,2)=="LT") {
|
||||
n=s[i].name.substring(2);
|
||||
var type = parseInt(s[i].value,10);
|
||||
gId("p0d"+n).innerHTML = (type > 49) ? "Data:" : (type >41) ? "Pins:" : "Pin:";
|
||||
gId("p1d"+n).innerHTML = (type > 49) ? "Clk:" : "";
|
||||
var LK = d.getElementsByName("L1"+n)[0];
|
||||
|
||||
memu += getMem(type, d.getElementsByName("LC"+n)[0].value, d.getElementsByName("L0"+n)[0].value);
|
||||
|
||||
for (p=1; p<5; p++) {
|
||||
var LK = d.getElementsByName("L"+p+n)[0];
|
||||
if (!LK) continue;
|
||||
if ((type>49 && p==1) || (type>41 && type < 50 && (p+40 < type))) // TYPE_xxxx values from const.h
|
||||
{
|
||||
LK.style.display = "inline";
|
||||
LK.required = true;
|
||||
} else {
|
||||
LK.style.display = "none";
|
||||
LK.required = false;
|
||||
LK.value="";
|
||||
}
|
||||
}
|
||||
if (type == 30 || type == 31 || (type > 40 && type < 46 && type != 43)) isRGBW = true;
|
||||
gId("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline";
|
||||
gId("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:";
|
||||
}
|
||||
}
|
||||
|
||||
var myC = d.querySelectorAll('.wc'),
|
||||
l = myC.length;
|
||||
for (i = 0; i < l; i++) {
|
||||
myC[i].style.display = (isRGBW) ? 'inline':'none';
|
||||
}
|
||||
|
||||
if (d.activeElement == d.getElementsByName("LC")[0]) {
|
||||
var o = d.getElementsByClassName("iST");
|
||||
var i = o.length;
|
||||
if (i == 1) d.getElementsByName("LC0")[0].value = d.getElementsByName("LC")[0].value;
|
||||
}
|
||||
|
||||
var LCs = d.getElementsByTagName("input");
|
||||
var sLC = 0, maxLC = 0;
|
||||
for (i=0; i<LCs.length; i++) {
|
||||
var nm = LCs[i].name.substring(0,2);
|
||||
if (nm=="LC" && LCs[i].name !== "LC") {
|
||||
var n=LCs[i].name.substring(2);
|
||||
var c=parseInt(LCs[i].value,10);
|
||||
if(gId("ls"+n).readOnly) gId("ls"+n).value=sLC;
|
||||
if(c){sLC+=c;if(c>maxLC)maxLC=c;}
|
||||
continue;
|
||||
}
|
||||
if (nm=="L0" || nm=="L1") {
|
||||
var lc=d.getElementsByName("LC"+LCs[i].name.substring(2))[0];
|
||||
lc.max=maxPB;
|
||||
}
|
||||
if (nm=="L0" || nm=="L1" || nm=="L2" || nm=="L3" || nm=="L4" || nm=="RL" || nm=="BT" || nm=="IR")
|
||||
if (LCs[i].value!="" && LCs[i].value!="-1") {
|
||||
var p = [];
|
||||
if (d.um_p && Array.isArray(d.um_p)) for (k=0;k<d.um_p.length;k++) p.push(d.um_p[k]);
|
||||
for (j=0; j<LCs.length; j++) {
|
||||
if (i==j) continue;
|
||||
var n2 = LCs[j].name.substring(0,2);
|
||||
if (n2=="L0" || n2=="L1" || n2=="L2" || n2=="L3" || n2=="L4" || n2=="RL" || n2=="BT" || n2=="IR")
|
||||
if (LCs[j].value!="" && LCs[j].value!="-1") p.push(parseInt(LCs[j].value,10));
|
||||
}
|
||||
if (p.some((e)=>e==parseInt(LCs[i].value,10))) LCs[i].style.color="red"; else LCs[i].style.color="#fff";
|
||||
}
|
||||
}
|
||||
|
||||
gId('m0').innerHTML = memu;
|
||||
bquot = memu / maxM * 100;
|
||||
gId('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? (bquot > 90 ? "red":"orange"):"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`;
|
||||
gId('ledwarning').style.display = (sLC > maxPB || maxLC > 800 || bquot > 80) ? 'inline':'none';
|
||||
gId('ledwarning').style.color = (sLC > maxPB || maxLC > maxPB || bquot > 100) ? 'red':'orange';
|
||||
gId('wreason').innerHTML = (bquot > 80) ? "80% of max. LED memory" +(bquot>100 ? ` (<b>WARNING: Using over ${maxM}B!</b>)` : "") : "800 LEDs per pin";
|
||||
|
||||
//var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
|
||||
var val = Math.ceil((100 + sLC * laprev)/500)/2;
|
||||
val = (val > 5) ? Math.ceil(val) : val;
|
||||
var s = "";
|
||||
var is12V = (d.Sf.LAsel.value == 30);
|
||||
var isWS2815 = (d.Sf.LAsel.value == 255);
|
||||
if (val < 1.02 && !is12V && !isWS2815)
|
||||
{
|
||||
s = "ESP 5V pin with 1A USB supply";
|
||||
} else
|
||||
{
|
||||
s += is12V ? "12V ": isWS2815 ? "WS2815 12V " : "5V ";
|
||||
s += val;
|
||||
s += "A supply connected to LEDs";
|
||||
}
|
||||
var val2 = Math.ceil((100 + sLC * laprev)/1500)/2;
|
||||
val2 = (val2 > 5) ? Math.ceil(val2) : val2;
|
||||
var s2 = "(for most effects, ~";
|
||||
s2 += val2;
|
||||
s2 += "A is enough)<br>";
|
||||
gId('psu').innerHTML = s;
|
||||
gId('psu2').innerHTML = isWS2815 ? "" : s2;
|
||||
}
|
||||
function lastEnd(i) {
|
||||
if (i<1) return 0;
|
||||
v = parseInt(d.getElementsByName("LS"+(i-1))[0].value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
||||
if (isNaN(v)) return 0;
|
||||
return v;
|
||||
}
|
||||
function addLEDs(n)
|
||||
{
|
||||
if (n>1) {maxB=n; gId("+").style.display="inline"; return;}
|
||||
|
||||
var o = d.getElementsByClassName("iST");
|
||||
var i = o.length;
|
||||
|
||||
if ((n==1 && i>=maxB) || (n==-1 && i==0)) return;
|
||||
|
||||
var f = gId("mLC");
|
||||
if (n==1) {
|
||||
// npm run build has trouble minimizing spaces inside string
|
||||
var cn = `<div class="iST">
|
||||
${i>0?'<hr style="width:260px">':''}
|
||||
${i+1}:
|
||||
<select name="LT${i}" onchange="UI()">
|
||||
<option value="22">WS281x</option>
|
||||
<option value="30">SK6812 RGBW</option>
|
||||
<option value="31">TM1814</option>
|
||||
<option value="24">400kHz</option>
|
||||
<option value="50">WS2801</option>
|
||||
<option value="51">APA102</option>
|
||||
<option value="52">LPD8806</option>
|
||||
<option value="53">P9813</option>
|
||||
<option value="41">PWM White</option>
|
||||
<option value="42">PWM WWCW</option>
|
||||
<option value="43">PWM RGB</option>
|
||||
<option value="44">PWM RGBW</option>
|
||||
<option value="45">PWM RGBWC</option>
|
||||
</select>
|
||||
Color Order:
|
||||
<select name="CO${i}">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
<option value="3">RBG</option>
|
||||
<option value="4">BGR</option>
|
||||
<option value="5">GBR</option>
|
||||
</select><br>
|
||||
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:35px" onchange="UI()"/>
|
||||
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<br>
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" required />
|
||||
<div id="dig${i}" style="display:inline">
|
||||
Count: <input type="number" name="LC${i}" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br>
|
||||
Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
||||
Skip 1<sup>st</sup> LED: <input id="sl${i}" type="checkbox" name="SL${i}"><br>
|
||||
</div>
|
||||
</div>`;
|
||||
f.insertAdjacentHTML("beforeend", cn);
|
||||
}
|
||||
if (n==-1) {
|
||||
o[--i].remove();--i;
|
||||
}
|
||||
|
||||
gId("+").style.display = (i<maxB-1) ? "inline":"none";
|
||||
gId("-").style.display = (i>0) ? "inline":"none";
|
||||
|
||||
UI();
|
||||
}
|
||||
function addBtn(i,p,t) {
|
||||
var c = gId("btns").innerHTML;
|
||||
var bt = "BT" + i;
|
||||
var be = "BE" + i;
|
||||
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" style="width:35px" value="${p}"> `;
|
||||
c += `<select name="${be}">`
|
||||
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
|
||||
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
|
||||
c += `<option value="2" ${t==3?"selected":""}>Push inverted</option>`;
|
||||
c += `<option value="4" ${t==4?"selected":""}>Switch</option>`;
|
||||
c += `<option value="5" ${t==4?"selected":""}>Switch inverted</option>`;
|
||||
c += `<option value="6" ${t==6?"selected":""}>Touch</option>`;
|
||||
c += `<option value="7" ${t==7?"selected":""}>Analog</option>`;
|
||||
c += `</select>`;
|
||||
c += `<span style="cursor: pointer;" onclick="off('${bt}')"> ×</span><br>`;
|
||||
gId("btns").innerHTML = c;
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
//maxM=5000;maxPB=1536;d.um_p=[1,6,7,8,9,10,11];addLEDs(3);d.Sf.LC.value=250;addLEDs(1);d.Sf.L00.value=2;d.Sf.L10.value=0;d.Sf.LC0.value=250;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=0;d.Sf.LS0.checked=0;d.Sf.MA.value=5400;d.Sf.LA.value=55;d.getElementsByClassName("pow")[0].innerHTML="350mA";d.Sf.CA.value=40;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=3;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=64;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=12;d.Sf.RM.checked=0;addBtn(0,0,2);addBtn(1,3,4);addBtn(2,-1,0);d.Sf.IR.value=-1;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import url("style.css");
|
||||
</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>LED & Hardware setup</h2>
|
||||
Total LED count: <input name="LC" id="LC" type="number" min="1" max="8192" oninput="UI()" required><br>
|
||||
<i>Recommended power supply for brightest white:</i><br>
|
||||
<b><span id="psu">?</span></b><br>
|
||||
<span id="psu2"><br></span>
|
||||
<br>
|
||||
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
|
||||
<div id="abl">
|
||||
Maximum Current: <input name="MA" type="number" min="250" max="65000" oninput="UI()" required> mA<br>
|
||||
<div id="ampwarning" style="color: orange; display: none;">
|
||||
⚠ Your power supply provides high current.<br>
|
||||
To improve the safety of your setup,<br>
|
||||
please use thick cables,<br>
|
||||
multiple power injection points and a fuse!<br>
|
||||
</div>
|
||||
<i>Automatically limits brightness to stay close to the limit.<br>
|
||||
Keep at <1A if powering LEDs directly from the ESP 5V pin!<br>
|
||||
If you are using an external power supply, enter its rating.<br>
|
||||
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
|
||||
LED voltage (Max. current for a single LED):<br>
|
||||
<select name="LAsel" onchange="enLA()">
|
||||
<option value="55" selected>5V default (55mA)</option>
|
||||
<option value="35">5V efficient (35mA)</option>
|
||||
<option value="30">12V (30mA)</option>
|
||||
<option value="255">WS2815 (12mA)</option>
|
||||
<option value="50">Custom</option>
|
||||
</select><br>
|
||||
<span id="LAdis" style="display: none;">Custom max. current per LED: <input name="LA" type="number" min="0" max="255" id="la" oninput="UI()" required> mA<br></span>
|
||||
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
|
||||
</div>
|
||||
<h3>Hardware setup</h3>
|
||||
<div id="mLC">LED outputs:</div>
|
||||
<button type="button" id="+" onclick="addLEDs(1)" style="display:none;border-radius:20px;height:36px;">+</button>
|
||||
<button type="button" id="-" onclick="addLEDs(-1)" style="display:none;border-radius:20px;width:36px;height:36px;">-</button><br>
|
||||
LED Memory Usage: <span id="m0">0</span> / <span id="m1">?</span> B<br>
|
||||
<div id="dbar" style="display:inline-block; width: 100px; height: 10px; border-radius: 20px;"></div><br>
|
||||
<div id="ledwarning" style="color: orange; display: none;">
|
||||
⚠ You might run into stability or lag issues.<br>
|
||||
Use less than <span id="wreason">800 LEDs per pin</span> for the best experience!<br>
|
||||
</div><hr style="width:260px">
|
||||
<div id="btns"></div>
|
||||
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
||||
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()" style="width:35px"> <select name="IT">
|
||||
<option value="0">Remote disabled</option>
|
||||
<option value="1">24-key RGB</option>
|
||||
<option value="2">24-key with CT</option>
|
||||
<option value="3">40-key blue</option>
|
||||
<option value="4">44-key RGB</option>
|
||||
<option value="5">21-key RGB</option>
|
||||
<option value="6">6-key black</option>
|
||||
<option value="7">9-key red</option>
|
||||
</select><span style="cursor: pointer;" onclick="off('IR')"> ×</span><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br>
|
||||
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()" style="width:35px"> Invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
||||
<hr style="width:260px">
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br><br>
|
||||
Apply preset <input name="BP" type="number" min="0" max="250" required> at boot (0 uses defaults)
|
||||
<br>- <i>or</i> -<br>
|
||||
Set current preset cycle setting as boot default: <input type="checkbox" name="PC"><br><br>
|
||||
Use Gamma correction for color: <input type="checkbox" name="GC"> (strongly recommended)<br>
|
||||
Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br><br>
|
||||
Brightness factor: <input name="BF" type="number" min="1" max="255" required> %
|
||||
<h3>Transitions</h3>
|
||||
Crossfade: <input type="checkbox" name="TF"><br>
|
||||
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
|
||||
Enable Palette transitions: <input type="checkbox" name="PF">
|
||||
<h3>Timed light</h3>
|
||||
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
|
||||
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
|
||||
Mode:
|
||||
<select name="TW">
|
||||
<option value="0">Wait and set</option>
|
||||
<option value="1">Fade</option>
|
||||
<option value="2">Fade Color</option>
|
||||
<option value="3">Sunrise</option>
|
||||
</select>
|
||||
<h3>Advanced</h3>
|
||||
Palette blending:
|
||||
<select name="PB">
|
||||
<option value="0">Linear (wrap if moving)</option>
|
||||
<option value="1">Linear (always wrap)</option>
|
||||
<option value="2">Linear (never wrap)</option>
|
||||
<option value="3">None (not recommended)</option>
|
||||
</select><br>
|
||||
<span class="wc">
|
||||
Auto-calculate white channel from RGB:<br>
|
||||
<select name="AW">
|
||||
<option value=0>None</option>
|
||||
<option value=1>Brighter</option>
|
||||
<option value=2>Accurate</option>
|
||||
<option value=3>Dual</option>
|
||||
<option value=4>Legacy</option>
|
||||
</select>
|
||||
<br></span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -15,29 +15,10 @@ function GetV(){var d=document;}
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
Button type:
|
||||
<select name=BT>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=2>Pushbutton</option>
|
||||
<option value=4>Switch</option>
|
||||
</select><br>
|
||||
Infrared remote:
|
||||
<select name=IR>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>24-key RGB</option>
|
||||
<option value=2>24-key with CT</option>
|
||||
<option value=3>40-key blue</option>
|
||||
<option value=4>44-key RGB</option>
|
||||
<option value=5>21-key RGB</option>
|
||||
<option value=6>6-key black</option>
|
||||
<option value=7>9-key red</option>
|
||||
</select><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
||||
<h3>WLED Broadcast</h3>
|
||||
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
|
||||
2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Receive: <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Send notifications on direct change: <input type="checkbox" name="SD"><br>
|
||||
Send notifications on button press or IR: <input type="checkbox" name="SB"><br>
|
||||
Send Alexa notifications: <input type="checkbox" name="SA"><br>
|
||||
|
@ -6,41 +6,41 @@
|
||||
<title>Time Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
function H()
|
||||
function H()
|
||||
{
|
||||
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
}
|
||||
function S()
|
||||
{
|
||||
BTa();GetV();Cs();FC();
|
||||
}
|
||||
function gId(s)
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
function Cs()
|
||||
{
|
||||
gId("cac").style.display="none";
|
||||
gId("coc").style.display="block";
|
||||
gId("ccc").style.display="none";
|
||||
if (gId("ca").selected)
|
||||
{
|
||||
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");
|
||||
gId("cac").style.display="block";
|
||||
}
|
||||
function B()
|
||||
if (gId("cc").selected)
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
gId("coc").style.display="none";
|
||||
gId("ccc").style.display="block";
|
||||
}
|
||||
function S()
|
||||
if (gId("cn").selected)
|
||||
{
|
||||
BTa();GetV();Cs();FC();
|
||||
}
|
||||
function gId(s)
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
function Cs()
|
||||
{
|
||||
gId("cac").style.display="none";
|
||||
gId("coc").style.display="block";
|
||||
gId("ccc").style.display="none";
|
||||
if (gId("ca").selected)
|
||||
{
|
||||
gId("cac").style.display="block";
|
||||
}
|
||||
if (gId("cc").selected)
|
||||
{
|
||||
gId("coc").style.display="none";
|
||||
gId("ccc").style.display="block";
|
||||
}
|
||||
if (gId("cn").selected)
|
||||
{
|
||||
gId("coc").style.display="none";
|
||||
}
|
||||
gId("coc").style.display="none";
|
||||
}
|
||||
}
|
||||
function BTa()
|
||||
{
|
||||
var ih="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";
|
||||
@ -75,10 +75,25 @@
|
||||
gId("W"+i).value=a[i];
|
||||
}
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
}
|
||||
function addRow(i,p,l,d) {
|
||||
var t = gId("macros"); // table
|
||||
var rCnt = t.rows.length; // get the number of rows.
|
||||
var tr = t.insertRow(rCnt); // table row.
|
||||
|
||||
var td = document.createElement('td'); // TABLE DEFINITION.
|
||||
td = tr.insertCell(0);
|
||||
td.innerHTML = `Button ${i}:`;
|
||||
td = tr.insertCell(1);
|
||||
td.innerHTML = `<input name="MP${i}" type="number" min="0" max="250" value="${p}" required>`;
|
||||
td = tr.insertCell(2);
|
||||
td.innerHTML = `<input name="ML${i}" type="number" min="0" max="250" value="${l}" required>`;
|
||||
td = tr.insertCell(3);
|
||||
td.innerHTML = `<input name="MD${i}" type="number" min="0" max="250" value="${d}" required>`;
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import url("style.css");
|
||||
@ -107,12 +122,12 @@
|
||||
<option value="10">JST(KST)</option>
|
||||
<option value="11">AEST/AEDT</option>
|
||||
<option value="12">NZST/NZDT</option>
|
||||
<option value="13">North Korea</option>
|
||||
<option value="14">IST (India)</option>
|
||||
<option value="15">CA-Saskatchewan</option>
|
||||
<option value="16">ACST</option>
|
||||
<option value="17">ACST/ACDT</option>
|
||||
<option value="18">HST (Hawaii)</option>
|
||||
<option value="13">North Korea</option>
|
||||
<option value="14">IST (India)</option>
|
||||
<option value="15">CA-Saskatchewan</option>
|
||||
<option value="16">ACST</option>
|
||||
<option value="17">ACST/ACDT</option>
|
||||
<option value="18">HST (Hawaii)</option>
|
||||
</select><br>
|
||||
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
|
||||
Current local time is <span class="times">unknown</span>.<br>
|
||||
@ -143,15 +158,27 @@
|
||||
Year: 20 <input name="CY" type="number" min="0" max="99" required> Month: <input name="CI" type="number" min="1" max="12" required> Day: <input name="CD" type="number" min="1" max="31" required><br>
|
||||
Hour: <input name="CH" type="number" min="0" max="23" required> Minute: <input name="CM" type="number" min="0" max="59" required> Second: <input name="CS" type="number" min="0" max="59" required><br>
|
||||
<h3>Macro presets</h3>
|
||||
<b>Macros have moved!</b><br>
|
||||
<i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br>
|
||||
Just enter the preset id below!</i>
|
||||
<b>Macros have moved!</b><br>
|
||||
<i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br>
|
||||
Just enter the preset id below!</i>
|
||||
<i>Use 0 for the default action instead of a preset</i><br>
|
||||
Alexa On/Off Preset: <input name="A0" type="number" min="0" max="250" required> <input name="A1" type="number" min="0" max="250" required><br>
|
||||
Button short press Preset: <input name="MP" type="number" min="0" max="250" required><br>
|
||||
Long Press: <input name="ML" type="number" min="0" max="250" required> Double press: <input name="MD" type="number" min="0" max="250" required><br>
|
||||
Countdown-Over Preset: <input name="MC" type="number" min="0" max="250" required><br>
|
||||
Timed-Light-Over Presets: <input name="MN" type="number" min="0" max="250" required><br>
|
||||
<h3>Button actions</h3>
|
||||
<table style="margin: 0 auto;" id="macros">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>push<br>switch</td>
|
||||
<td>short<br>on->off</td>
|
||||
<td>long<br>off->on</td>
|
||||
<td>double<br>N/A</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Macros#analog-button" target="_blank">Analog Button setup</a>
|
||||
<h3>Time-controlled presets</h3>
|
||||
<div style="display: inline-block">
|
||||
<table id="TMT">
|
||||
|
@ -20,8 +20,8 @@ void handleBlynk();
|
||||
void updateBlynk();
|
||||
|
||||
//button.cpp
|
||||
void shortPressAction();
|
||||
bool isButtonPressed();
|
||||
void shortPressAction(uint8_t b=0);
|
||||
bool isButtonPressed(uint8_t b=0);
|
||||
void handleButton();
|
||||
void handleIO();
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -79,9 +79,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
|
||||
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
|
||||
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin);
|
||||
//TODO remove all busses, but not in this system call
|
||||
//busses->removeAll();
|
||||
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++)
|
||||
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s]))
|
||||
pinManager.deallocatePin(btnPin[s]);
|
||||
|
||||
strip.isRgbw = false;
|
||||
uint8_t colorOrder, type, skip;
|
||||
@ -97,7 +97,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
|
||||
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED
|
||||
if (!request->hasArg(lp)) {
|
||||
DEBUG_PRINTLN("No data."); break;
|
||||
DEBUG_PRINTLN(F("No data.")); break;
|
||||
}
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
lp[1] = 48+i;
|
||||
@ -107,7 +107,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
type = request->arg(lt).toInt();
|
||||
strip.isRgbw = strip.isRgbw || BusManager::isRgbw(type);
|
||||
skip = request->hasArg(sl) ? LED_SKIP_AMOUNT : 0;
|
||||
|
||||
|
||||
if (request->hasArg(lc) && request->arg(lc).toInt() > 0) {
|
||||
length = request->arg(lc).toInt();
|
||||
} else {
|
||||
@ -127,11 +127,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
// upate other pins
|
||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||
if (pinManager.isPinOk(hw_ir_pin) && pinManager.allocatePin(hw_ir_pin,false)) {
|
||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||
irPin = hw_ir_pin;
|
||||
} else {
|
||||
irPin = -1;
|
||||
}
|
||||
irEnabled = request->arg(F("IT")).toInt();
|
||||
|
||||
int hw_rly_pin = request->arg(F("RL")).toInt();
|
||||
if (pinManager.allocatePin(hw_rly_pin,true)) {
|
||||
@ -141,13 +142,20 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
}
|
||||
rlyMde = (bool)request->hasArg(F("RM"));
|
||||
|
||||
int hw_btn_pin = request->arg(F("BT")).toInt();
|
||||
if (pinManager.allocatePin(hw_btn_pin,false)) {
|
||||
btnPin = hw_btn_pin;
|
||||
pinMode(btnPin, INPUT_PULLUP);
|
||||
} else {
|
||||
btnPin = -1;
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
char bt[4] = "BT"; bt[2] = 48+i; bt[3] = 0; // button pin
|
||||
char be[4] = "BE"; be[2] = 48+i; be[3] = 0; // button type
|
||||
int hw_btn_pin = request->arg(bt).toInt();
|
||||
if (pinManager.allocatePin(hw_btn_pin,false)) {
|
||||
btnPin[i] = hw_btn_pin;
|
||||
pinMode(btnPin[i], INPUT_PULLUP);
|
||||
buttonType[i] = request->arg(be).toInt();
|
||||
} else {
|
||||
btnPin[i] = -1;
|
||||
buttonType[i] = BTN_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
touchThreshold = request->arg(F("TT")).toInt();
|
||||
|
||||
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
|
||||
strip.milliampsPerLed = request->arg(F("LA")).toInt();
|
||||
@ -191,8 +199,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
//SYNC
|
||||
if (subPage == 4)
|
||||
{
|
||||
buttonType = request->arg(F("BT")).toInt();
|
||||
irEnabled = request->arg(F("IR")).toInt();
|
||||
int t = request->arg(F("UP")).toInt();
|
||||
if (t > 0) udpPort = t;
|
||||
t = request->arg(F("U2")).toInt();
|
||||
@ -234,6 +240,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
alexaEnabled = request->hasArg(F("AL"));
|
||||
strlcpy(alexaInvocationName, request->arg(F("AI")).c_str(), 33);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
strlcpy(blynkHost, request->arg("BH").c_str(), 33);
|
||||
t = request->arg(F("BP")).toInt();
|
||||
if (t > 0) blynkPort = t;
|
||||
@ -241,6 +248,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (request->hasArg("BK") && !request->arg("BK").equals(F("Hidden"))) {
|
||||
strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey, blynkHost, blynkPort);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
mqttEnabled = request->hasArg(F("MQ"));
|
||||
@ -303,8 +311,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
analogClock5MinuteMarks = request->hasArg(F("O5"));
|
||||
analogClockSecondsTrail = request->hasArg(F("OS"));
|
||||
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
strcpy(cronixieDisplay,request->arg(F("CX")).c_str());
|
||||
cronixieBacklight = request->hasArg(F("CB"));
|
||||
#endif
|
||||
countdownMode = request->hasArg(F("CE"));
|
||||
countdownYear = request->arg(F("CY")).toInt();
|
||||
countdownMonth = request->arg(F("CI")).toInt();
|
||||
@ -316,11 +326,17 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
macroAlexaOn = request->arg(F("A0")).toInt();
|
||||
macroAlexaOff = request->arg(F("A1")).toInt();
|
||||
macroButton = request->arg(F("MP")).toInt();
|
||||
macroLongPress = request->arg(F("ML")).toInt();
|
||||
macroCountdown = request->arg(F("MC")).toInt();
|
||||
macroNl = request->arg(F("MN")).toInt();
|
||||
macroDoublePress = request->arg(F("MD")).toInt();
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
char mp[4] = "MP"; mp[2] = 48+i; mp[3] = 0; // short
|
||||
char ml[4] = "ML"; ml[2] = 48+i; ml[3] = 0; // long
|
||||
char md[4] = "MD"; md[2] = 48+i; md[3] = 0; // double
|
||||
//if (!request->hasArg(mp)) break;
|
||||
macroButton[i] = request->arg(mp).toInt(); // these will default to 0 if not present
|
||||
macroLongPress[i] = request->arg(ml).toInt();
|
||||
macroDoublePress[i] = request->arg(md).toInt();
|
||||
}
|
||||
|
||||
char k[3]; k[2] = 0;
|
||||
for (int i = 0; i<10; i++)
|
||||
|
113
wled00/wled.cpp
113
wled00/wled.cpp
@ -75,7 +75,6 @@ ethernet_settings ethernetBoards[] = {
|
||||
ETH_CLOCK_GPIO17_OUT // eth_clk_mode
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// turns all LEDs off and restarts ESP
|
||||
@ -90,7 +89,7 @@ void WLED::reset()
|
||||
yield(); // enough time to send response to client
|
||||
}
|
||||
setAllLeds();
|
||||
DEBUG_PRINTLN("MODULE RESET");
|
||||
DEBUG_PRINTLN(F("MODULE RESET"));
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
@ -148,10 +147,10 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
switch (event) {
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
DEBUG_PRINT("ETH Started");
|
||||
DEBUG_PRINT(F("ETH Started"));
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
DEBUG_PRINT("ETH Connected");
|
||||
DEBUG_PRINT(F("ETH Connected"));
|
||||
if (!apActive) {
|
||||
WiFi.disconnect(true);
|
||||
}
|
||||
@ -166,7 +165,7 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
showWelcomePage = false;
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
DEBUG_PRINT("ETH Disconnected");
|
||||
DEBUG_PRINT(F("ETH Disconnected"));
|
||||
forceReconnect = true;
|
||||
break;
|
||||
#endif
|
||||
@ -178,7 +177,6 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
void WLED::loop()
|
||||
{
|
||||
handleTime();
|
||||
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
@ -232,10 +230,17 @@ void WLED::loop()
|
||||
#ifdef ESP8266
|
||||
MDNS.update();
|
||||
#endif
|
||||
|
||||
//millis() rolls over every 50 days
|
||||
if (lastMqttReconnectAttempt > millis()) {
|
||||
rolloverMillis++;
|
||||
lastMqttReconnectAttempt = 0;
|
||||
}
|
||||
if (millis() - lastMqttReconnectAttempt > 30000) {
|
||||
if (lastMqttReconnectAttempt > millis()) rolloverMillis++; //millis() rolls over every 50 days
|
||||
lastMqttReconnectAttempt = millis();
|
||||
initMqtt();
|
||||
yield();
|
||||
// refresh WLED nodes list
|
||||
refreshNodeList();
|
||||
if (nodeBroadcastEnabled) sendSysInfoUDP();
|
||||
yield();
|
||||
@ -245,6 +250,7 @@ void WLED::loop()
|
||||
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
|
||||
if (doInitBusses) {
|
||||
doInitBusses = false;
|
||||
DEBUG_PRINTLN(F("Re-init busses."));
|
||||
busses.removeAll();
|
||||
uint32_t mem = 0;
|
||||
strip.isRgbw = false;
|
||||
@ -268,20 +274,27 @@ void WLED::loop()
|
||||
// DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999) {
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); toki.printTime(toki.getTime());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(WiFi.status());
|
||||
DEBUG_PRINTLN(F("---DEBUG INFO---"));
|
||||
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
|
||||
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||
} else
|
||||
DEBUG_PRINTLN(F("No PSRAM"));
|
||||
#endif
|
||||
DEBUG_PRINT(F("Wifi state: ")); DEBUG_PRINTLN(WiFi.status());
|
||||
|
||||
if (WiFi.status() != lastWifiState) {
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(Network.localIP());
|
||||
DEBUG_PRINT("Loops/sec: "); DEBUG_PRINTLN(loops / 10);
|
||||
DEBUG_PRINT(F("State time: ")); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT(F("NTP last sync: ")); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT(F("Client IP: ")); DEBUG_PRINTLN(Network.localIP());
|
||||
DEBUG_PRINT(F("Loops/sec: ")); DEBUG_PRINTLN(loops / 10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
@ -299,25 +312,35 @@ void WLED::setup()
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT("---WLED ");
|
||||
DEBUG_PRINT(F("---WLED "));
|
||||
DEBUG_PRINT(versionString);
|
||||
DEBUG_PRINT(" ");
|
||||
DEBUG_PRINT(VERSION);
|
||||
DEBUG_PRINTLN(" INIT---");
|
||||
DEBUG_PRINTLN(F(" INIT---"));
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
DEBUG_PRINT("esp32 ");
|
||||
DEBUG_PRINT(F("esp32 "));
|
||||
DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||
#else
|
||||
DEBUG_PRINT("esp8266 ");
|
||||
DEBUG_PRINT(F("esp8266 "));
|
||||
DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
#endif
|
||||
DEBUG_PRINT("heap ");
|
||||
DEBUG_PRINT(F("heap "));
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
registerUsermods();
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
pinManager.allocatePin(16); // GPIO16 reserved for SPI RAM
|
||||
pinManager.allocatePin(17); // GPIO17 reserved for SPI RAM
|
||||
}
|
||||
#endif
|
||||
|
||||
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
|
||||
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
pinManager.allocatePin(1,true); // GPIO1 reserved for debug output
|
||||
#endif
|
||||
#ifdef WLED_USE_DMX //reserve GPIO2 as hardcoded DMX pin
|
||||
pinManager.allocatePin(2);
|
||||
#endif
|
||||
@ -334,21 +357,18 @@ void WLED::setup()
|
||||
errorFlag = ERR_FS_BEGIN;
|
||||
} else deEEP();
|
||||
updateFSInfo();
|
||||
|
||||
DEBUG_PRINTLN(F("Reading config"));
|
||||
deserializeConfigFromFS();
|
||||
|
||||
#if STATUSLED
|
||||
bool lStatusLed = false;
|
||||
for (uint8_t i=0; i<strip.numStrips; i++) {
|
||||
if (strip.getStripPin(i)==STATUSLED) {
|
||||
lStatusLed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lStatusLed)
|
||||
pinMode(STATUSLED, OUTPUT);
|
||||
if (!pinManager.isPinAllocated(STATUSLED)) pinMode(STATUSLED, OUTPUT);
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN(F("Initializing strip"));
|
||||
beginStrip();
|
||||
|
||||
DEBUG_PRINTLN(F("Usermods setup"));
|
||||
userSetup();
|
||||
usermods.setup();
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
@ -358,7 +378,11 @@ void WLED::setup()
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
#endif
|
||||
|
||||
Serial.println(F("Ada"));
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
if (!pinManager.isPinAllocated(3)) {
|
||||
Serial.println(F("Ada"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// generate module IDs
|
||||
escapedMac = WiFi.macAddress();
|
||||
@ -397,6 +421,10 @@ void WLED::setup()
|
||||
#endif
|
||||
// HTTP server page init
|
||||
initServer();
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
|
||||
#endif
|
||||
}
|
||||
|
||||
void WLED::beginStrip()
|
||||
@ -410,8 +438,9 @@ void WLED::beginStrip()
|
||||
strip.setBrightness(0);
|
||||
strip.setShowCallback(handleOverlayDraw);
|
||||
|
||||
if (bootPreset > 0) applyPreset(bootPreset);
|
||||
if (turnOnAtBoot) {
|
||||
if (bootPreset > 0) {
|
||||
applyPreset(bootPreset);
|
||||
} else if (turnOnAtBoot) {
|
||||
if (briS > 0) bri = briS;
|
||||
else if (bri == 0) bri = 128;
|
||||
} else {
|
||||
@ -424,8 +453,8 @@ void WLED::beginStrip()
|
||||
digitalWrite(rlyPin, (rlyMde ? bri : !bri));
|
||||
|
||||
// disable button if it is "pressed" unintentionally
|
||||
if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed())
|
||||
buttonType = BTN_TYPE_NONE;
|
||||
//if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed())
|
||||
// buttonType = BTN_TYPE_NONE;
|
||||
}
|
||||
|
||||
void WLED::initAP(bool resetAP)
|
||||
@ -539,11 +568,13 @@ void WLED::initInterfaces()
|
||||
{
|
||||
DEBUG_PRINTLN(F("Init STA interfaces"));
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
if (hueIP[0] == 0) {
|
||||
hueIP[0] = Network.localIP()[0];
|
||||
hueIP[1] = Network.localIP()[1];
|
||||
hueIP[2] = Network.localIP()[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
// init Alexa hue emulation
|
||||
if (alexaEnabled)
|
||||
@ -581,7 +612,9 @@ void WLED::initInterfaces()
|
||||
if (ntpEnabled)
|
||||
ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
initBlynk(blynkApiKey, blynkHost, blynkPort);
|
||||
#endif
|
||||
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||
reconnectHue();
|
||||
initMqtt();
|
||||
@ -603,7 +636,7 @@ void WLED::handleConnection()
|
||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||
if (millis() - heapTime > 5000) {
|
||||
uint32_t heap = ESP.getFreeHeap();
|
||||
if (heap < 9000 && lastHeap < 9000) {
|
||||
if (heap < JSON_BUFFER_SIZE+512 && lastHeap < JSON_BUFFER_SIZE+512) {
|
||||
DEBUG_PRINT(F("Heap too low! "));
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
@ -672,11 +705,7 @@ void WLED::handleConnection()
|
||||
void WLED::handleStatusLED()
|
||||
{
|
||||
#if STATUSLED
|
||||
for (uint8_t s=0; s<strip.numStrips; s++) {
|
||||
if (strip.getStripPin(s)==STATUSLED) {
|
||||
return; // pin used for strip
|
||||
}
|
||||
}
|
||||
if (pinManager.isPinAllocated(STATUSLED)) return; //lower priority if something else uses the same pin
|
||||
|
||||
ledStatusType = WLED_CONNECTED ? 0 : 2;
|
||||
if (mqttEnabled && ledStatusType != 2) // Wi-Fi takes presendence over MQTT
|
||||
@ -696,4 +725,4 @@ void WLED::handleStatusLED()
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -114,6 +114,26 @@
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
|
||||
// ESP32-WROVER features SPI RAM (aka PSRAM) which can be allocated using ps_malloc()
|
||||
// we can create custom PSRAMDynamicJsonDocument to use such feature (replacing DynamicJsonDocument)
|
||||
// The following is a construct to enable code to compile without it.
|
||||
// There is a code thet will still not use PSRAM though:
|
||||
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
struct PSRAM_Allocator {
|
||||
void* allocate(size_t size) {
|
||||
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
||||
else return malloc(size); // fallback
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
free(pointer);
|
||||
}
|
||||
};
|
||||
using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
|
||||
#else
|
||||
#define PSRAMDynamicJsonDocument DynamicJsonDocument
|
||||
#endif
|
||||
|
||||
#include "fcn_declare.h"
|
||||
#include "html_ui.h"
|
||||
#include "html_settings.h"
|
||||
@ -189,9 +209,9 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
|
||||
// Hardware CONFIG (only changeble HERE, not at runtime)
|
||||
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
|
||||
#ifndef BTNPIN
|
||||
WLED_GLOBAL int8_t btnPin _INIT(0);
|
||||
WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({0});
|
||||
#else
|
||||
WLED_GLOBAL int8_t btnPin _INIT(BTNPIN);
|
||||
WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({BTNPIN});
|
||||
#endif
|
||||
#ifndef RLYPIN
|
||||
WLED_GLOBAL int8_t rlyPin _INIT(12);
|
||||
@ -264,7 +284,7 @@ WLED_GLOBAL NodesMap Nodes;
|
||||
WLED_GLOBAL bool nodeListEnabled _INIT(true);
|
||||
WLED_GLOBAL bool nodeBroadcastEnabled _INIT(true);
|
||||
|
||||
WLED_GLOBAL byte buttonType _INIT(BTN_TYPE_PUSH);
|
||||
WLED_GLOBAL byte buttonType[WLED_MAX_BUTTONS] _INIT({BTN_TYPE_PUSH});
|
||||
WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver
|
||||
|
||||
WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port
|
||||
@ -284,9 +304,11 @@ WLED_GLOBAL bool notifyTwice _INIT(false); // notificatio
|
||||
WLED_GLOBAL bool alexaEnabled _INIT(false); // enable device discovery by Amazon Echo
|
||||
WLED_GLOBAL char alexaInvocationName[33] _INIT("Light"); // speech control name of device. Choose something voice-to-text can understand
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
WLED_GLOBAL char blynkApiKey[36] _INIT(""); // Auth token for Blynk server. If empty, no connection will be made
|
||||
WLED_GLOBAL char blynkHost[33] _INIT("blynk-cloud.com"); // Default Blynk host
|
||||
WLED_GLOBAL uint16_t blynkPort _INIT(80); // Default Blynk port
|
||||
#endif
|
||||
|
||||
WLED_GLOBAL uint16_t realtimeTimeoutMs _INIT(2500); // ms timeout of realtime mode before returning to normal mode
|
||||
WLED_GLOBAL int arlsOffset _INIT(0); // realtime LED offset
|
||||
@ -316,6 +338,7 @@ WLED_GLOBAL char mqttPass[41] _INIT(""); // optional: password
|
||||
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
|
||||
WLED_GLOBAL uint16_t mqttPort _INIT(1883);
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
WLED_GLOBAL bool huePollingEnabled _INIT(false); // poll hue bridge for light state
|
||||
WLED_GLOBAL uint16_t huePollIntervalMs _INIT(2500); // low values (< 1sec) may cause lag but offer quicker response
|
||||
WLED_GLOBAL char hueApiKey[47] _INIT("api"); // key token will be obtained from bridge
|
||||
@ -324,6 +347,7 @@ WLED_GLOBAL IPAddress hueIP _INIT_N(((0, 0, 0, 0))); // IP address of the bridge
|
||||
WLED_GLOBAL bool hueApplyOnOff _INIT(true);
|
||||
WLED_GLOBAL bool hueApplyBri _INIT(true);
|
||||
WLED_GLOBAL bool hueApplyColor _INIT(true);
|
||||
#endif
|
||||
|
||||
// Time CONFIG
|
||||
WLED_GLOBAL bool ntpEnabled _INIT(false); // get internet time. Only required if you use clock overlays or time-activated macros
|
||||
@ -338,8 +362,10 @@ WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your
|
||||
WLED_GLOBAL bool analogClockSecondsTrail _INIT(false); // Display seconds as trail of LEDs instead of a single pixel
|
||||
WLED_GLOBAL bool analogClock5MinuteMarks _INIT(false); // Light pixels at every 5-minute position
|
||||
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
WLED_GLOBAL char cronixieDisplay[7] _INIT("HHMMSS"); // Cronixie Display mask. See wled13_cronixie.ino
|
||||
WLED_GLOBAL bool cronixieBacklight _INIT(true); // Allow digits to be back-illuminated
|
||||
#endif
|
||||
|
||||
WLED_GLOBAL bool countdownMode _INIT(false); // Clock will count down towards date
|
||||
WLED_GLOBAL byte countdownYear _INIT(20), countdownMonth _INIT(1); // Countdown target date, year is last two digits
|
||||
@ -349,7 +375,9 @@ WLED_GLOBAL byte countdownMin _INIT(0) , countdownSec _INIT(0);
|
||||
WLED_GLOBAL byte macroNl _INIT(0); // after nightlight delay over
|
||||
WLED_GLOBAL byte macroCountdown _INIT(0);
|
||||
WLED_GLOBAL byte macroAlexaOn _INIT(0), macroAlexaOff _INIT(0);
|
||||
WLED_GLOBAL byte macroButton _INIT(0), macroLongPress _INIT(0), macroDoublePress _INIT(0);
|
||||
WLED_GLOBAL byte macroButton[WLED_MAX_BUTTONS] _INIT({0});
|
||||
WLED_GLOBAL byte macroLongPress[WLED_MAX_BUTTONS] _INIT({0});
|
||||
WLED_GLOBAL byte macroDoublePress[WLED_MAX_BUTTONS] _INIT({0});
|
||||
|
||||
// Security CONFIG
|
||||
WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
|
||||
@ -410,10 +438,11 @@ WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. U
|
||||
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
|
||||
|
||||
// button
|
||||
WLED_GLOBAL bool buttonPressedBefore _INIT(false);
|
||||
WLED_GLOBAL bool buttonLongPressed _INIT(false);
|
||||
WLED_GLOBAL unsigned long buttonPressedTime _INIT(0);
|
||||
WLED_GLOBAL unsigned long buttonWaitTime _INIT(0);
|
||||
WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
|
||||
WLED_GLOBAL bool buttonLongPressed[WLED_MAX_BUTTONS] _INIT({false});
|
||||
WLED_GLOBAL unsigned long buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
|
||||
WLED_GLOBAL unsigned long buttonWaitTime[WLED_MAX_BUTTONS] _INIT({0});
|
||||
WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESHOLD);
|
||||
|
||||
// notifications
|
||||
WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect);
|
||||
|
@ -93,7 +93,7 @@ void loadSettingsFromEEPROM()
|
||||
|
||||
notifyButton = EEPROM.read(230);
|
||||
notifyTwice = EEPROM.read(231);
|
||||
buttonType = EEPROM.read(232) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
|
||||
buttonType[0] = EEPROM.read(232) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
|
||||
|
||||
staticIP[0] = EEPROM.read(234);
|
||||
staticIP[1] = EEPROM.read(235);
|
||||
@ -157,6 +157,7 @@ void loadSettingsFromEEPROM()
|
||||
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
|
||||
if (lastEEPROMversion > 4) {
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
huePollingEnabled = EEPROM.read(2048);
|
||||
//hueUpdatingEnabled = EEPROM.read(2049);
|
||||
for (int i = 2050; i < 2054; ++i)
|
||||
@ -172,6 +173,7 @@ void loadSettingsFromEEPROM()
|
||||
hueApplyBri = EEPROM.read(2104);
|
||||
hueApplyColor = EEPROM.read(2105);
|
||||
huePollLightId = EEPROM.read(2106);
|
||||
#endif
|
||||
}
|
||||
if (lastEEPROMversion > 5) {
|
||||
overlayMin = EEPROM.read(2150);
|
||||
@ -188,18 +190,20 @@ void loadSettingsFromEEPROM()
|
||||
countdownSec = EEPROM.read(2161);
|
||||
setCountdown();
|
||||
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
readStringFromEEPROM(2165, cronixieDisplay, 6);
|
||||
cronixieBacklight = EEPROM.read(2171);
|
||||
#endif
|
||||
|
||||
//macroBoot = EEPROM.read(2175);
|
||||
macroAlexaOn = EEPROM.read(2176);
|
||||
macroAlexaOff = EEPROM.read(2177);
|
||||
macroButton = EEPROM.read(2178);
|
||||
macroLongPress = EEPROM.read(2179);
|
||||
macroButton[0] = EEPROM.read(2178);
|
||||
macroLongPress[0] = EEPROM.read(2179);
|
||||
macroCountdown = EEPROM.read(2180);
|
||||
macroNl = EEPROM.read(2181);
|
||||
macroDoublePress = EEPROM.read(2182);
|
||||
if (macroDoublePress > 16) macroDoublePress = 0;
|
||||
macroDoublePress[0] = EEPROM.read(2182);
|
||||
if (macroDoublePress[0] > 16) macroDoublePress[0] = 0;
|
||||
}
|
||||
|
||||
if (lastEEPROMversion > 6)
|
||||
@ -237,7 +241,7 @@ void loadSettingsFromEEPROM()
|
||||
|
||||
if (lastEEPROMversion > 9)
|
||||
{
|
||||
strip.setColorOrder(EEPROM.read(383));
|
||||
//strip.setColorOrder(EEPROM.read(383));
|
||||
irEnabled = EEPROM.read(385);
|
||||
strip.ablMilliampsMax = EEPROM.read(387) + ((EEPROM.read(388) << 8) & 0xFF00);
|
||||
} else if (lastEEPROMversion > 1) //ABL is off by default when updating from version older than 0.8.2
|
||||
@ -343,8 +347,10 @@ void loadSettingsFromEEPROM()
|
||||
//custom macro memory (16 slots/ each 64byte)
|
||||
//1024-2047 reserved
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
readStringFromEEPROM(2220, blynkApiKey, 35);
|
||||
if (strlen(blynkApiKey) < 25) blynkApiKey[0] = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
// DMX (2530 - 2549)2535
|
||||
@ -417,10 +423,10 @@ void deEEP() {
|
||||
for (byte j = 0; j < numChannels; j++) colX.add(EEPROM.read(memloc + j));
|
||||
}
|
||||
|
||||
segObj[F("fx")] = EEPROM.read(i+10);
|
||||
segObj["fx"] = EEPROM.read(i+10);
|
||||
segObj[F("sx")] = EEPROM.read(i+11);
|
||||
segObj[F("ix")] = EEPROM.read(i+16);
|
||||
segObj[F("pal")] = EEPROM.read(i+17);
|
||||
segObj["pal"] = EEPROM.read(i+17);
|
||||
} else {
|
||||
WS2812FX::Segment* seg = strip.getSegments();
|
||||
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
||||
|
@ -256,27 +256,53 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
if (subPage == 2) {
|
||||
char nS[8];
|
||||
|
||||
// add usermod pins as d.um_p array (TODO: usermod config shouldn't use state. instead we should load "um" object from cfg.json)
|
||||
/*DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||
JsonObject mods = doc.createNestedObject(F("mods"));
|
||||
usermods.addToJsonState(mods);
|
||||
// add reserved and usermod pins as d.um_p array
|
||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE/2);
|
||||
JsonObject mods = doc.createNestedObject(F("um"));
|
||||
usermods.addToConfig(mods);
|
||||
oappend(SET_F("d.um_p=["));
|
||||
if (!mods.isNull()) {
|
||||
uint8_t i=0;
|
||||
oappend(SET_F("d.um_p=["));
|
||||
for (JsonPair kv : mods) {
|
||||
if (strncmp_P(kv.key().c_str(),PSTR("pin_"),4) == 0) {
|
||||
if (i++) oappend(SET_F(","));
|
||||
oappend(itoa((int)kv.value(),nS,10));
|
||||
if (!kv.value().isNull()) {
|
||||
// element is an JsonObject
|
||||
JsonObject obj = kv.value();
|
||||
if (obj["pin"] != nullptr) {
|
||||
if (obj["pin"].is<JsonArray>()) {
|
||||
JsonArray pins = obj["pin"].as<JsonArray>();
|
||||
for (JsonVariant pv : pins) {
|
||||
if (i++) oappend(SET_F(","));
|
||||
oappendi(pv.as<int>());
|
||||
}
|
||||
} else {
|
||||
if (i++) oappend(SET_F(","));
|
||||
oappendi(obj["pin"].as<int>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
oappend(SET_F("];"));
|
||||
}*/
|
||||
if (i) oappend(SET_F(","));
|
||||
oappend(SET_F("6,7,8,9,10,11")); // flash memory pins
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
oappend(SET_F(",2")); // DMX hardcoded pin
|
||||
#endif
|
||||
//Adalight / Serial in requires pin 3 to be unused. However, Serial input can not be prevented by WLED
|
||||
#ifdef WLED_DEBUG
|
||||
oappend(SET_F(",1")); // debug output (TX) pin
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM
|
||||
#endif
|
||||
//TODO: add reservations for Ethernet shield pins
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#endif
|
||||
}
|
||||
oappend(SET_F("];"));
|
||||
|
||||
// set limits
|
||||
oappend(SET_F("bLimits("));
|
||||
oappend(itoa(WLED_MAX_BUSSES,nS,10));
|
||||
oappend(",");
|
||||
oappend(itoa(MAX_LEDS_PER_BUS,nS,10));
|
||||
oappend(",");
|
||||
oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LED_MEMORY,nS,10));
|
||||
oappend(SET_F(");"));
|
||||
|
||||
@ -286,7 +312,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
sappend('v',SET_F("LC"),ledCount);
|
||||
|
||||
for (uint8_t s=0; s < busses.getNumBusses(); s++){
|
||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
||||
Bus* bus = busses.getBus(s);
|
||||
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
|
||||
@ -320,7 +346,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
}
|
||||
|
||||
sappend('v',SET_F("CA"),briS);
|
||||
|
||||
sappend('v',SET_F("AW"),strip.rgbwMode);
|
||||
|
||||
sappend('c',SET_F("BO"),turnOnAtBoot);
|
||||
@ -338,8 +363,16 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('i',SET_F("PB"),strip.paletteBlend);
|
||||
sappend('v',SET_F("RL"),rlyPin);
|
||||
sappend('c',SET_F("RM"),rlyMde);
|
||||
sappend('v',SET_F("BT"),btnPin);
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
oappend(SET_F("addBtn("));
|
||||
oappend(itoa(i,nS,10)); oappend(",");
|
||||
oappend(itoa(btnPin[i],nS,10)); oappend(",");
|
||||
oappend(itoa(buttonType[i],nS,10));
|
||||
oappend(SET_F(");"));
|
||||
}
|
||||
sappend('v',SET_F("TT"),touchThreshold);
|
||||
sappend('v',SET_F("IR"),irPin);
|
||||
sappend('v',SET_F("IT"),irEnabled);
|
||||
}
|
||||
|
||||
if (subPage == 3)
|
||||
@ -350,8 +383,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
if (subPage == 4)
|
||||
{
|
||||
sappend('v',SET_F("BT"),buttonType);
|
||||
sappend('v',SET_F("IR"),irEnabled);
|
||||
sappend('v',SET_F("UP"),udpPort);
|
||||
sappend('v',SET_F("U2"),udpPort2);
|
||||
sappend('c',SET_F("RB"),receiveNotificationBrightness);
|
||||
@ -381,8 +412,10 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappends('s',SET_F("AI"),alexaInvocationName);
|
||||
sappend('c',SET_F("SA"),notifyAlexa);
|
||||
sappends('s',SET_F("BK"),(char*)((blynkEnabled)?SET_F("Hidden"):""));
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
sappends('s',SET_F("BH"),blynkHost);
|
||||
sappend('v',SET_F("BP"),blynkPort);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
sappend('c',SET_F("MQ"),mqttEnabled);
|
||||
@ -451,8 +484,10 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("OM"),analogClock12pixel);
|
||||
sappend('c',SET_F("OS"),analogClockSecondsTrail);
|
||||
sappend('c',SET_F("O5"),analogClock5MinuteMarks);
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
sappends('s',SET_F("CX"),cronixieDisplay);
|
||||
sappend('c',SET_F("CB"),cronixieBacklight);
|
||||
#endif
|
||||
sappend('c',SET_F("CE"),countdownMode);
|
||||
sappend('v',SET_F("CY"),countdownYear);
|
||||
sappend('v',SET_F("CI"),countdownMonth);
|
||||
@ -463,11 +498,16 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
sappend('v',SET_F("A0"),macroAlexaOn);
|
||||
sappend('v',SET_F("A1"),macroAlexaOff);
|
||||
sappend('v',SET_F("MP"),macroButton);
|
||||
sappend('v',SET_F("ML"),macroLongPress);
|
||||
sappend('v',SET_F("MC"),macroCountdown);
|
||||
sappend('v',SET_F("MN"),macroNl);
|
||||
sappend('v',SET_F("MD"),macroDoublePress);
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
oappend(SET_F("addRow("));
|
||||
oappend(itoa(i,tm,10)); oappend(",");
|
||||
oappend(itoa(macroButton[i],tm,10)); oappend(",");
|
||||
oappend(itoa(macroLongPress[i],tm,10)); oappend(",");
|
||||
oappend(itoa(macroDoublePress[i],tm,10));
|
||||
oappend(SET_F(");"));
|
||||
}
|
||||
|
||||
char k[4];
|
||||
k[2] = 0; //Time macros
|
||||
|
Loading…
Reference in New Issue
Block a user