Merge branch 'master' into dev
Minor tweaks.
This commit is contained in:
commit
3066a142b8
19
CHANGELOG.md
19
CHANGELOG.md
@ -2,6 +2,25 @@
|
|||||||
|
|
||||||
### Builds after release 0.12.0
|
### Builds after release 0.12.0
|
||||||
|
|
||||||
|
#### Build 2107021
|
||||||
|
|
||||||
|
- Added WebSockets support to UI
|
||||||
|
|
||||||
|
#### Build 2107020
|
||||||
|
|
||||||
|
- Send websockets on every state change
|
||||||
|
- Improved Aurora effect
|
||||||
|
|
||||||
|
#### Build 2107011
|
||||||
|
|
||||||
|
- Added MQTT button feedback option (PR #2011)
|
||||||
|
|
||||||
|
#### Build 2107010
|
||||||
|
|
||||||
|
- Added JSON IR codes (PR #1941)
|
||||||
|
- Adjusted the width of WiFi and LED settings input fields
|
||||||
|
- Fixed a minor visual issue with slider trail not reaching thumb on low values
|
||||||
|
|
||||||
#### Build 2106302
|
#### Build 2106302
|
||||||
|
|
||||||
- Fixed settings page broken by using "%" in input fields
|
- Fixed settings page broken by using "%" in input fields
|
||||||
|
@ -185,18 +185,18 @@ upload_speed = 115200
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
lib_compat_mode = strict
|
lib_compat_mode = strict
|
||||||
lib_deps =
|
lib_deps =
|
||||||
fastled/FastLED @ 3.3.2
|
fastled/FastLED @ 3.4.0
|
||||||
NeoPixelBus @ ^2.6.0
|
NeoPixelBus @ 2.6.4
|
||||||
ESPAsyncTCP @ 1.2.0
|
ESPAsyncTCP @ 1.2.0
|
||||||
ESPAsyncUDP
|
ESPAsyncUDP
|
||||||
AsyncTCP @ 1.0.3
|
AsyncTCP @ 1.0.3
|
||||||
IRremoteESP8266 @ 2.7.3
|
IRremoteESP8266 @ 2.7.18
|
||||||
https://github.com/lorol/LITTLEFS.git
|
https://github.com/lorol/LITTLEFS.git
|
||||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.2
|
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.2
|
||||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||||
#TFT_eSPI
|
#TFT_eSPI
|
||||||
#For use SSD1306 OLED display uncomment following
|
#For use SSD1306 OLED display uncomment following
|
||||||
U8g2@~2.27.2
|
U8g2@~2.28.8
|
||||||
#For Dallas sensor uncomment following 2 lines
|
#For Dallas sensor uncomment following 2 lines
|
||||||
OneWire@~2.3.5
|
OneWire@~2.3.5
|
||||||
; milesburton/DallasTemperature@^3.9.0
|
; milesburton/DallasTemperature@^3.9.0
|
||||||
|
@ -193,16 +193,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
if (enabled) {
|
||||||
if (!pinManager.allocatePin(PIRsensorPin,false)) {
|
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||||
PIRsensorPin = -1; // allocation failed
|
if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin,false)) {
|
||||||
enabled = false;
|
// PIR Sensor mode INPUT_PULLUP
|
||||||
DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed."));
|
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||||
} else {
|
|
||||||
// PIR Sensor mode INPUT_PULLUP
|
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
|
||||||
if (enabled) {
|
|
||||||
sensorPinState = digitalRead(PIRsensorPin);
|
sensorPinState = digitalRead(PIRsensorPin);
|
||||||
|
} else {
|
||||||
|
if (PIRsensorPin >= 0) DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed."));
|
||||||
|
PIRsensorPin = -1; // allocation failed
|
||||||
|
enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initDone = true;
|
initDone = true;
|
||||||
@ -221,8 +221,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
// only check sensors 10x/s
|
// only check sensors 4x/s
|
||||||
if (millis() - lastLoop < 100 || strip.isUpdating()) return;
|
if (!enabled || millis() - lastLoop < 250 || strip.isUpdating()) return;
|
||||||
lastLoop = millis();
|
lastLoop = millis();
|
||||||
|
|
||||||
if (!updatePIRsensorState()) {
|
if (!updatePIRsensorState()) {
|
||||||
|
@ -107,19 +107,20 @@ class UsermodTemperature : public Usermod {
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
int retries = 10;
|
int retries = 10;
|
||||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
if (enabled) {
|
||||||
if (!pinManager.allocatePin(temperaturePin,false)) {
|
// config says we are enabled
|
||||||
temperaturePin = -1; // allocation failed
|
DEBUG_PRINTLN(F("Allocating temperature pin..."));
|
||||||
enabled = false;
|
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||||
DEBUG_PRINTLN(F("Temperature pin allocation failed."));
|
if (temperaturePin >= 0 && pinManager.allocatePin(temperaturePin)) {
|
||||||
} else {
|
|
||||||
if (enabled) {
|
|
||||||
// config says we are enabled
|
|
||||||
oneWire = new OneWire(temperaturePin);
|
oneWire = new OneWire(temperaturePin);
|
||||||
if (!oneWire->reset())
|
if (!oneWire->reset())
|
||||||
enabled = false; // resetting 1-Wire bus yielded an error
|
enabled = false; // resetting 1-Wire bus yielded an error
|
||||||
else
|
else
|
||||||
while ((enabled=findSensor()) && retries--) delay(25); // try to find sensor
|
while ((enabled=findSensor()) && retries--) delay(25); // try to find sensor
|
||||||
|
} else {
|
||||||
|
if (temperaturePin >= 0) DEBUG_PRINTLN(F("Temperature pin allocation failed."));
|
||||||
|
temperaturePin = -1; // allocation failed
|
||||||
|
enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initDone = true;
|
initDone = true;
|
||||||
|
@ -133,6 +133,7 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
if (type == NONE) return;
|
if (type == NONE) return;
|
||||||
if (!pinManager.allocatePin(sclPin)) { sclPin = -1; type = NONE; return;}
|
if (!pinManager.allocatePin(sclPin)) { sclPin = -1; type = NONE; return;}
|
||||||
if (!pinManager.allocatePin(sdaPin)) { pinManager.deallocatePin(sclPin); sclPin = sdaPin = -1; type = NONE; return; }
|
if (!pinManager.allocatePin(sdaPin)) { pinManager.deallocatePin(sclPin); sclPin = sdaPin = -1; type = NONE; return; }
|
||||||
|
DEBUG_PRINTLN(F("Allocating display."));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSD1306:
|
case SSD1306:
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@ -184,12 +185,19 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
type = NONE;
|
type = NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(static_cast<U8X8*>(u8x8))->begin();
|
initDone = true;
|
||||||
|
if (u8x8 != nullptr) {
|
||||||
|
DEBUG_PRINTLN(F("Starting display."));
|
||||||
|
(static_cast<U8X8*>(u8x8))->begin();
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTLN(F("Display init failed."));
|
||||||
|
type = NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
setFlipMode(flip);
|
setFlipMode(flip);
|
||||||
setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||||
setPowerSave(0);
|
setPowerSave(0);
|
||||||
drawString(0, 0, "Loading...");
|
drawString(0, 0, "Loading...");
|
||||||
initDone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||||
@ -648,6 +656,7 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
type = newType;
|
type = newType;
|
||||||
DEBUG_PRINTLN(F(" config loaded."));
|
DEBUG_PRINTLN(F(" config loaded."));
|
||||||
} else {
|
} else {
|
||||||
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
// changing parameters from settings page
|
// changing parameters from settings page
|
||||||
if (sclPin!=newScl || sdaPin!=newSda || type!=newType) {
|
if (sclPin!=newScl || sdaPin!=newSda || type!=newType) {
|
||||||
if (type != NONE) delete (static_cast<U8X8*>(u8x8));
|
if (type != NONE) delete (static_cast<U8X8*>(u8x8));
|
||||||
@ -665,7 +674,6 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
setContrast(contrast);
|
setContrast(contrast);
|
||||||
setFlipMode(flip);
|
setFlipMode(flip);
|
||||||
if (needsRedraw && !wakeDisplay()) redraw(true);
|
if (needsRedraw && !wakeDisplay()) redraw(true);
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
|
||||||
}
|
}
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
return true;
|
return true;
|
||||||
|
@ -3926,7 +3926,6 @@ uint16_t WS2812FX::mode_tv_simulator(void) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//CONFIG
|
//CONFIG
|
||||||
#define BACKLIGHT 5
|
|
||||||
#define W_MAX_COUNT 20 //Number of simultaneous waves
|
#define W_MAX_COUNT 20 //Number of simultaneous waves
|
||||||
#define W_MAX_SPEED 6 //Higher number, higher speed
|
#define W_MAX_SPEED 6 //Higher number, higher speed
|
||||||
#define W_WIDTH_FACTOR 6 //Higher number, smaller waves
|
#define W_WIDTH_FACTOR 6 //Higher number, smaller waves
|
||||||
@ -4051,9 +4050,13 @@ uint16_t WS2812FX::mode_aurora(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t backlight = 1; //dimmer backlight if less active colors
|
||||||
|
if (SEGCOLOR(0)) backlight++;
|
||||||
|
if (SEGCOLOR(1)) backlight++;
|
||||||
|
if (SEGCOLOR(2)) backlight++;
|
||||||
//Loop through LEDs to determine color
|
//Loop through LEDs to determine color
|
||||||
for(int i = 0; i < SEGLEN; i++) {
|
for(int i = 0; i < SEGLEN; i++) {
|
||||||
CRGB mixedRgb = CRGB(BACKLIGHT, BACKLIGHT, BACKLIGHT);
|
CRGB mixedRgb = CRGB(backlight, backlight, backlight);
|
||||||
|
|
||||||
//For each LED we must check each wave if it is "active" at this position.
|
//For each LED we must check each wave if it is "active" at this position.
|
||||||
//If there are multiple waves active on a LED we multiply their values.
|
//If there are multiple waves active on a LED we multiply their values.
|
||||||
@ -4065,7 +4068,7 @@ uint16_t WS2812FX::mode_aurora(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPixelColor(i, mixedRgb[0], mixedRgb[1], mixedRgb[2], BACKLIGHT);
|
setPixelColor(i, mixedRgb[0], mixedRgb[1], mixedRgb[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FRAMETIME;
|
return FRAMETIME;
|
||||||
|
22
wled00/FX.h
22
wled00/FX.h
@ -319,6 +319,27 @@ class WS2812FX {
|
|||||||
vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vLength;
|
return vLength;
|
||||||
}
|
}
|
||||||
|
uint8_t differs(Segment& b) {
|
||||||
|
uint8_t d = 0;
|
||||||
|
if (start != b.start) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
if (stop != b.stop) d |= SEG_DIFFERS_BOUNDS;
|
||||||
|
if (offset != b.offset) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (grouping != b.grouping) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (spacing != b.spacing) d |= SEG_DIFFERS_GSO;
|
||||||
|
if (opacity != b.opacity) d |= SEG_DIFFERS_BRI;
|
||||||
|
if (mode != b.mode) d |= SEG_DIFFERS_FX;
|
||||||
|
if (speed != b.speed) d |= SEG_DIFFERS_FX;
|
||||||
|
if (intensity != b.intensity) d |= SEG_DIFFERS_FX;
|
||||||
|
if (palette != b.palette) d |= SEG_DIFFERS_FX;
|
||||||
|
|
||||||
|
if ((options & 0b00101111) != (b.options & 0b00101111)) d |= SEG_DIFFERS_OPT;
|
||||||
|
for (uint8_t i = 0; i < NUM_COLORS; i++)
|
||||||
|
{
|
||||||
|
if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
} segment;
|
} segment;
|
||||||
|
|
||||||
// segment runtime parameters
|
// segment runtime parameters
|
||||||
@ -619,7 +640,6 @@ class WS2812FX {
|
|||||||
gammaCorrectBri = false,
|
gammaCorrectBri = false,
|
||||||
gammaCorrectCol = true,
|
gammaCorrectCol = true,
|
||||||
applyToAllSelected = true,
|
applyToAllSelected = true,
|
||||||
segmentsAreIdentical(Segment* a, Segment* b),
|
|
||||||
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p),
|
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p),
|
||||||
// return true if the strip is being sent pixel updates
|
// return true if the strip is being sent pixel updates
|
||||||
isUpdating(void);
|
isUpdating(void);
|
||||||
|
@ -1018,23 +1018,6 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
|
|||||||
return crgb_to_col(fastled_col);
|
return crgb_to_col(fastled_col);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@returns `true` if color, mode, speed, intensity and palette match
|
|
||||||
bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
|
|
||||||
{
|
|
||||||
//if (a->start != b->start) return false;
|
|
||||||
//if (a->stop != b->stop) return false;
|
|
||||||
for (uint8_t i = 0; i < NUM_COLORS; i++)
|
|
||||||
{
|
|
||||||
if (a->colors[i] != b->colors[i]) return false;
|
|
||||||
}
|
|
||||||
if (a->mode != b->mode) return false;
|
|
||||||
if (a->speed != b->speed) return false;
|
|
||||||
if (a->intensity != b->intensity) return false;
|
|
||||||
if (a->palette != b->palette) return false;
|
|
||||||
//if (a->getOption(SEG_OPTION_REVERSED) != b->getOption(SEG_OPTION_REVERSED)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//load custom mapping table from JSON file
|
//load custom mapping table from JSON file
|
||||||
void WS2812FX::deserializeMap(uint8_t n) {
|
void WS2812FX::deserializeMap(uint8_t n) {
|
||||||
|
@ -19,7 +19,7 @@ void shortPressAction(uint8_t b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// publish MQTT message
|
// publish MQTT message
|
||||||
if (WLED_MQTT_CONNECTED) {
|
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
|
||||||
char subuf[64];
|
char subuf[64];
|
||||||
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
||||||
mqtt->publish(subuf, 0, false, "short");
|
mqtt->publish(subuf, 0, false, "short");
|
||||||
@ -74,7 +74,7 @@ void handleSwitch(uint8_t b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// publish MQTT message
|
// publish MQTT message
|
||||||
if (WLED_MQTT_CONNECTED) {
|
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
|
||||||
char subuf[64];
|
char subuf[64];
|
||||||
if (buttonType[b] == BTN_TYPE_PIR_SENSOR) sprintf_P(subuf, PSTR("%s/motion/%d"), mqttDeviceTopic, (int)b);
|
if (buttonType[b] == BTN_TYPE_PIR_SENSOR) sprintf_P(subuf, PSTR("%s/motion/%d"), mqttDeviceTopic, (int)b);
|
||||||
else sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
else sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
||||||
@ -96,7 +96,7 @@ void handleAnalog(uint8_t b)
|
|||||||
|
|
||||||
if (buttonType[b] == BTN_TYPE_ANALOG_INVERTED) aRead = 255 - aRead;
|
if (buttonType[b] == BTN_TYPE_ANALOG_INVERTED) aRead = 255 - aRead;
|
||||||
|
|
||||||
// remove noise & reduce frequency of UI updates (3*13mV)
|
// remove noise & reduce frequency of UI updates
|
||||||
aRead &= 0xFC;
|
aRead &= 0xFC;
|
||||||
|
|
||||||
if (oldRead[b] == aRead) return; // no change in reading
|
if (oldRead[b] == aRead) return; // no change in reading
|
||||||
@ -199,7 +199,7 @@ void handleButton()
|
|||||||
else _setRandomColor(false,true);
|
else _setRandomColor(false,true);
|
||||||
|
|
||||||
// publish MQTT message
|
// publish MQTT message
|
||||||
if (WLED_MQTT_CONNECTED) {
|
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
|
||||||
char subuf[64];
|
char subuf[64];
|
||||||
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
||||||
mqtt->publish(subuf, 0, false, "long");
|
mqtt->publish(subuf, 0, false, "long");
|
||||||
@ -227,7 +227,7 @@ void handleButton()
|
|||||||
applyPreset(macroDoublePress[b]);
|
applyPreset(macroDoublePress[b]);
|
||||||
|
|
||||||
// publish MQTT message
|
// publish MQTT message
|
||||||
if (WLED_MQTT_CONNECTED) {
|
if (buttonPublishMqtt && WLED_MQTT_CONNECTED) {
|
||||||
char subuf[64];
|
char subuf[64];
|
||||||
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
sprintf_P(subuf, _mqtt_topic_button, mqttDeviceTopic, (int)b);
|
||||||
mqtt->publish(subuf, 0, false, "double");
|
mqtt->publish(subuf, 0, false, "double");
|
||||||
|
@ -121,7 +121,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (lC > ledCount) ledCount = lC; // fix incorrect total length (honour analog setup)
|
if (lC > ledCount) ledCount = lC; // fix incorrect total length (honour analog setup)
|
||||||
|
|
||||||
// read multiple button configuration
|
// read multiple button configuration
|
||||||
JsonArray hw_btn_ins = hw[F("btn")]["ins"];
|
JsonObject btn_obj = hw["btn"];
|
||||||
|
JsonArray hw_btn_ins = btn_obj[F("ins")];
|
||||||
if (!hw_btn_ins.isNull()) {
|
if (!hw_btn_ins.isNull()) {
|
||||||
uint8_t s = 0;
|
uint8_t s = 0;
|
||||||
for (JsonObject btn : hw_btn_ins) {
|
for (JsonObject btn : hw_btn_ins) {
|
||||||
@ -133,7 +134,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
} else {
|
} else {
|
||||||
btnPin[s] = -1;
|
btnPin[s] = -1;
|
||||||
}
|
}
|
||||||
JsonArray hw_btn_ins_0_macros = btn[F("macros")];
|
JsonArray hw_btn_ins_0_macros = btn["macros"];
|
||||||
CJSON(macroButton[s], hw_btn_ins_0_macros[0]);
|
CJSON(macroButton[s], hw_btn_ins_0_macros[0]);
|
||||||
CJSON(macroLongPress[s],hw_btn_ins_0_macros[1]);
|
CJSON(macroLongPress[s],hw_btn_ins_0_macros[1]);
|
||||||
CJSON(macroDoublePress[s], hw_btn_ins_0_macros[2]);
|
CJSON(macroDoublePress[s], hw_btn_ins_0_macros[2]);
|
||||||
@ -158,7 +159,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
macroDoublePress[s] = 0;
|
macroDoublePress[s] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CJSON(touchThreshold,hw[F("btn")][F("tt")]);
|
CJSON(touchThreshold,btn_obj[F("tt")]);
|
||||||
|
CJSON(buttonPublishMqtt,btn_obj["mqtt"]);
|
||||||
|
|
||||||
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||||
if (hw_ir_pin > -2) {
|
if (hw_ir_pin > -2) {
|
||||||
@ -190,8 +192,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
CJSON(briMultiplier, light[F("scale-bri")]);
|
CJSON(briMultiplier, light[F("scale-bri")]);
|
||||||
CJSON(strip.paletteBlend, light[F("pal-mode")]);
|
CJSON(strip.paletteBlend, light[F("pal-mode")]);
|
||||||
|
|
||||||
float light_gc_bri = light[F("gc")]["bri"];
|
float light_gc_bri = light["gc"]["bri"];
|
||||||
float light_gc_col = light[F("gc")]["col"]; // 2.8
|
float light_gc_col = light["gc"]["col"]; // 2.8
|
||||||
if (light_gc_bri > 1.5) strip.gammaCorrectBri = true;
|
if (light_gc_bri > 1.5) strip.gammaCorrectBri = true;
|
||||||
else if (light_gc_bri > 0.5) strip.gammaCorrectBri = false;
|
else if (light_gc_bri > 0.5) strip.gammaCorrectBri = false;
|
||||||
if (light_gc_col > 1.5) strip.gammaCorrectCol = true;
|
if (light_gc_col > 1.5) strip.gammaCorrectCol = true;
|
||||||
@ -210,7 +212,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (nightlightDelayMinsDefault != prev) nightlightDelayMins = nightlightDelayMinsDefault;
|
if (nightlightDelayMinsDefault != prev) nightlightDelayMins = nightlightDelayMinsDefault;
|
||||||
|
|
||||||
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
CJSON(nightlightTargetBri, light_nl[F("tbri")]);
|
||||||
CJSON(macroNl, light_nl[F("macro")]);
|
CJSON(macroNl, light_nl["macro"]);
|
||||||
|
|
||||||
JsonObject def = doc[F("def")];
|
JsonObject def = doc[F("def")];
|
||||||
CJSON(bootPreset, def[F("ps")]);
|
CJSON(bootPreset, def[F("ps")]);
|
||||||
@ -234,10 +236,10 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
prev = notifyDirectDefault;
|
prev = notifyDirectDefault;
|
||||||
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
CJSON(notifyDirectDefault, if_sync_send[F("dir")]);
|
||||||
if (notifyDirectDefault != prev) notifyDirect = notifyDirectDefault;
|
if (notifyDirectDefault != prev) notifyDirect = notifyDirectDefault;
|
||||||
CJSON(notifyButton, if_sync_send[F("btn")]);
|
CJSON(notifyButton, if_sync_send["btn"]);
|
||||||
CJSON(notifyAlexa, if_sync_send[F("va")]);
|
CJSON(notifyAlexa, if_sync_send["va"]);
|
||||||
CJSON(notifyHue, if_sync_send[F("hue")]);
|
CJSON(notifyHue, if_sync_send["hue"]);
|
||||||
CJSON(notifyMacro, if_sync_send[F("macro")]);
|
CJSON(notifyMacro, if_sync_send["macro"]);
|
||||||
CJSON(notifyTwice, if_sync_send[F("twice")]);
|
CJSON(notifyTwice, if_sync_send[F("twice")]);
|
||||||
|
|
||||||
JsonObject if_nodes = interfaces["nodes"];
|
JsonObject if_nodes = interfaces["nodes"];
|
||||||
@ -261,10 +263,10 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
CJSON(arlsDisableGammaCorrection, if_live[F("no-gc")]); // false
|
CJSON(arlsDisableGammaCorrection, if_live[F("no-gc")]); // false
|
||||||
CJSON(arlsOffset, if_live[F("offset")]); // 0
|
CJSON(arlsOffset, if_live[F("offset")]); // 0
|
||||||
|
|
||||||
CJSON(alexaEnabled, interfaces[F("va")][F("alexa")]); // false
|
CJSON(alexaEnabled, interfaces["va"][F("alexa")]); // false
|
||||||
|
|
||||||
CJSON(macroAlexaOn, interfaces[F("va")][F("macros")][0]);
|
CJSON(macroAlexaOn, interfaces["va"]["macros"][0]);
|
||||||
CJSON(macroAlexaOff, interfaces[F("va")][F("macros")][1]);
|
CJSON(macroAlexaOff, interfaces["va"]["macros"][1]);
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_BLYNK
|
#ifndef WLED_DISABLE_BLYNK
|
||||||
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
||||||
@ -291,7 +293,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_HUESYNC
|
#ifndef WLED_DISABLE_HUESYNC
|
||||||
JsonObject if_hue = interfaces[F("hue")];
|
JsonObject if_hue = interfaces["hue"];
|
||||||
CJSON(huePollingEnabled, if_hue["en"]);
|
CJSON(huePollingEnabled, if_hue["en"]);
|
||||||
CJSON(huePollLightId, if_hue["id"]);
|
CJSON(huePollLightId, if_hue["id"]);
|
||||||
tdd = if_hue[F("iv")] | -1;
|
tdd = if_hue[F("iv")] | -1;
|
||||||
@ -339,7 +341,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
CJSON(countdownHour, cntdwn_goal[3]);
|
CJSON(countdownHour, cntdwn_goal[3]);
|
||||||
CJSON(countdownMin, cntdwn_goal[4]);
|
CJSON(countdownMin, cntdwn_goal[4]);
|
||||||
CJSON(countdownSec, cntdwn_goal[5]);
|
CJSON(countdownSec, cntdwn_goal[5]);
|
||||||
CJSON(macroCountdown, cntdwn[F("macro")]);
|
CJSON(macroCountdown, cntdwn["macro"]);
|
||||||
setCountdown();
|
setCountdown();
|
||||||
|
|
||||||
JsonArray timers = tm["ins"];
|
JsonArray timers = tm["ins"];
|
||||||
@ -349,7 +351,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset
|
if (it<8 && timer[F("hour")]==255) it=8; // hour==255 -> sunrise/sunset
|
||||||
CJSON(timerHours[it], timer[F("hour")]);
|
CJSON(timerHours[it], timer[F("hour")]);
|
||||||
CJSON(timerMinutes[it], timer["min"]);
|
CJSON(timerMinutes[it], timer["min"]);
|
||||||
CJSON(timerMacro[it], timer[F("macro")]);
|
CJSON(timerMacro[it], timer["macro"]);
|
||||||
|
|
||||||
byte dowPrev = timerWeekday[it];
|
byte dowPrev = timerWeekday[it];
|
||||||
//note: act is currently only 0 or 1.
|
//note: act is currently only 0 or 1.
|
||||||
@ -538,6 +540,7 @@ void serializeConfig() {
|
|||||||
hw_btn_ins_0_macros.add(macroDoublePress[i]);
|
hw_btn_ins_0_macros.add(macroDoublePress[i]);
|
||||||
}
|
}
|
||||||
hw_btn[F("tt")] = touchThreshold;
|
hw_btn[F("tt")] = touchThreshold;
|
||||||
|
hw_btn["mqtt"] = buttonPublishMqtt;
|
||||||
|
|
||||||
JsonObject hw_ir = hw.createNestedObject("ir");
|
JsonObject hw_ir = hw.createNestedObject("ir");
|
||||||
hw_ir["pin"] = irPin;
|
hw_ir["pin"] = irPin;
|
||||||
@ -567,7 +570,7 @@ void serializeConfig() {
|
|||||||
light_nl[F("mode")] = nightlightMode;
|
light_nl[F("mode")] = nightlightMode;
|
||||||
light_nl["dur"] = nightlightDelayMinsDefault;
|
light_nl["dur"] = nightlightDelayMinsDefault;
|
||||||
light_nl[F("tbri")] = nightlightTargetBri;
|
light_nl[F("tbri")] = nightlightTargetBri;
|
||||||
light_nl[F("macro")] = macroNl;
|
light_nl["macro"] = macroNl;
|
||||||
|
|
||||||
JsonObject def = doc.createNestedObject("def");
|
JsonObject def = doc.createNestedObject("def");
|
||||||
def[F("ps")] = bootPreset;
|
def[F("ps")] = bootPreset;
|
||||||
@ -587,10 +590,10 @@ void serializeConfig() {
|
|||||||
|
|
||||||
JsonObject if_sync_send = if_sync.createNestedObject("send");
|
JsonObject if_sync_send = if_sync.createNestedObject("send");
|
||||||
if_sync_send[F("dir")] = notifyDirect;
|
if_sync_send[F("dir")] = notifyDirect;
|
||||||
if_sync_send[F("btn")] = notifyButton;
|
if_sync_send["btn"] = notifyButton;
|
||||||
if_sync_send[F("va")] = notifyAlexa;
|
if_sync_send["va"] = notifyAlexa;
|
||||||
if_sync_send[F("hue")] = notifyHue;
|
if_sync_send["hue"] = notifyHue;
|
||||||
if_sync_send[F("macro")] = notifyMacro;
|
if_sync_send["macro"] = notifyMacro;
|
||||||
if_sync_send[F("twice")] = notifyTwice;
|
if_sync_send[F("twice")] = notifyTwice;
|
||||||
|
|
||||||
JsonObject if_nodes = interfaces.createNestedObject("nodes");
|
JsonObject if_nodes = interfaces.createNestedObject("nodes");
|
||||||
@ -682,7 +685,7 @@ void serializeConfig() {
|
|||||||
JsonArray goal = cntdwn.createNestedArray(F("goal"));
|
JsonArray goal = cntdwn.createNestedArray(F("goal"));
|
||||||
goal.add(countdownYear); goal.add(countdownMonth); goal.add(countdownDay);
|
goal.add(countdownYear); goal.add(countdownMonth); goal.add(countdownDay);
|
||||||
goal.add(countdownHour); goal.add(countdownMin); goal.add(countdownSec);
|
goal.add(countdownHour); goal.add(countdownMin); goal.add(countdownSec);
|
||||||
cntdwn[F("macro")] = macroCountdown;
|
cntdwn["macro"] = macroCountdown;
|
||||||
|
|
||||||
JsonArray timers_ins = timers.createNestedArray("ins");
|
JsonArray timers_ins = timers.createNestedArray("ins");
|
||||||
|
|
||||||
@ -692,7 +695,7 @@ void serializeConfig() {
|
|||||||
timers_ins0["en"] = (timerWeekday[i] & 0x01);
|
timers_ins0["en"] = (timerWeekday[i] & 0x01);
|
||||||
timers_ins0[F("hour")] = timerHours[i];
|
timers_ins0[F("hour")] = timerHours[i];
|
||||||
timers_ins0["min"] = timerMinutes[i];
|
timers_ins0["min"] = timerMinutes[i];
|
||||||
timers_ins0[F("macro")] = timerMacro[i];
|
timers_ins0["macro"] = timerMacro[i];
|
||||||
timers_ins0[F("dow")] = timerWeekday[i] >> 1;
|
timers_ins0[F("dow")] = timerWeekday[i] >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +755,7 @@ bool deserializeConfigSec() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_HUESYNC
|
#ifndef WLED_DISABLE_HUESYNC
|
||||||
getStringFromJson(hueApiKey, interfaces[F("hue")][F("key")], 47);
|
getStringFromJson(hueApiKey, interfaces["hue"][F("key")], 47);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject ota = doc["ota"];
|
JsonObject ota = doc["ota"];
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
||||||
#define NOTIFIER_CALL_MODE_BLYNK 9
|
#define NOTIFIER_CALL_MODE_BLYNK 9
|
||||||
#define NOTIFIER_CALL_MODE_ALEXA 10
|
#define NOTIFIER_CALL_MODE_ALEXA 10
|
||||||
|
#define NOTIFIER_CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
||||||
|
|
||||||
//RGB to RGBW conversion mode
|
//RGB to RGBW conversion mode
|
||||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
||||||
@ -195,6 +196,14 @@
|
|||||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||||
#define SEG_OPTION_TRANSITIONAL 7
|
#define SEG_OPTION_TRANSITIONAL 7
|
||||||
|
|
||||||
|
//Segment differs return byte
|
||||||
|
#define SEG_DIFFERS_BRI 0x01
|
||||||
|
#define SEG_DIFFERS_OPT 0x02
|
||||||
|
#define SEG_DIFFERS_COL 0x04
|
||||||
|
#define SEG_DIFFERS_FX 0x08
|
||||||
|
#define SEG_DIFFERS_BOUNDS 0x10
|
||||||
|
#define SEG_DIFFERS_GSO 0x20
|
||||||
|
|
||||||
//Playlist option byte
|
//Playlist option byte
|
||||||
#define PL_OPTION_SHUFFLE 0x01
|
#define PL_OPTION_SHUFFLE 0x01
|
||||||
|
|
||||||
|
@ -140,6 +140,10 @@ button {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
.segt TD.h {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 2px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
.keytd {
|
.keytd {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -573,6 +577,8 @@ input[type=range]::-moz-range-thumb {
|
|||||||
transition-duration: 0.5s;
|
transition-duration: 0.5s;
|
||||||
-webkit-backface-visibility: hidden;
|
-webkit-backface-visibility: hidden;
|
||||||
-webkit-transform:translate3d(0,0,0);
|
-webkit-transform:translate3d(0,0,0);
|
||||||
|
overflow: clip;
|
||||||
|
text-overflow: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-s {
|
.btn-s {
|
||||||
@ -595,9 +601,11 @@ input[type=range]::-moz-range-thumb {
|
|||||||
}
|
}
|
||||||
.btn-xs, .btn-pl-del, .btn-pl-add {
|
.btn-xs, .btn-pl-del, .btn-pl-add {
|
||||||
width: 42px;
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
}
|
}
|
||||||
.btn-pl-del, .btn-pl-add {
|
.btn-pl-del, .btn-pl-add {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
#qcs-w {
|
#qcs-w {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@ -975,13 +983,13 @@ input[type=number]::-webkit-outer-spin-button {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#selectPalette .lstI.selected {
|
#pallist .lstI.selected {
|
||||||
top: 80px;
|
top: 27px;
|
||||||
bottom: 0;
|
bottom: -11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#selectPalette .lstI.sticky {
|
#pallist .lstI.sticky {
|
||||||
top: 40px;
|
top: -11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lstI.sticky {
|
.lstI.sticky {
|
||||||
|
@ -102,11 +102,11 @@
|
|||||||
<p class="labels"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
<p class="labels"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
||||||
<div class="il">
|
<div class="il">
|
||||||
<div class="staytop fnd">
|
<div class="staytop fnd">
|
||||||
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'selectPalette')" onfocus="search(this)" />
|
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'pallist')" onfocus="search(this)" />
|
||||||
<span onclick="clean(this)" class="icons"></span>
|
<span onclick="clean(this)" class="icons"></span>
|
||||||
<div class="icons"><svg xmlns='http://www.w3.org/2000/svg' class='fndIcn'><circle cx='8' cy='8' r='6' /><line x1='12' y1='12' x2='24' y2='12' transform='rotate(45,12,12)' /></svg></div>
|
<div class="icons"><svg xmlns='http://www.w3.org/2000/svg' class='fndIcn'><circle cx='8' cy='8' r='6' /><line x1='12' y1='12' x2='24' y2='12' transform='rotate(45,12,12)' /></svg></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="selectPalette" class="list">
|
<div id="pallist" class="list">
|
||||||
<div class="lstI" data-id="0">
|
<div class="lstI" data-id="0">
|
||||||
<label class="radio schkl">
|
<label class="radio schkl">
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ var selColors;
|
|||||||
var expanded = [false];
|
var expanded = [false];
|
||||||
var powered = [true];
|
var powered = [true];
|
||||||
var nlDur = 60, nlTar = 0;
|
var nlDur = 60, nlTar = 0;
|
||||||
var nlFade = false;
|
var nlMode = false;
|
||||||
var selectedFx = 0;
|
var selectedFx = 0;
|
||||||
var selectedPal = 0;
|
var selectedPal = 0;
|
||||||
var csel = 0;
|
var csel = 0;
|
||||||
@ -16,19 +16,18 @@ var lastUpdate = 0;
|
|||||||
var segCount = 0, ledCount = 0, lowestUnused = 0, maxSeg = 0, lSeg = 0;
|
var segCount = 0, ledCount = 0, lowestUnused = 0, maxSeg = 0, lSeg = 0;
|
||||||
var pcMode = false, pcModeA = false, lastw = 0;
|
var pcMode = false, pcModeA = false, lastw = 0;
|
||||||
var tr = 7;
|
var tr = 7;
|
||||||
var pNum = 0;
|
|
||||||
var d = document;
|
var d = document;
|
||||||
const ranges = RangeTouch.setup('input[type="range"]', {});
|
const ranges = RangeTouch.setup('input[type="range"]', {});
|
||||||
var palettesData;
|
var palettesData;
|
||||||
var pJson = {}, eJson = {}, lJson = {};
|
var pJson = {}, eJson = {}, lJson = {};
|
||||||
var pN = "", pI = 0;
|
var pN = "", pI = 0, pNum = 0;
|
||||||
var pmt = 1, pmtLS = 0, pmtLast = 0;
|
var pmt = 1, pmtLS = 0, pmtLast = 0;
|
||||||
var lastinfo = {};
|
var lastinfo = {};
|
||||||
|
var ws, noWS = false;
|
||||||
var cfg = {
|
var cfg = {
|
||||||
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
||||||
comp :{colors:{picker: true, rgb: false, quick: true, hex: false}, labels:true, pcmbot:false, pid:true, seglen:false}
|
comp :{colors:{picker: true, rgb: false, quick: true, hex: false}, labels:true, pcmbot:false, pid:true, seglen:false}
|
||||||
};
|
};
|
||||||
var myWS, noWS = false;
|
|
||||||
|
|
||||||
var cpick = new iro.ColorPicker("#picker", {
|
var cpick = new iro.ColorPicker("#picker", {
|
||||||
width: 260,
|
width: 260,
|
||||||
@ -257,16 +256,6 @@ function onLoad()
|
|||||||
sl.addEventListener('touchstart', toggleBubble);
|
sl.addEventListener('touchstart', toggleBubble);
|
||||||
sl.addEventListener('touchend', toggleBubble);
|
sl.addEventListener('touchend', toggleBubble);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create UI update WS handler
|
|
||||||
myWS = new WebSocket('ws://'+(loc?locip:window.location.hostname)+'/ws');
|
|
||||||
// myWS.onopen = function () {
|
|
||||||
// myWS.send("{'v':true}");
|
|
||||||
// }
|
|
||||||
myWS.onmessage = function(event) {
|
|
||||||
var json = JSON.parse(event.data);
|
|
||||||
if (handleJson(json.state)) updateUI(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTablinks(tabI)
|
function updateTablinks(tabI)
|
||||||
@ -557,6 +546,7 @@ function loadInfo(callback=null)
|
|||||||
return res.json();
|
return res.json();
|
||||||
})
|
})
|
||||||
.then(json => {
|
.then(json => {
|
||||||
|
clearErrorToast();
|
||||||
lastinfo = json;
|
lastinfo = json;
|
||||||
var name = json.name;
|
var name = json.name;
|
||||||
gId('namelabel').innerHTML = name;
|
gId('namelabel').innerHTML = name;
|
||||||
@ -569,8 +559,11 @@ function loadInfo(callback=null)
|
|||||||
syncTglRecv = json.str;
|
syncTglRecv = json.str;
|
||||||
maxSeg = json.leds.maxseg;
|
maxSeg = json.leds.maxseg;
|
||||||
pmt = json.fs.pmt;
|
pmt = json.fs.pmt;
|
||||||
gId('buttonNodes').style.display = showNodes() ? "block":"none";
|
showNodes();
|
||||||
populateInfo(json);
|
populateInfo(json);
|
||||||
|
// Create UI update WS handler
|
||||||
|
if (!ws && json.ws > -1) setTimeout(makeWS,1000);
|
||||||
|
reqsLegal = true;
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
@ -813,10 +806,10 @@ function populatePalettes()
|
|||||||
"name": "Default",
|
"name": "Default",
|
||||||
});
|
});
|
||||||
|
|
||||||
var paletteHtml = "";
|
var html = "";
|
||||||
for (let i = 0; i < palettes.length; i++) {
|
for (let i = 0; i < palettes.length; i++) {
|
||||||
let previewCss = genPalPrevCss(palettes[i].id);
|
let previewCss = genPalPrevCss(palettes[i].id);
|
||||||
paletteHtml += generateListItemHtml(
|
html += generateListItemHtml(
|
||||||
'palette',
|
'palette',
|
||||||
palettes[i].id,
|
palettes[i].id,
|
||||||
palettes[i].name,
|
palettes[i].name,
|
||||||
@ -825,12 +818,12 @@ function populatePalettes()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
gId('selectPalette').innerHTML=paletteHtml;
|
gId('pallist').innerHTML=html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function redrawPalPrev()
|
function redrawPalPrev()
|
||||||
{
|
{
|
||||||
let palettes = d.querySelectorAll('#selectPalette .lstI');
|
let palettes = d.querySelectorAll('#pallist .lstI');
|
||||||
for (let i = 0; i < palettes.length; i++) {
|
for (let i = 0; i < palettes.length; i++) {
|
||||||
let id = palettes[i].dataset.id;
|
let id = palettes[i].dataset.id;
|
||||||
let lstPrev = palettes[i].querySelector('.lstIprev');
|
let lstPrev = palettes[i].querySelector('.lstIprev');
|
||||||
@ -899,10 +892,10 @@ function genPalPrevCss(id)
|
|||||||
|
|
||||||
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '')
|
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '')
|
||||||
{
|
{
|
||||||
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}">
|
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" onClick="${clickAction}()">
|
||||||
<label class="radio schkl">
|
<label class="radio schkl">
|
||||||
|
|
||||||
<input type="radio" value="${id}" name="${listName}" onChange="${clickAction}()">
|
<input type="radio" value="${id}" name="${listName}">
|
||||||
<span class="radiomark schk"></span>
|
<span class="radiomark schk"></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="lstIcontent" onClick="${clickAction}(${id})">
|
<div class="lstIcontent" onClick="${clickAction}(${id})">
|
||||||
@ -918,8 +911,9 @@ function updateTrail(e, slidercol)
|
|||||||
{
|
{
|
||||||
if (e==null) return;
|
if (e==null) return;
|
||||||
var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
|
var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
|
||||||
var progress = e.value * 100 / max;
|
var perc = e.value * 100 / max;
|
||||||
progress = parseInt(progress);
|
perc = parseInt(perc);
|
||||||
|
if (perc < 50) perc += 2;
|
||||||
var scol;
|
var scol;
|
||||||
switch (slidercol) {
|
switch (slidercol) {
|
||||||
case 1: scol = "#f00"; break;
|
case 1: scol = "#f00"; break;
|
||||||
@ -927,7 +921,7 @@ function updateTrail(e, slidercol)
|
|||||||
case 3: scol = "#00f"; break;
|
case 3: scol = "#00f"; break;
|
||||||
default: scol = "var(--c-f)";
|
default: scol = "var(--c-f)";
|
||||||
}
|
}
|
||||||
var val = `linear-gradient(90deg, ${scol} ${progress}%, var(--c-4) ${progress}%)`;
|
var val = `linear-gradient(90deg, ${scol} ${perc}%, var(--c-4) ${perc}%)`;
|
||||||
e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = val;
|
e.parentNode.getElementsByClassName('sliderdisplay')[0].style.background = val;
|
||||||
var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0];
|
var bubble = e.parentNode.parentNode.getElementsByTagName('output')[0];
|
||||||
if (bubble) bubble.innerHTML = e.value;
|
if (bubble) bubble.innerHTML = e.value;
|
||||||
@ -993,12 +987,12 @@ function updatePA(scrollto=false)
|
|||||||
|
|
||||||
function updateUI(scrollto=false)
|
function updateUI(scrollto=false)
|
||||||
{
|
{
|
||||||
noWS = (!myWS || myWS.readyState === WebSocket.CLOSED);
|
noWS = (!ws || ws.readyState === WebSocket.CLOSED);
|
||||||
|
|
||||||
gId('buttonPower').className = (isOn) ? "active":"";
|
gId('buttonPower').className = (isOn) ? "active":"";
|
||||||
gId('buttonNl').className = (nlA) ? "active":"";
|
gId('buttonNl').className = (nlA) ? "active":"";
|
||||||
gId('buttonSync').className = (syncSend) ? "active":"";
|
gId('buttonSync').className = (syncSend) ? "active":"";
|
||||||
gId('buttonNodes').style.display = showNodes() ? "block":"none";
|
showNodes();
|
||||||
|
|
||||||
updateSelectedPalette(scrollto);
|
updateSelectedPalette(scrollto);
|
||||||
updateSelectedFx(scrollto);
|
updateSelectedFx(scrollto);
|
||||||
@ -1016,7 +1010,7 @@ function updateUI(scrollto=false)
|
|||||||
|
|
||||||
function updateSelectedPalette(scrollto=false)
|
function updateSelectedPalette(scrollto=false)
|
||||||
{
|
{
|
||||||
var parent = gId('selectPalette');
|
var parent = gId('pallist');
|
||||||
var selPaletteInput = parent.querySelector(`input[name="palette"][value="${selectedPal}"]`);
|
var selPaletteInput = parent.querySelector(`input[name="palette"][value="${selectedPal}"]`);
|
||||||
if (selPaletteInput) selPaletteInput.checked = true;
|
if (selPaletteInput) selPaletteInput.checked = true;
|
||||||
|
|
||||||
@ -1030,7 +1024,6 @@ function updateSelectedPalette(scrollto=false)
|
|||||||
function updateSelectedFx(scrollto=false)
|
function updateSelectedFx(scrollto=false)
|
||||||
{
|
{
|
||||||
var parent = gId('fxlist');
|
var parent = gId('fxlist');
|
||||||
|
|
||||||
var selEffectInput = parent.querySelector(`input[name="fx"][value="${selectedFx}"]`);
|
var selEffectInput = parent.querySelector(`input[name="fx"][value="${selectedFx}"]`);
|
||||||
if (selEffectInput) selEffectInput.checked = true;
|
if (selEffectInput) selEffectInput.checked = true;
|
||||||
|
|
||||||
@ -1055,7 +1048,34 @@ function cmpP(a, b)
|
|||||||
return a[1].n.localeCompare(b[1].n,undefined, {numeric: true});
|
return a[1].n.localeCompare(b[1].n,undefined, {numeric: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleJson(s)
|
function makeWS() {
|
||||||
|
if (ws) return;
|
||||||
|
ws = new WebSocket('ws://'+(loc?locip:window.location.hostname)+'/ws');
|
||||||
|
ws.onmessage = function(event) {
|
||||||
|
clearTimeout(jsonTimeout);
|
||||||
|
jsonTimeout = null;
|
||||||
|
clearErrorToast();
|
||||||
|
gId('connind').style.backgroundColor = "#079";
|
||||||
|
var json = JSON.parse(event.data);
|
||||||
|
var info = json.info;
|
||||||
|
if (info) {
|
||||||
|
lastinfo = info;
|
||||||
|
showNodes();
|
||||||
|
if (isInfo) {
|
||||||
|
populateInfo(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var s = json.state ? json.state : json;
|
||||||
|
displayRover(info, s);
|
||||||
|
readState(s);
|
||||||
|
};
|
||||||
|
ws.onclose = function(event) {
|
||||||
|
gId('connind').style.backgroundColor = "#831";
|
||||||
|
ws = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readState(s,command=false)
|
||||||
{
|
{
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
|
|
||||||
@ -1076,8 +1096,12 @@ function handleJson(s)
|
|||||||
if(s.seg[i].sel) {selc = ind; break;} ind++;
|
if(s.seg[i].sel) {selc = ind; break;} ind++;
|
||||||
}
|
}
|
||||||
var i=s.seg[selc];
|
var i=s.seg[selc];
|
||||||
if (!i) return false; // no segments!
|
if (!i) {
|
||||||
|
showToast('No Segments!', true);
|
||||||
|
updateUI();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
selColors = i.col;
|
selColors = i.col;
|
||||||
var cd = gId('csl').children;
|
var cd = gId('csl').children;
|
||||||
for (let e = cd.length-1; e >= 0; e--)
|
for (let e = cd.length-1; e >= 0; e--)
|
||||||
@ -1104,21 +1128,37 @@ function handleJson(s)
|
|||||||
gId('sliderSpeed').value = i.sx;
|
gId('sliderSpeed').value = i.sx;
|
||||||
gId('sliderIntensity').value = i.ix;
|
gId('sliderIntensity').value = i.ix;
|
||||||
|
|
||||||
|
if (s.error && s.error != 0) {
|
||||||
|
var errstr = "";
|
||||||
|
switch (s.error) {
|
||||||
|
case 10:
|
||||||
|
errstr = "Could not mount filesystem!";
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
errstr = "Not enough space to save preset!";
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
errstr = "Preset not found.";
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
errstr = "A filesystem error has occured.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
showToast('Error ' + s.error + ": " + errstr, true);
|
||||||
|
}
|
||||||
|
|
||||||
selectedPal = i.pal;
|
selectedPal = i.pal;
|
||||||
selectedFx = i.fx;
|
selectedFx = i.fx;
|
||||||
|
updateUI(true);
|
||||||
//if (!gId('fxlist').querySelector(`input[name="fx"][value="${i.fx}"]`)) location.reload(); //effect list is gone (e.g. if restoring tab). Reload.
|
|
||||||
|
|
||||||
displayRover(lastinfo, s);
|
|
||||||
clearErrorToast();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonTimeout;
|
var jsonTimeout;
|
||||||
|
var reqsLegal = false;
|
||||||
|
|
||||||
function requestJson(command, rinfo = true, verbose = true, callback = null)
|
function requestJson(command, rinfo = true, verbose = true, callback = null)
|
||||||
{
|
{
|
||||||
gId('connind').style.backgroundColor = "#a90";
|
gId('connind').style.backgroundColor = "#a90";
|
||||||
|
if (command && !reqsLegal) return; //stop post requests from chrome onchange event on page restore
|
||||||
lastUpdate = new Date();
|
lastUpdate = new Date();
|
||||||
if (!jsonTimeout) jsonTimeout = setTimeout(showErrorToast, 3000);
|
if (!jsonTimeout) jsonTimeout = setTimeout(showErrorToast, 3000);
|
||||||
var req = null;
|
var req = null;
|
||||||
@ -1131,6 +1171,12 @@ function requestJson(command, rinfo = true, verbose = true, callback = null)
|
|||||||
command.time = Math.floor(Date.now() / 1000);
|
command.time = Math.floor(Date.now() / 1000);
|
||||||
req = JSON.stringify(command);
|
req = JSON.stringify(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((command || rinfo) && ws && ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.send(req?req:'{"v":true}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: type,
|
method: type,
|
||||||
headers: {
|
headers: {
|
||||||
@ -1153,24 +1199,8 @@ function requestJson(command, rinfo = true, verbose = true, callback = null)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var s = json.state ? json.state : json;
|
var s = json.state ? json.state : json;
|
||||||
if (!handleJson(s)) {
|
readState(s);
|
||||||
showToast('No Segments!', true);
|
reqsLegal = true;
|
||||||
updateUI(false);
|
|
||||||
if (callback) callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.error && s.error != 0) {
|
|
||||||
var errstr = "";
|
|
||||||
switch (s.error) {
|
|
||||||
case 10: errstr = "Could not mount filesystem!"; break;
|
|
||||||
case 11: errstr = "Not enough space to save preset!"; break;
|
|
||||||
case 12: errstr = "The requested preset does not exist."; break;
|
|
||||||
case 19: errstr = "A filesystem error has occured."; break;
|
|
||||||
}
|
|
||||||
showToast('Error ' + s.error + ": " + errstr, true);
|
|
||||||
}
|
|
||||||
updateUI(true);
|
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
@ -1191,8 +1221,12 @@ function togglePower()
|
|||||||
function toggleNl()
|
function toggleNl()
|
||||||
{
|
{
|
||||||
nlA = !nlA;
|
nlA = !nlA;
|
||||||
if (nlA) showToast(`Timer active. Your light will turn ${nlTar > 0 ? "on":"off"} ${nlFade ? "over":"after"} ${nlDur} minutes.`);
|
if (nlA)
|
||||||
else showToast('Timer deactivated.');
|
{
|
||||||
|
showToast(`Timer active. Your light will turn ${nlTar > 0 ? "on":"off"} ${nlMode ? "over":"after"} ${nlDur} minutes.`);
|
||||||
|
} else {
|
||||||
|
showToast('Timer deactivated.');
|
||||||
|
}
|
||||||
var obj = {"nl": {"on": nlA}};
|
var obj = {"nl": {"on": nlA}};
|
||||||
requestJson(obj, false);
|
requestJson(obj, false);
|
||||||
}
|
}
|
||||||
@ -1291,7 +1325,7 @@ function makePlSel(arr) {
|
|||||||
function refreshPlE(p) {
|
function refreshPlE(p) {
|
||||||
var plEDiv = gId(`ple${p}`);
|
var plEDiv = gId(`ple${p}`);
|
||||||
if (!plEDiv) return;
|
if (!plEDiv) return;
|
||||||
var content = "";
|
var content = "<div class=\"c\">Playlist entries</div>";
|
||||||
for (var i = 0; i < plJson[p].ps.length; i++) {
|
for (var i = 0; i < plJson[p].ps.length; i++) {
|
||||||
content += makePlEntry(p,i);
|
content += makePlEntry(p,i);
|
||||||
}
|
}
|
||||||
@ -1408,7 +1442,7 @@ ${plSelContent}
|
|||||||
<div class="c">Save to ID <input class="noslide" id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
<div class="c">Save to ID <input class="noslide" id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
||||||
<div class="c">
|
<div class="c">
|
||||||
<button class="btn btn-i btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon"></i>Save</button>
|
<button class="btn btn-i btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon"></i>Save</button>
|
||||||
${(i>0)?'<button class="btn btn-i btn-pl-del" id="p'+i+'del" onclick="delP('+i+')"><i class="icons btn-icon"></i>':'<button class="btn btn-p" onclick="resetPUtil()">Cancel'}</button>
|
${(i>0)?'<button class="btn btn-i btn-pl-del" id="p'+i+'del" onclick="delP('+i+')"><i class="icons btn-icon"></i>Delete':'<button class="btn btn-p" onclick="resetPUtil()">Cancel'}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="pwarn ${(i>0)?"bp":""} c" id="p${i}warn"></div>
|
<div class="pwarn ${(i>0)?"bp":""} c" id="p${i}warn"></div>
|
||||||
${(i>0)? ('<div class="h">ID ' +i+ '</div>'):""}`;
|
${(i>0)? ('<div class="h">ID ' +i+ '</div>'):""}`;
|
||||||
@ -1432,6 +1466,11 @@ function makePlEntry(p,i) {
|
|||||||
</td>
|
</td>
|
||||||
<td><button class="btn btn-i btn-pl-add" onclick="addPl(${p},${i})"><i class="icons btn-icon"></i></button></td>
|
<td><button class="btn btn-i btn-pl-add" onclick="addPl(${p},${i})"><i class="icons btn-icon"></i></button></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="h">Duration</td>
|
||||||
|
<td class="h">Transition</td>
|
||||||
|
<td class="h">#${i+1}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="40%"><input class="noslide segn" type="number" placeholder="Duration" max=6553.0 min=0.2 step=0.1 oninput="pleDur(${p},${i},this)" value="${plJson[p].dur[i]/10.0}">s</td>
|
<td width="40%"><input class="noslide segn" type="number" placeholder="Duration" max=6553.0 min=0.2 step=0.1 oninput="pleDur(${p},${i},this)" value="${plJson[p].dur[i]/10.0}">s</td>
|
||||||
<td width="40%"><input class="noslide segn" type="number" placeholder="Transition" max=65.0 min=0.0 step=0.1 oninput="pleTr(${p},${i},this)" value="${plJson[p].transition[i]/10.0}">s</td>
|
<td width="40%"><input class="noslide segn" type="number" placeholder="Transition" max=65.0 min=0.0 step=0.1 oninput="pleTr(${p},${i},this)" value="${plJson[p].transition[i]/10.0}">s</td>
|
||||||
@ -1555,14 +1594,15 @@ function setX(ind = null)
|
|||||||
function setPalette(paletteId = null)
|
function setPalette(paletteId = null)
|
||||||
{
|
{
|
||||||
if (paletteId === null) {
|
if (paletteId === null) {
|
||||||
paletteId = parseInt(d.querySelector('#selectPalette input[name="palette"]:checked').value);
|
paletteId = parseInt(d.querySelector('#pallist input[name="palette"]:checked').value);
|
||||||
} else {
|
} else {
|
||||||
d.querySelector(`#selectPalette input[name="palette"][value="${paletteId}`).checked = true;
|
d.querySelector(`#pallist input[name="palette"][value="${paletteId}`).checked = true;
|
||||||
}
|
}
|
||||||
var selElement = d.querySelector('#selectPalette .selected');
|
var selElement = d.querySelector('#pallist .selected');
|
||||||
if (selElement) selElement.classList.remove('selected');
|
if (selElement) {
|
||||||
|
selElement.classList.remove('selected')
|
||||||
d.querySelector(`#selectPalette .lstI[data-id="${paletteId}"]`).classList.add('selected');
|
}
|
||||||
|
d.querySelector(`#pallist .lstI[data-id="${paletteId}"]`).classList.add('selected');
|
||||||
var obj = {"seg": {"pal": paletteId}};
|
var obj = {"seg": {"pal": paletteId}};
|
||||||
requestJson(obj, false, noWS);
|
requestJson(obj, false, noWS);
|
||||||
}
|
}
|
||||||
@ -2026,13 +2066,13 @@ function move(e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showNodes() {
|
function showNodes() {
|
||||||
return (lastinfo.ndc > 0 && (w > 797 || (w > 539 && w < 720)));
|
gId('buttonNodes').style.display = (lastinfo.ndc > 0 && (w > 797 || (w > 539 && w < 720))) ? "block":"none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function size()
|
function size()
|
||||||
{
|
{
|
||||||
w = window.innerWidth;
|
w = window.innerWidth;
|
||||||
gId('buttonNodes').style.display = showNodes() ? "block":"none";
|
showNodes();
|
||||||
var h = gId('top').clientHeight;
|
var h = gId('top').clientHeight;
|
||||||
sCol('--th', h + "px");
|
sCol('--th', h + "px");
|
||||||
sCol('--bh', gId('bot').clientHeight + "px");
|
sCol('--bh', gId('bot').clientHeight + "px");
|
||||||
|
@ -92,7 +92,6 @@
|
|||||||
}
|
}
|
||||||
//returns mem usage
|
//returns mem usage
|
||||||
function getMem(type, len, p0) {
|
function getMem(type, len, p0) {
|
||||||
//len = parseInt(len);
|
|
||||||
if (type < 32) {
|
if (type < 32) {
|
||||||
if (maxM < 10000 && p0==3) { //8266 DMA uses 5x the mem
|
if (maxM < 10000 && p0==3) { //8266 DMA uses 5x the mem
|
||||||
if (type > 29) return len*20; //RGBW
|
if (type > 29) return len*20; //RGBW
|
||||||
@ -154,7 +153,7 @@
|
|||||||
}
|
}
|
||||||
// gId("ew"+n).onclick = (type > 31 && type < 48) ? (function(){return false}) : (function(){}); // prevent change for analog
|
// gId("ew"+n).onclick = (type > 31 && type < 48) ? (function(){return false}) : (function(){}); // prevent change for analog
|
||||||
// isRGBW |= gId("ew"+n).checked;
|
// isRGBW |= gId("ew"+n).checked;
|
||||||
isRGBW |= (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h
|
isRGBW |= (type == 30 || type == 31 || (type > 40 && type < 46 && type != 43)); // RGBW checkbox, TYPE_xxxx values from const.h
|
||||||
gId("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline"; // hide reverse, skip 1st & count for analog
|
gId("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline"; // hide reverse, skip 1st & count for analog
|
||||||
gId("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:"; // change analog start description
|
gId("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:"; // change analog start description
|
||||||
}
|
}
|
||||||
@ -240,6 +239,8 @@
|
|||||||
function lastEnd(i) {
|
function lastEnd(i) {
|
||||||
if (i<1) return 0;
|
if (i<1) return 0;
|
||||||
v = parseInt(d.getElementsByName("LS"+(i-1))[0].value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
v = parseInt(d.getElementsByName("LS"+(i-1))[0].value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
||||||
|
var type = parseInt(d.getElementsByName("LT"+(i-1))[0].value);
|
||||||
|
if (type > 31 && type < 48) v = 1; //PWM busses
|
||||||
if (isNaN(v)) return 0;
|
if (isNaN(v)) return 0;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -288,9 +289,9 @@ Color Order:
|
|||||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="33" class="s" onchange="UI()"/>
|
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="33" class="s" onchange="UI()"/>
|
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="33" class="s" onchange="UI()"/>
|
||||||
<br>
|
<br>
|
||||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />
|
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l" min="0" max="8191" value="${lastEnd(i)}" readonly required />
|
||||||
<div id="dig${i}" style="display:inline">
|
<div id="dig${i}" style="display:inline">
|
||||||
Count: <input type="number" name="LC${i}" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br>
|
Count: <input type="number" name="LC${i}" class="l" min="0" max="${maxPB}" value="1" required oninput="UI()" /><br>
|
||||||
Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
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>
|
Skip 1<sup>st</sup> LED: <input id="sl${i}" type="checkbox" name="SL${i}"><br>
|
||||||
</div>
|
</div>
|
||||||
@ -358,7 +359,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
|||||||
<br>
|
<br>
|
||||||
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
|
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
|
||||||
<div id="abl">
|
<div id="abl">
|
||||||
Maximum Current: <input name="MA" type="number" min="250" max="65000" oninput="UI()" required> mA<br>
|
Maximum Current: <input name="MA" type="number" class="l" min="250" max="65000" oninput="UI()" required> mA<br>
|
||||||
<div id="ampwarning" style="color: orange; display: none;">
|
<div id="ampwarning" style="color: orange; display: none;">
|
||||||
⚠ Your power supply provides high current.<br>
|
⚠ Your power supply provides high current.<br>
|
||||||
To improve the safety of your setup,<br>
|
To improve the safety of your setup,<br>
|
||||||
@ -393,37 +394,36 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
|||||||
<div id="btns"></div>
|
<div id="btns"></div>
|
||||||
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
||||||
IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="s"><select name="IT" onchange="UI()">
|
IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="s"><select name="IT" onchange="UI()">
|
||||||
<option value="0">Remote disabled</option>
|
<option value=0>Remote disabled</option>
|
||||||
<option value="1">24-key RGB</option>
|
<option value=1>24-key RGB</option>
|
||||||
<option value="2">24-key with CT</option>
|
<option value=2>24-key with CT</option>
|
||||||
<option value="3">40-key blue</option>
|
<option value=3>40-key blue</option>
|
||||||
<option value="4">44-key RGB</option>
|
<option value=4>44-key RGB</option>
|
||||||
<option value="5">21-key RGB</option>
|
<option value=5>21-key RGB</option>
|
||||||
<option value="6">6-key black</option>
|
<option value=6>6-key black</option>
|
||||||
<option value="7">9-key red</option>
|
<option value=7>9-key red</option>
|
||||||
<option value="8">JSON remote</option>
|
<option value=8>JSON remote</option>
|
||||||
</select><span style="cursor: pointer;" onclick="off('IR')"> ×</span><br>
|
</select><span style="cursor: pointer;" onclick="off('IR')"> ×</span><br>
|
||||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div>
|
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div>
|
||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><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()" class="s"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
Relay pin: <input type="number" min="-1" max="33" name="RL" onchange="UI()" class="s"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
||||||
<hr style="width:260px">
|
<hr style="width:260px">
|
||||||
<h3>Defaults</h3>
|
<h3>Defaults</h3>
|
||||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
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>
|
Default brightness: <input name="CA" type="number" class="m" 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)
|
Apply preset <input name="BP" type="number" class="m" min="0" max="250" required> at boot (0 uses defaults)
|
||||||
<br>- <i>or</i> -<br>
|
<br><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 color: <input type="checkbox" name="GC"> (strongly recommended)<br>
|
||||||
Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br><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> %
|
Brightness factor: <input name="BF" type="number" class="m" min="1" max="255" required> %
|
||||||
<h3>Transitions</h3>
|
<h3>Transitions</h3>
|
||||||
Crossfade: <input type="checkbox" name="TF"><br>
|
Crossfade: <input type="checkbox" name="TF"><br>
|
||||||
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
|
Transition Time: <input name="TD" type="number" class="xl" min="0" max="65500"> ms<br>
|
||||||
Enable Palette transitions: <input type="checkbox" name="PF">
|
Enable Palette transitions: <input type="checkbox" name="PF">
|
||||||
<h3>Timed light</h3>
|
<h3>Timed light</h3>
|
||||||
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
|
Default Duration: <input name="TL" type="number" class="m" min="1" max="255" required> min<br>
|
||||||
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
|
Default Target brightness: <input name="TB" type="number" class="m" min="0" max="255" required><br>
|
||||||
Mode:
|
Mode:
|
||||||
<select name="TW">
|
<select name="TW">
|
||||||
<option value="0">Wait and set</option>
|
<option value="0">Wait and set</option>
|
||||||
|
@ -87,6 +87,7 @@ Password: <input type="password" name="MQPASS" maxlength="64"><br>
|
|||||||
Client ID: <input name="MQCID" maxlength="40"><br>
|
Client ID: <input name="MQCID" maxlength="40"><br>
|
||||||
Device Topic: <input name="MD" maxlength="32"><br>
|
Device Topic: <input name="MD" maxlength="32"><br>
|
||||||
Group Topic: <input name="MG" maxlength="32"><br>
|
Group Topic: <input name="MG" maxlength="32"><br>
|
||||||
|
Publish on button press: <input type="checkbox" name="BM"><br>
|
||||||
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
||||||
<h3>Philips Hue</h3>
|
<h3>Philips Hue</h3>
|
||||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||||
|
@ -54,16 +54,16 @@ input[type="number"].xl {
|
|||||||
width: 85px;
|
width: 85px;
|
||||||
}
|
}
|
||||||
input[type="number"].l {
|
input[type="number"].l {
|
||||||
width: 60px;
|
width: 63px;
|
||||||
}
|
}
|
||||||
input[type="number"].m {
|
input[type="number"].m {
|
||||||
width: 55px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
input[type="number"].s {
|
input[type="number"].s {
|
||||||
width: 42px;
|
width: 49px;
|
||||||
}
|
}
|
||||||
input[type="number"].xs {
|
input[type="number"].xs {
|
||||||
width: 35px;
|
width: 42px;
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
|
File diff suppressed because one or more lines are too long
4413
wled00/html_ui.h
4413
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -161,7 +161,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
|||||||
hueColormode = 1;
|
hueColormode = 1;
|
||||||
} else //hs mode
|
} else //hs mode
|
||||||
{
|
{
|
||||||
hueHue = root[F("hue")];
|
hueHue = root["hue"];
|
||||||
hueSat = root[F("sat")];
|
hueSat = root[F("sat")];
|
||||||
hueColormode = 2;
|
hueColormode = 2;
|
||||||
}
|
}
|
||||||
|
287
wled00/json.cpp
287
wled00/json.cpp
@ -9,11 +9,14 @@
|
|||||||
void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||||
{
|
{
|
||||||
byte id = elem["id"] | it;
|
byte id = elem["id"] | it;
|
||||||
if (id < strip.getMaxSegments())
|
if (id >= strip.getMaxSegments()) return;
|
||||||
{
|
|
||||||
WS2812FX::Segment& seg = strip.getSegment(id);
|
WS2812FX::Segment& seg = strip.getSegment(id);
|
||||||
uint16_t start = elem[F("start")] | seg.start;
|
//WS2812FX::Segment prev;
|
||||||
int stop = elem["stop"] | -1;
|
//prev = seg; //make a backup so we can tell if something changed
|
||||||
|
|
||||||
|
uint16_t start = elem[F("start")] | seg.start;
|
||||||
|
int stop = elem["stop"] | -1;
|
||||||
|
|
||||||
if (elem["n"]) {
|
if (elem["n"]) {
|
||||||
// name field exists
|
// name field exists
|
||||||
@ -38,64 +41,64 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop < 0) {
|
if (stop < 0) {
|
||||||
uint16_t len = elem[F("len")];
|
uint16_t len = elem[F("len")];
|
||||||
stop = (len > 0) ? start + len : seg.stop;
|
stop = (len > 0) ? start + len : seg.stop;
|
||||||
}
|
}
|
||||||
uint16_t grp = elem[F("grp")] | seg.grouping;
|
uint16_t grp = elem[F("grp")] | seg.grouping;
|
||||||
uint16_t spc = elem[F("spc")] | seg.spacing;
|
uint16_t spc = elem[F("spc")] | seg.spacing;
|
||||||
strip.setSegment(id, start, stop, grp, spc);
|
strip.setSegment(id, start, stop, grp, spc);
|
||||||
seg.offset = elem[F("of")] | seg.offset;
|
seg.offset = elem[F("of")] | seg.offset;
|
||||||
if (stop > start && seg.offset > stop - start -1) seg.offset = stop - start -1;
|
if (stop > start && seg.offset > stop - start -1) seg.offset = stop - start -1;
|
||||||
|
|
||||||
int segbri = elem["bri"] | -1;
|
int segbri = elem["bri"] | -1;
|
||||||
if (segbri == 0) {
|
if (segbri == 0) {
|
||||||
seg.setOption(SEG_OPTION_ON, 0, id);
|
seg.setOption(SEG_OPTION_ON, 0, id);
|
||||||
} else if (segbri > 0) {
|
} else if (segbri > 0) {
|
||||||
seg.setOpacity(segbri, id);
|
seg.setOpacity(segbri, id);
|
||||||
seg.setOption(SEG_OPTION_ON, 1, id);
|
seg.setOption(SEG_OPTION_ON, 1, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON), id);
|
||||||
|
|
||||||
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON), id);
|
JsonArray colarr = elem["col"];
|
||||||
|
if (!colarr.isNull())
|
||||||
JsonArray colarr = elem["col"];
|
{
|
||||||
if (!colarr.isNull())
|
for (uint8_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < 3; i++)
|
int rgbw[] = {0,0,0,0};
|
||||||
{
|
bool colValid = false;
|
||||||
int rgbw[] = {0,0,0,0};
|
if (colarr[i].is<unsigned long>()) {
|
||||||
bool colValid = false;
|
// unsigned long RGBW (@blazoncek v2 experimental API implementation)
|
||||||
if (colarr[i].is<unsigned long>()) {
|
uint32_t colX = colarr[i];
|
||||||
// unsigned long RGBW (@blazoncek v2 experimental API implementation)
|
rgbw[0] = (colX >> 16) & 0xFF;
|
||||||
uint32_t colX = colarr[i];
|
rgbw[1] = (colX >> 8) & 0xFF;
|
||||||
rgbw[0] = (colX >> 16) & 0xFF;
|
rgbw[2] = (colX ) & 0xFF;
|
||||||
rgbw[1] = (colX >> 8) & 0xFF;
|
rgbw[3] = (colX >> 24) & 0xFF;
|
||||||
rgbw[2] = (colX ) & 0xFF;
|
colValid = true;
|
||||||
rgbw[3] = (colX >> 24) & 0xFF;
|
} else {
|
||||||
colValid = true;
|
JsonArray colX = colarr[i];
|
||||||
} else {
|
if (colX.isNull()) {
|
||||||
JsonArray colX = colarr[i];
|
byte brgbw[] = {0,0,0,0};
|
||||||
if (colX.isNull()) {
|
const char* hexCol = colarr[i];
|
||||||
byte brgbw[] = {0,0,0,0};
|
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
||||||
const char* hexCol = colarr[i];
|
int kelvin = colarr[i] | -1;
|
||||||
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
if (kelvin < 0) continue;
|
||||||
int kelvin = colarr[i] | -1;
|
if (kelvin == 0) seg.setColor(i, 0, id);
|
||||||
if (kelvin < 0) continue;
|
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
||||||
if (kelvin == 0) seg.setColor(i, 0, id);
|
|
||||||
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
|
||||||
colValid = true;
|
|
||||||
} else { //HEX string, e.g. "FFAA00"
|
|
||||||
colValid = colorFromHexString(brgbw, hexCol);
|
|
||||||
}
|
|
||||||
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
|
||||||
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
|
||||||
byte sz = colX.size();
|
|
||||||
if (sz == 0) continue; //do nothing on empty array
|
|
||||||
byte cp = copyArray(colX, rgbw, 4);
|
|
||||||
if (cp == 1 && rgbw[0] == 0)
|
|
||||||
seg.setColor(i, 0, id);
|
|
||||||
colValid = true;
|
colValid = true;
|
||||||
|
} else { //HEX string, e.g. "FFAA00"
|
||||||
|
colValid = colorFromHexString(brgbw, hexCol);
|
||||||
}
|
}
|
||||||
|
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||||
|
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
||||||
|
byte sz = colX.size();
|
||||||
|
if (sz == 0) continue; //do nothing on empty array
|
||||||
|
|
||||||
|
byte cp = copyArray(colX, rgbw, 4);
|
||||||
|
if (cp == 1 && rgbw[0] == 0)
|
||||||
|
seg.setColor(i, 0, id);
|
||||||
|
colValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!colValid) continue;
|
if (!colValid) continue;
|
||||||
@ -109,90 +112,90 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lx parser
|
|
||||||
#ifdef WLED_ENABLE_LOXONE
|
|
||||||
int lx = elem[F("lx")] | -1;
|
|
||||||
if (lx > 0) {
|
|
||||||
parseLxJson(lx, id, false);
|
|
||||||
}
|
|
||||||
int ly = elem[F("ly")] | -1;
|
|
||||||
if (ly > 0) {
|
|
||||||
parseLxJson(ly, id, true);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
|
|
||||||
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
|
||||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
|
||||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
|
||||||
|
|
||||||
//temporary, strip object gets updated via colorUpdated()
|
|
||||||
if (id == strip.getMainSegmentId()) {
|
|
||||||
byte effectPrev = effectCurrent;
|
|
||||||
effectCurrent = elem[F("fx")] | effectCurrent;
|
|
||||||
if (!presetId && effectCurrent != effectPrev) unloadPlaylist(); //stop playlist if active and FX changed manually
|
|
||||||
effectSpeed = elem[F("sx")] | effectSpeed;
|
|
||||||
effectIntensity = elem[F("ix")] | effectIntensity;
|
|
||||||
effectPalette = elem["pal"] | effectPalette;
|
|
||||||
} else { //permanent
|
|
||||||
byte fx = elem[F("fx")] | seg.mode;
|
|
||||||
if (fx != seg.mode && fx < strip.getModeCount()) {
|
|
||||||
strip.setMode(id, fx);
|
|
||||||
if (!presetId) unloadPlaylist(); //stop playlist if active and FX changed manually
|
|
||||||
}
|
|
||||||
seg.speed = elem[F("sx")] | seg.speed;
|
|
||||||
seg.intensity = elem[F("ix")] | seg.intensity;
|
|
||||||
seg.palette = elem["pal"] | seg.palette;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
|
||||||
if (!iarr.isNull()) {
|
|
||||||
strip.setPixelSegment(id);
|
|
||||||
|
|
||||||
//freeze and init to black
|
|
||||||
if (!seg.getOption(SEG_OPTION_FREEZE)) {
|
|
||||||
seg.setOption(SEG_OPTION_FREEZE, true);
|
|
||||||
strip.fill(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t start = 0, stop = 0;
|
|
||||||
byte set = 0; //0 nothing set, 1 start set, 2 range set
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < iarr.size(); i++) {
|
|
||||||
if(iarr[i].is<JsonInteger>()) {
|
|
||||||
if (!set) {
|
|
||||||
start = iarr[i];
|
|
||||||
set = 1;
|
|
||||||
} else {
|
|
||||||
stop = iarr[i];
|
|
||||||
set = 2;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
JsonArray icol = iarr[i];
|
|
||||||
if (icol.isNull()) break;
|
|
||||||
|
|
||||||
byte sz = icol.size();
|
|
||||||
if (sz == 0 || sz > 4) break;
|
|
||||||
|
|
||||||
int rgbw[] = {0,0,0,0};
|
|
||||||
copyArray(icol, rgbw);
|
|
||||||
|
|
||||||
if (set < 2) stop = start + 1;
|
|
||||||
for (uint16_t i = start; i < stop; i++) {
|
|
||||||
strip.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
|
||||||
}
|
|
||||||
if (!set) start++;
|
|
||||||
set = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strip.setPixelSegment(255);
|
|
||||||
strip.trigger();
|
|
||||||
} else { //return to regular effect
|
|
||||||
seg.setOption(SEG_OPTION_FREEZE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lx parser
|
||||||
|
#ifdef WLED_ENABLE_LOXONE
|
||||||
|
int lx = elem[F("lx")] | -1;
|
||||||
|
if (lx > 0) {
|
||||||
|
parseLxJson(lx, id, false);
|
||||||
|
}
|
||||||
|
int ly = elem[F("ly")] | -1;
|
||||||
|
if (ly > 0) {
|
||||||
|
parseLxJson(ly, id, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
|
||||||
|
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
||||||
|
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||||
|
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||||
|
|
||||||
|
//temporary, strip object gets updated via colorUpdated()
|
||||||
|
if (id == strip.getMainSegmentId()) {
|
||||||
|
byte effectPrev = effectCurrent;
|
||||||
|
effectCurrent = elem[F("fx")] | effectCurrent;
|
||||||
|
if (!presetId && effectCurrent != effectPrev) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||||
|
effectSpeed = elem[F("sx")] | effectSpeed;
|
||||||
|
effectIntensity = elem[F("ix")] | effectIntensity;
|
||||||
|
effectPalette = elem["pal"] | effectPalette;
|
||||||
|
} else { //permanent
|
||||||
|
byte fx = elem[F("fx")] | seg.mode;
|
||||||
|
if (fx != seg.mode && fx < strip.getModeCount()) {
|
||||||
|
strip.setMode(id, fx);
|
||||||
|
if (!presetId) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||||
|
}
|
||||||
|
seg.speed = elem[F("sx")] | seg.speed;
|
||||||
|
seg.intensity = elem[F("ix")] | seg.intensity;
|
||||||
|
seg.palette = elem["pal"] | seg.palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
||||||
|
if (!iarr.isNull()) {
|
||||||
|
strip.setPixelSegment(id);
|
||||||
|
|
||||||
|
//freeze and init to black
|
||||||
|
if (!seg.getOption(SEG_OPTION_FREEZE)) {
|
||||||
|
seg.setOption(SEG_OPTION_FREEZE, true);
|
||||||
|
strip.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t start = 0, stop = 0;
|
||||||
|
byte set = 0; //0 nothing set, 1 start set, 2 range set
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < iarr.size(); i++) {
|
||||||
|
if(iarr[i].is<JsonInteger>()) {
|
||||||
|
if (!set) {
|
||||||
|
start = iarr[i];
|
||||||
|
set = 1;
|
||||||
|
} else {
|
||||||
|
stop = iarr[i];
|
||||||
|
set = 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
JsonArray icol = iarr[i];
|
||||||
|
if (icol.isNull()) break;
|
||||||
|
|
||||||
|
byte sz = icol.size();
|
||||||
|
if (sz == 0 || sz > 4) break;
|
||||||
|
|
||||||
|
int rgbw[] = {0,0,0,0};
|
||||||
|
copyArray(icol, rgbw);
|
||||||
|
|
||||||
|
if (set < 2) stop = start + 1;
|
||||||
|
for (uint16_t i = start; i < stop; i++) {
|
||||||
|
strip.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
||||||
|
}
|
||||||
|
if (!set) start++;
|
||||||
|
set = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strip.setPixelSegment(255);
|
||||||
|
strip.trigger();
|
||||||
|
} else { //return to regular effect
|
||||||
|
seg.setOption(SEG_OPTION_FREEZE, false);
|
||||||
|
}
|
||||||
|
return; // seg.hasChanged(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deserializeState(JsonObject root, byte presetId)
|
bool deserializeState(JsonObject root, byte presetId)
|
||||||
@ -337,6 +340,8 @@ bool deserializeState(JsonObject root, byte presetId)
|
|||||||
if (!playlist.isNull()) {
|
if (!playlist.isNull()) {
|
||||||
loadPlaylist(playlist, presetId);
|
loadPlaylist(playlist, presetId);
|
||||||
noNotification = true; //do not notify both for this request and the first playlist entry
|
noNotification = true; //do not notify both for this request and the first playlist entry
|
||||||
|
} else {
|
||||||
|
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_WS_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||||
|
@ -115,7 +115,7 @@ void colorUpdated(int callMode)
|
|||||||
|
|
||||||
notify(callMode);
|
notify(callMode);
|
||||||
|
|
||||||
//set flag to update blynk and mqtt
|
//set flag to update blynk, ws and mqtt
|
||||||
interfaceUpdateCallMode = callMode;
|
interfaceUpdateCallMode = callMode;
|
||||||
} else {
|
} else {
|
||||||
if (nightlightActive && !nightlightActiveOld &&
|
if (nightlightActive && !nightlightActiveOld &&
|
||||||
@ -180,6 +180,11 @@ void colorUpdated(int callMode)
|
|||||||
void updateInterfaces(uint8_t callMode)
|
void updateInterfaces(uint8_t callMode)
|
||||||
{
|
{
|
||||||
sendDataWs();
|
sendDataWs();
|
||||||
|
if (callMode == NOTIFIER_CALL_MODE_WS_SEND) {
|
||||||
|
lastInterfaceUpdate = millis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_ALEXA
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
|
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
|
||||||
espalexaDevice->setValue(bri);
|
espalexaDevice->setValue(bri);
|
||||||
|
@ -258,6 +258,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
strlcpy(mqttClientID, request->arg(F("MQCID")).c_str(), 41);
|
strlcpy(mqttClientID, request->arg(F("MQCID")).c_str(), 41);
|
||||||
strlcpy(mqttDeviceTopic, request->arg(F("MD")).c_str(), 33);
|
strlcpy(mqttDeviceTopic, request->arg(F("MD")).c_str(), 33);
|
||||||
strlcpy(mqttGroupTopic, request->arg(F("MG")).c_str(), 33);
|
strlcpy(mqttGroupTopic, request->arg(F("MG")).c_str(), 33);
|
||||||
|
buttonPublishMqtt = request->hasArg(F("BM"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_HUESYNC
|
#ifndef WLED_DISABLE_HUESYNC
|
||||||
@ -550,13 +551,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
DEBUG_PRINTLN(req);
|
DEBUG_PRINTLN(req);
|
||||||
|
|
||||||
strip.applyToAllSelected = false;
|
strip.applyToAllSelected = false;
|
||||||
//snapshot to check if request changed values later, temporary.
|
|
||||||
byte prevCol[4] = {col[0], col[1], col[2], col[3]};
|
|
||||||
byte prevColSec[4] = {colSec[0], colSec[1], colSec[2], colSec[3]};
|
|
||||||
byte prevEffect = effectCurrent;
|
|
||||||
byte prevSpeed = effectSpeed;
|
|
||||||
byte prevIntensity = effectIntensity;
|
|
||||||
byte prevPalette = effectPalette;
|
|
||||||
|
|
||||||
//segment select (sets main segment)
|
//segment select (sets main segment)
|
||||||
byte prevMain = strip.getMainSegmentId();
|
byte prevMain = strip.getMainSegmentId();
|
||||||
@ -616,6 +610,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
pos = req.indexOf(F("PL="));
|
pos = req.indexOf(F("PL="));
|
||||||
if (pos > 0) applyPreset(getNumVal(&req, pos));
|
if (pos > 0) applyPreset(getNumVal(&req, pos));
|
||||||
|
|
||||||
|
//snapshot to check if request changed values later, temporary.
|
||||||
|
byte prevCol[4] = {col[0], col[1], col[2], col[3]};
|
||||||
|
byte prevColSec[4] = {colSec[0], colSec[1], colSec[2], colSec[3]};
|
||||||
|
byte prevEffect = effectCurrent;
|
||||||
|
byte prevSpeed = effectSpeed;
|
||||||
|
byte prevIntensity = effectIntensity;
|
||||||
|
byte prevPalette = effectPalette;
|
||||||
|
|
||||||
//set brightness
|
//set brightness
|
||||||
updateVal(&req, "&A=", &bri);
|
updateVal(&req, "&A=", &bri);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2107021
|
#define VERSION 2107031
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -438,6 +438,7 @@ 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
|
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
|
||||||
|
|
||||||
// button
|
// button
|
||||||
|
WLED_GLOBAL bool buttonPublishMqtt _INIT(false);
|
||||||
WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
|
WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
|
||||||
WLED_GLOBAL bool buttonLongPressed[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 buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
|
||||||
|
@ -40,7 +40,8 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
}
|
}
|
||||||
verboseResponse = deserializeState(root);
|
verboseResponse = deserializeState(root);
|
||||||
}
|
}
|
||||||
if (verboseResponse || millis() - lastInterfaceUpdate < 1900) sendDataWs(client); //update if it takes longer than 100ms until next "broadcast"
|
//update if it takes longer than 300ms until next "broadcast"
|
||||||
|
if (verboseResponse && (millis() - lastInterfaceUpdate < 1700 || !interfaceUpdateCallMode)) sendDataWs(client);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//message is comprised of multiple frames or the frame is split into multiple packets
|
//message is comprised of multiple frames or the frame is split into multiple packets
|
||||||
|
@ -474,6 +474,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappends('s',SET_F("MQCID"),mqttClientID);
|
sappends('s',SET_F("MQCID"),mqttClientID);
|
||||||
sappends('s',SET_F("MD"),mqttDeviceTopic);
|
sappends('s',SET_F("MD"),mqttDeviceTopic);
|
||||||
sappends('s',SET_F("MG"),mqttGroupTopic);
|
sappends('s',SET_F("MG"),mqttGroupTopic);
|
||||||
|
sappend('c',SET_F("BM"),buttonPublishMqtt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_HUESYNC
|
#ifndef WLED_DISABLE_HUESYNC
|
||||||
|
Loading…
Reference in New Issue
Block a user