mirror of
https://github.com/wled/WLED.git
synced 2025-09-17 09:08:55 +00:00
Compare commits
79 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a371239172 | ||
![]() |
4fd904fbcc | ||
![]() |
b73a257389 | ||
![]() |
9e70d6b3e1 | ||
![]() |
9caca37ab1 | ||
![]() |
6e76fc0aa7 | ||
![]() |
6171883758 | ||
![]() |
942b68c948 | ||
![]() |
9ca7ffa5a3 | ||
![]() |
d1ce23c5ac | ||
![]() |
b7b6d0a6bc | ||
![]() |
10c51eea2c | ||
![]() |
48d20c02a1 | ||
![]() |
c5cc0b3f2b | ||
![]() |
6ebef8846c | ||
![]() |
5d1993935e | ||
![]() |
caab8943cb | ||
![]() |
f5c05b24fb | ||
![]() |
940a0d006d | ||
![]() |
8fe67a04d8 | ||
![]() |
bec745d095 | ||
![]() |
223fd35138 | ||
![]() |
d3fc0309c0 | ||
![]() |
830223f6e2 | ||
![]() |
eb53c52499 | ||
![]() |
96c9e2b4d6 | ||
![]() |
c34b948bad | ||
![]() |
9ac609f846 | ||
![]() |
6aa47bfd1b | ||
![]() |
ff46e6ea86 | ||
![]() |
5489c74986 | ||
![]() |
f6f8151150 | ||
![]() |
a20d577f6c | ||
![]() |
c4c2494dd1 | ||
![]() |
c9c294a1d5 | ||
![]() |
6359a8a8a2 | ||
![]() |
f9b44381bd | ||
![]() |
eb1ccb600b | ||
![]() |
b2db61aa03 | ||
![]() |
ee55a574de | ||
![]() |
0998fd32cd | ||
![]() |
686f2c4aa6 | ||
![]() |
cd234673ea | ||
![]() |
54d7a81f16 | ||
![]() |
9d8d2c0aa1 | ||
![]() |
17ce6b9507 | ||
![]() |
296065a976 | ||
![]() |
0b0f600f97 | ||
![]() |
f1371d6737 | ||
![]() |
03a33790e1 | ||
![]() |
c0816c80ae | ||
![]() |
071ebe6ef2 | ||
![]() |
2126e42743 | ||
![]() |
8a2b34adb4 | ||
![]() |
93eb4d21bf | ||
![]() |
868cedeed2 | ||
![]() |
5c794f428a | ||
![]() |
612d6f85bd | ||
![]() |
e5cef6b877 | ||
![]() |
f2a63c04a8 | ||
![]() |
5a5064e070 | ||
![]() |
478fa3132c | ||
![]() |
a84859c211 | ||
![]() |
67013bd58f | ||
![]() |
b51be31d8a | ||
![]() |
a3bef49124 | ||
![]() |
a5cf553f17 | ||
![]() |
640188f4e2 | ||
![]() |
48265bbe02 | ||
![]() |
6aaf544079 | ||
![]() |
9904c10984 | ||
![]() |
81c810eba4 | ||
![]() |
5e6b1e8175 | ||
![]() |
48c165b0b4 | ||
![]() |
042605701e | ||
![]() |
32cf1495d3 | ||
![]() |
9577e49231 | ||
![]() |
de19839145 | ||
![]() |
f970780d6c |
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.vscode
|
||||
!.vscode/extensions.json
|
35
.travis.yml
Normal file
35
.travis.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
# Continuous Integration (CI) is the practice, in software
|
||||
# engineering, of merging all developer working copies with a shared mainline
|
||||
# several times a day < https://docs.platformio.org/page/ci/index.html >
|
||||
#
|
||||
# Documentation:
|
||||
#
|
||||
# * Travis CI Embedded Builds with PlatformIO
|
||||
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||
#
|
||||
# * PlatformIO integration with Travis CI
|
||||
# < https://docs.platformio.org/page/ci/travis.html >
|
||||
#
|
||||
# * User Guide for `platformio ci` command
|
||||
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||
#
|
||||
#
|
||||
# Please choose one of the following templates (proposed below) and uncomment
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
env:
|
||||
- PLATFORMIO_CI_SRC=wled00
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- platformio update
|
||||
script:
|
||||
- platformio ci --project-conf=./platformio.ini -v
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
39
include/README
Normal file
39
include/README
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
Normal file
46
lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
126
platformio.ini
Normal file
126
platformio.ini
Normal file
@@ -0,0 +1,126 @@
|
||||
; PlatformIO Project Configuration File
|
||||
; Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
src_dir = ./wled00
|
||||
data_dir = ./wled00/data
|
||||
lib_extra_dirs = ./wled00/src
|
||||
env_default = nodemcuv2
|
||||
; env_default = esp01
|
||||
; env_default = esp01_1m
|
||||
; env_default = d1_mini
|
||||
; env_default = esp32dev
|
||||
|
||||
|
||||
[common]
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
board_build.flash_mode = dout
|
||||
upload_speed = 921600
|
||||
build_flags =
|
||||
; -D VERSION=0.8.2
|
||||
; -D DEBUG
|
||||
# TODO replace libs in /lib with managed libs in here if possible.
|
||||
# If they are not changed it's just a matter of setting the correct version and change the import statement
|
||||
lib_deps_external =
|
||||
#Blynk@0.5.4
|
||||
#E131@1.0.0
|
||||
#webserver
|
||||
FastLED@3.2.1
|
||||
NeoPixelBus@2.4.1
|
||||
#PubSubClient@2.7
|
||||
#Time@1.5
|
||||
#Timezone@1.2.1
|
||||
#WS2812FX@1.1.2
|
||||
|
||||
[common:esp8266]
|
||||
platform = espressif8266@1.8.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
|
||||
[common:esp8266_512k]
|
||||
platform = espressif8266@1.7.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; -D WLED_DISABLE_MOBILE_UI
|
||||
-D WLED_DISABLE_OTA
|
||||
-D WLED_DISABLE_ALEXA
|
||||
; -D WLED_DISABLE_BLYNK
|
||||
; -D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
|
||||
[common:esp32]
|
||||
platform = espressif32@1.5.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
-D ARDUINO_ARCH_ESP32
|
||||
-D WORKAROUND_ESP32_BITBANG
|
||||
|
||||
|
||||
# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html
|
||||
[env:nodemcuv2]
|
||||
board = nodemcuv2
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
IRremoteESP8266@2.5.3
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
IRremoteESP8266@2.5.3
|
||||
|
||||
[env:esp01_1m]
|
||||
board = esp01_1m
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
# disable IR because there is no pin for it
|
||||
-D WLED_DISABLE_INFRARED
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
[env:esp01]
|
||||
board = esp01
|
||||
platform = ${common:esp8266_512k.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_512k.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
# see: http://docs.platformio.org/en/latest/platforms/espressif32.html
|
||||
[env:esp32dev]
|
||||
board = esp32dev
|
||||
platform = ${common:esp32.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp32.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
26
readme.md
26
readme.md
@@ -1,11 +1,16 @@
|
||||

|
||||

|
||||
|
||||
## Welcome to my project WLED! (v0.8.0)
|
||||
[](https://github.com/Aircoookie/WLED/releases)
|
||||
[](https://discord.gg/KuqP7NE)
|
||||
[](https://github.com/Aircoookie/WLED/wiki)
|
||||
[](https://github.com/Aircoookie/WLED-App)
|
||||
|
||||
## Welcome to my project WLED!
|
||||
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs!
|
||||
|
||||
### Features:
|
||||
- WS2812FX library integrated for over 70 special effects
|
||||
- WS2812FX library integrated for 80 special effects
|
||||
- FastLED noise effects and palettes
|
||||
- Customizable Mobile and desktop UI with color and effect controls
|
||||
- Settings page - configuration over network
|
||||
@@ -16,18 +21,21 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
- Nightlight function (gradually dims down)
|
||||
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
||||
- Configurable analog clock + support for the Cronixie kit by Diamex
|
||||
- Configurable Auto Brightness limit for safer operation
|
||||
|
||||
### Supported light control interfaces:
|
||||
- WLED Android app
|
||||
- HTTP request API
|
||||
- Blynk IoT
|
||||
- MQTT
|
||||
- E1.31
|
||||
- Hyperion
|
||||
- UDP realtime
|
||||
- Alexa smart device (including dimming)
|
||||
- Alexa voice control (including dimming and color)
|
||||
- Sync to Philips hue lights
|
||||
- Adalight (PC ambilight via serial)
|
||||
- Sync color of multiple WLED devices (UDP notifier)
|
||||
- Infrared remotes (24-key RGB, receiver required)
|
||||
- Simple timers/schedules (time from NTP, timezones/DST supported)
|
||||
|
||||
### Quick start guide and documentation:
|
||||
@@ -37,16 +45,10 @@ See the [wiki](https://github.com/Aircoookie/WLED/wiki)!
|
||||
### Other
|
||||
|
||||
Licensed under the MIT license
|
||||
Credits in About page!
|
||||
Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)!
|
||||
|
||||
Uses Linearicons by Perxis!
|
||||
|
||||
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
|
||||
If you insist that you just love WLED too much, you can [send me a gift](https://paypal.me/aircoookie)!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
If WLED really brightens up your every day, you can [](https://paypal.me/aircoookie)
|
||||
|
11
test/README
Normal file
11
test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
@@ -5,32 +5,39 @@
|
||||
//#define WORKAROUND_ESP32_BITBANG
|
||||
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
|
||||
|
||||
#define LEDPIN 2 //strip pin. Only effective for ESP32, ESP8266 must use gpio2
|
||||
//PIN CONFIGURATION
|
||||
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266
|
||||
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
|
||||
#define IR_PIN 4 //infrared pin.
|
||||
#define AUXPIN 15 //unused auxiliary output pin
|
||||
|
||||
|
||||
//uncomment this if red and green are swapped
|
||||
//#define SWAPRG
|
||||
|
||||
//automatically uses the right driver method for each platform
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method
|
||||
#endif
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
#define PIXELMETHOD NeoEsp32BitBangWs2813Method
|
||||
#pragma message "Software BitBang is used because of your NeoPixelBus version. Look in NpbWrapper.h for instructions on how to mitigate flickering."
|
||||
#else
|
||||
#define PIXELMETHOD NeoWs2813Method
|
||||
#endif
|
||||
#else //esp8266
|
||||
//you may change to DMA method on pin GPIO3 here
|
||||
#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod
|
||||
//#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod
|
||||
//autoselect the right method depending on strip pin
|
||||
#if LEDPIN == 2
|
||||
#define PIXELMETHOD NeoEsp8266UartWs2813Method //if you get an error here, try to change to NeoEsp8266Uart1Ws2813Method or use Neopixelbus v2.3.5
|
||||
#elif LEDPIN == 3
|
||||
#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp8266BitBang800KbpsMethod
|
||||
#pragma message "Software BitBang will be used because of your selected LED pin. This may cause flicker. Use GPIO 2 or 3 for best results."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//handle swapping Red and Green automatically
|
||||
#ifdef SWAPRG
|
||||
#define PIXELFEATURE3 NeoRgbFeature
|
||||
#define PIXELFEATURE4 NeoRgbwFeature
|
||||
#else
|
||||
|
||||
//you can now change the color order in the web settings
|
||||
#define PIXELFEATURE3 NeoGrbFeature
|
||||
#define PIXELFEATURE4 NeoGrbwFeature
|
||||
#endif
|
||||
|
||||
|
||||
#include <NeoPixelBrightnessBus.h>
|
||||
|
||||
@@ -46,10 +53,10 @@ class NeoPixelWrapper
|
||||
{
|
||||
public:
|
||||
NeoPixelWrapper() :
|
||||
// initialize each member to null
|
||||
_pGrb(NULL),
|
||||
_pGrbw(NULL),
|
||||
_type(NeoPixelType_None)
|
||||
// initialize each member to null
|
||||
_pGrb(NULL),
|
||||
_pGrbw(NULL),
|
||||
_type(NeoPixelType_None)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -64,8 +71,8 @@ public:
|
||||
cleanup();
|
||||
_type = type;
|
||||
|
||||
switch (_type) {
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb:
|
||||
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
|
||||
_pGrb->Begin();
|
||||
@@ -81,23 +88,25 @@ public:
|
||||
void Show()
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
delay(1);
|
||||
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
|
||||
#endif
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
delay(1);
|
||||
portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
switch (_type) {
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb: _pGrb->Show(); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->Show(); break;
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
portENABLE_INTERRUPTS();
|
||||
#endif
|
||||
#ifdef WORKAROUND_ESP32_BITBANG
|
||||
portENABLE_INTERRUPTS();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CanShow() const
|
||||
{
|
||||
switch (_type) {
|
||||
@@ -106,65 +115,65 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColor(uint16_t indexPixel, RgbColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
}
|
||||
void SetPixelColor(uint16_t indexPixel, RgbColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColor(uint16_t indexPixel, RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
}
|
||||
void SetPixelColor(uint16_t indexPixel, RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetBrightness(byte b)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetBrightness(b); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break;
|
||||
}
|
||||
void SetBrightness(byte b)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetBrightness(b); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break;
|
||||
}
|
||||
}
|
||||
|
||||
RgbColor GetPixelColor(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break;
|
||||
}
|
||||
return 0;
|
||||
RgbColor GetPixelColor(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: Due to feature differences, some support RGBW but the method name
|
||||
// here needs to be unique, thus GetPixeColorRgbw
|
||||
RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break;
|
||||
}
|
||||
return 0;
|
||||
// NOTE: Due to feature differences, some support RGBW but the method name
|
||||
// here needs to be unique, thus GetPixeColorRgbw
|
||||
RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClearTo(RgbColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->ClearTo(color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
}
|
||||
void ClearTo(RgbColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->ClearTo(color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearTo(RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
}
|
||||
void ClearTo(RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
NeoPixelType _type;
|
||||
|
1694
wled00/WS2812FX.cpp
1694
wled00/WS2812FX.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,7 @@
|
||||
//pixelmethod now in NpbWrapper.h
|
||||
|
||||
/*
|
||||
WS2812FX.h - Library for WS2812 LED effects.
|
||||
Harm Aldick - 2016
|
||||
www.aldick.org
|
||||
FEATURES
|
||||
* A lot of blinken modes and counting
|
||||
* WS2812FX can be used as drop-in replacement for Adafruit NeoPixel Library
|
||||
NOTES
|
||||
* Uses the Adafruit NeoPixel library. Get it here:
|
||||
https://github.com/adafruit/Adafruit_NeoPixel
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Harm Aldick
|
||||
@@ -28,11 +20,7 @@
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
CHANGELOG
|
||||
2016-05-28 Initial beta release
|
||||
2016-06-03 Code cleanup, minor improvements, new modes
|
||||
2016-06-04 2 new fx, fixed setColor (now also resets _mode_color)
|
||||
2017-02-02 added external trigger functionality (e.g. for sound-to-light)
|
||||
|
||||
Modified for WLED
|
||||
*/
|
||||
|
||||
@@ -41,9 +29,12 @@
|
||||
|
||||
#include "NpbWrapper.h"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS (uint8_t)50
|
||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||
#include "FastLED.h"
|
||||
|
||||
#define DEFAULT_BRIGHTNESS (uint8_t)127
|
||||
#define DEFAULT_MODE (uint8_t)0
|
||||
#define DEFAULT_SPEED (uint16_t)1000
|
||||
#define DEFAULT_SPEED (uint8_t)128
|
||||
#define DEFAULT_COLOR (uint32_t)0xFF0000
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -82,7 +73,7 @@
|
||||
#define REVERSE (uint8_t)0x80
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE)
|
||||
|
||||
#define MODE_COUNT 74
|
||||
#define MODE_COUNT 80
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
@@ -100,10 +91,10 @@
|
||||
#define FX_MODE_THEATER_CHASE 13
|
||||
#define FX_MODE_THEATER_CHASE_RAINBOW 14
|
||||
#define FX_MODE_RUNNING_LIGHTS 15
|
||||
#define FX_MODE_TWINKLE 16
|
||||
#define FX_MODE_TWINKLE_RANDOM 17
|
||||
#define FX_MODE_TWINKLE_FADE 18
|
||||
#define FX_MODE_TWINKLE_FADE_RANDOM 19
|
||||
#define FX_MODE_SAW 16
|
||||
#define FX_MODE_TWINKLE 17
|
||||
#define FX_MODE_DISSOLVE 18
|
||||
#define FX_MODE_DISSOLVE_RANDOM 19
|
||||
#define FX_MODE_SPARKLE 20
|
||||
#define FX_MODE_FLASH_SPARKLE 21
|
||||
#define FX_MODE_HYPER_SPARKLE 22
|
||||
@@ -127,7 +118,7 @@
|
||||
#define FX_MODE_LARSON_SCANNER 40
|
||||
#define FX_MODE_COMET 41
|
||||
#define FX_MODE_FIREWORKS 42
|
||||
#define FX_MODE_FIREWORKS_RANDOM 43
|
||||
#define FX_MODE_RAIN 43
|
||||
#define FX_MODE_MERRY_CHRISTMAS 44
|
||||
#define FX_MODE_FIRE_FLICKER 45
|
||||
#define FX_MODE_GRADIENT 46
|
||||
@@ -159,6 +150,13 @@
|
||||
#define FX_MODE_NOISE16_2 71
|
||||
#define FX_MODE_NOISE16_3 72
|
||||
#define FX_MODE_NOISE16_4 73
|
||||
#define FX_MODE_COLORTWINKLE 74
|
||||
#define FX_MODE_LAKE 75
|
||||
#define FX_MODE_METEOR 76
|
||||
#define FX_MODE_METEOR_SMOOTH 77
|
||||
#define FX_MODE_RAILWAY 78
|
||||
#define FX_MODE_RIPPLE 79
|
||||
|
||||
|
||||
class WS2812FX {
|
||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||
@@ -201,10 +199,10 @@ class WS2812FX {
|
||||
_mode[FX_MODE_FADE] = &WS2812FX::mode_fade;
|
||||
_mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase;
|
||||
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
|
||||
_mode[FX_MODE_SAW] = &WS2812FX::mode_saw;
|
||||
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
|
||||
_mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random;
|
||||
_mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade;
|
||||
_mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random;
|
||||
_mode[FX_MODE_DISSOLVE] = &WS2812FX::mode_dissolve;
|
||||
_mode[FX_MODE_DISSOLVE_RANDOM] = &WS2812FX::mode_dissolve_random;
|
||||
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
|
||||
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
|
||||
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
|
||||
@@ -228,7 +226,7 @@ class WS2812FX {
|
||||
_mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner;
|
||||
_mode[FX_MODE_COMET] = &WS2812FX::mode_comet;
|
||||
_mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks;
|
||||
_mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random;
|
||||
_mode[FX_MODE_RAIN] = &WS2812FX::mode_rain;
|
||||
_mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas;
|
||||
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
|
||||
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient;
|
||||
@@ -261,19 +259,30 @@ class WS2812FX {
|
||||
_mode[FX_MODE_NOISE16_2] = &WS2812FX::mode_noise16_2;
|
||||
_mode[FX_MODE_NOISE16_3] = &WS2812FX::mode_noise16_3;
|
||||
_mode[FX_MODE_NOISE16_4] = &WS2812FX::mode_noise16_4;
|
||||
_mode[FX_MODE_COLORTWINKLE] = &WS2812FX::mode_colortwinkle;
|
||||
_mode[FX_MODE_LAKE] = &WS2812FX::mode_lake;
|
||||
_mode[FX_MODE_METEOR] = &WS2812FX::mode_meteor;
|
||||
_mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth;
|
||||
_mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway;
|
||||
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
_running = false;
|
||||
_num_segments = 1;
|
||||
_segments[0].mode = DEFAULT_MODE;
|
||||
_segments[0].colors[0] = DEFAULT_COLOR;
|
||||
_segments[0].start = 0;
|
||||
_segments[0].speed = DEFAULT_SPEED;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
targetPalette = CloudColors_p;
|
||||
_reverseMode = false;
|
||||
_skipFirstMode = false;
|
||||
colorOrder = 0;
|
||||
paletteFade = 0;
|
||||
paletteBlend = 0;
|
||||
ablMilliampsMax = 750;
|
||||
currentMilliamps = 0;
|
||||
_locked = NULL;
|
||||
_modeUsesLock = false;
|
||||
_cronixieDigits = new byte[6];
|
||||
bus = new NeoPixelWrapper();
|
||||
RESET_RUNTIME;
|
||||
@@ -282,8 +291,7 @@ class WS2812FX {
|
||||
void
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirst),
|
||||
service(void),
|
||||
clear(void),
|
||||
strip_off(void),
|
||||
blur(uint8_t),
|
||||
fade_out(uint8_t r),
|
||||
setMode(uint8_t m),
|
||||
setSpeed(uint8_t s),
|
||||
@@ -316,9 +324,13 @@ class WS2812FX {
|
||||
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
show(void);
|
||||
|
||||
bool
|
||||
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p);
|
||||
|
||||
uint8_t
|
||||
paletteFade,
|
||||
paletteBlend,
|
||||
colorOrder,
|
||||
getBrightness(void),
|
||||
getMode(void),
|
||||
getSpeed(void),
|
||||
@@ -327,14 +339,11 @@ class WS2812FX {
|
||||
|
||||
uint32_t
|
||||
color_wheel(uint8_t),
|
||||
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
|
||||
color_blend(uint32_t,uint32_t,uint8_t),
|
||||
getPixelColor(uint16_t),
|
||||
getColor(void);
|
||||
|
||||
double
|
||||
getPowerEstimate(uint16_t leds, uint32_t c, byte b),
|
||||
getSafePowerMultiplier(double safeMilliAmps, uint16_t leds, uint32_t c, byte b);
|
||||
|
||||
WS2812FX::Segment
|
||||
getSegment(void);
|
||||
|
||||
@@ -346,15 +355,18 @@ class WS2812FX {
|
||||
|
||||
// mode helper functions
|
||||
uint16_t
|
||||
blink(uint32_t, uint32_t, bool strobe),
|
||||
color_wipe(uint32_t, uint32_t, bool),
|
||||
theater_chase(uint32_t, uint32_t),
|
||||
twinkle(uint32_t),
|
||||
twinkle_fade(uint32_t),
|
||||
chase(uint32_t, uint32_t, uint32_t),
|
||||
ablMilliampsMax,
|
||||
currentMilliamps,
|
||||
blink(uint32_t, uint32_t, bool strobe, bool),
|
||||
color_wipe(uint32_t, uint32_t, bool , bool),
|
||||
scan(bool),
|
||||
theater_chase(uint32_t, uint32_t, bool),
|
||||
running_base(bool),
|
||||
dissolve(uint32_t),
|
||||
chase(uint32_t, uint32_t, uint32_t, bool),
|
||||
gradient_base(bool),
|
||||
running(uint32_t, uint32_t),
|
||||
fireworks(uint32_t),
|
||||
tricolor_chase(uint32_t, uint32_t, uint32_t);
|
||||
tricolor_chase(uint32_t, uint32_t);
|
||||
|
||||
// builtin modes
|
||||
uint16_t
|
||||
@@ -378,10 +390,10 @@ class WS2812FX {
|
||||
mode_rainbow(void),
|
||||
mode_rainbow_cycle(void),
|
||||
mode_running_lights(void),
|
||||
mode_saw(void),
|
||||
mode_twinkle(void),
|
||||
mode_twinkle_random(void),
|
||||
mode_twinkle_fade(void),
|
||||
mode_twinkle_fade_random(void),
|
||||
mode_dissolve(void),
|
||||
mode_dissolve_random(void),
|
||||
mode_sparkle(void),
|
||||
mode_flash_sparkle(void),
|
||||
mode_hyper_sparkle(void),
|
||||
@@ -401,7 +413,7 @@ class WS2812FX {
|
||||
mode_larson_scanner(void),
|
||||
mode_comet(void),
|
||||
mode_fireworks(void),
|
||||
mode_fireworks_random(void),
|
||||
mode_rain(void),
|
||||
mode_merry_christmas(void),
|
||||
mode_halloween(void),
|
||||
mode_fire_flicker(void),
|
||||
@@ -416,6 +428,7 @@ class WS2812FX {
|
||||
mode_tricolor_chase(void),
|
||||
mode_tricolor_wipe(void),
|
||||
mode_tricolor_fade(void),
|
||||
mode_lightning(void),
|
||||
mode_icu(void),
|
||||
mode_multi_comet(void),
|
||||
mode_dual_larson_scanner(void),
|
||||
@@ -432,22 +445,30 @@ class WS2812FX {
|
||||
mode_noise16_2(void),
|
||||
mode_noise16_3(void),
|
||||
mode_noise16_4(void),
|
||||
mode_lightning(void);
|
||||
mode_colortwinkle(void),
|
||||
mode_lake(void),
|
||||
mode_meteor(void),
|
||||
mode_meteor_smooth(void),
|
||||
mode_railway(void),
|
||||
mode_ripple(void);
|
||||
|
||||
private:
|
||||
NeoPixelWrapper *bus;
|
||||
|
||||
CRGB fastled_from_col(uint32_t);
|
||||
CRGBPalette16 currentPalette;
|
||||
CRGBPalette16 targetPalette;
|
||||
|
||||
uint16_t _length;
|
||||
uint16_t _rand16seed;
|
||||
uint8_t _brightness;
|
||||
|
||||
void handle_palette(void);
|
||||
void fill(uint32_t);
|
||||
bool modeUsesLock(uint8_t);
|
||||
|
||||
double
|
||||
_cronixieSecMultiplier;
|
||||
|
||||
boolean
|
||||
_running,
|
||||
bool
|
||||
_modeUsesLock,
|
||||
_rgbwMode,
|
||||
_reverseMode,
|
||||
_cronixieMode,
|
||||
@@ -466,11 +487,146 @@ class WS2812FX {
|
||||
uint8_t _segment_index = 0;
|
||||
uint8_t _segment_index_palette_last = 99;
|
||||
uint8_t _num_segments = 1;
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element
|
||||
// start, stop, speed, intensity, mode, options, color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}}
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element
|
||||
// start, stop, speed, intensity, palette, mode, options, color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, 0, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}}
|
||||
};
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 17 bytes per element
|
||||
};
|
||||
|
||||
|
||||
const char JSON_mode_names[] PROGMEM = R"=====({"effects":[
|
||||
"Solid",
|
||||
"Blink",
|
||||
"Breathe",
|
||||
"Wipe",
|
||||
"Wipe Random",
|
||||
"Random Colors",
|
||||
"Sweep",
|
||||
"Dynamic",
|
||||
"Colorloop",
|
||||
"Rainbow",
|
||||
"Scan",
|
||||
"Dual Scan",
|
||||
"Fade",
|
||||
"Chase",
|
||||
"Chase Rainbow",
|
||||
"Running",
|
||||
"Saw",
|
||||
"Twinkle",
|
||||
"Dissolve",
|
||||
"Dissolve Rnd",
|
||||
"Sparkle",
|
||||
"Dark Sparkle",
|
||||
"Sparkle+",
|
||||
"Strobe",
|
||||
"Strobe Rainbow",
|
||||
"Mega Strobe",
|
||||
"Blink Rainbow",
|
||||
"Android",
|
||||
"Chase",
|
||||
"Chase Random",
|
||||
"Chase Rainbow",
|
||||
"Chase Flash",
|
||||
"Chase Flash Rnd",
|
||||
"Rainbow Runner",
|
||||
"Colorful",
|
||||
"Traffic Light",
|
||||
"Sweep Random",
|
||||
"Running 2",
|
||||
"Red & Blue",
|
||||
"Stream",
|
||||
"Scanner",
|
||||
"Lighthouse",
|
||||
"Fireworks",
|
||||
"Rain",
|
||||
"Merry Christmas",
|
||||
"Fire Flicker",
|
||||
"Gradient",
|
||||
"Loading",
|
||||
"In Out",
|
||||
"In In",
|
||||
"Out Out",
|
||||
"Out In",
|
||||
"Circus",
|
||||
"Halloween",
|
||||
"Tri Chase",
|
||||
"Tri Wipe",
|
||||
"Tri Fade",
|
||||
"Lightning",
|
||||
"ICU",
|
||||
"Multi Comet",
|
||||
"Dual Scanner",
|
||||
"Stream 2",
|
||||
"Oscillate",
|
||||
"Pride 2015",
|
||||
"Juggle",
|
||||
"Palette",
|
||||
"Fire 2012",
|
||||
"Colorwaves",
|
||||
"BPM",
|
||||
"Fill Noise",
|
||||
"Noise 1",
|
||||
"Noise 2",
|
||||
"Noise 3",
|
||||
"Noise 4",
|
||||
"Colortwinkle",
|
||||
"Lake",
|
||||
"Meteor",
|
||||
"Smooth Meteor",
|
||||
"Railway",
|
||||
"Ripple"
|
||||
]})=====";
|
||||
|
||||
|
||||
const char JSON_palette_names[] PROGMEM = R"=====({"palettes":[
|
||||
"Default",
|
||||
"Random Cycle",
|
||||
"Primary Color",
|
||||
"Based on Primary",
|
||||
"Set Colors",
|
||||
"Based on Set",
|
||||
"Party",
|
||||
"Cloud",
|
||||
"Lava",
|
||||
"Ocean",
|
||||
"Forest",
|
||||
"Rainbow",
|
||||
"Rainbow Bands",
|
||||
"Sunset",
|
||||
"Rivendell",
|
||||
"Breeze",
|
||||
"Red & Blue",
|
||||
"Yellowout",
|
||||
"Analogous",
|
||||
"Splash",
|
||||
"Pastel",
|
||||
"Sunset 2",
|
||||
"Beech",
|
||||
"Vintage",
|
||||
"Departure",
|
||||
"Landscape",
|
||||
"Beach",
|
||||
"Sherbet",
|
||||
"Hult",
|
||||
"Hult 64",
|
||||
"Drywet",
|
||||
"Jul",
|
||||
"Grintage",
|
||||
"Rewhi",
|
||||
"Tertiary",
|
||||
"Fire",
|
||||
"Icefire",
|
||||
"Cyane",
|
||||
"Light Pink",
|
||||
"Autumn",
|
||||
"Magenta",
|
||||
"Magred",
|
||||
"Yelmag",
|
||||
"Yelblu",
|
||||
"Orange & Teal",
|
||||
"Tiamat",
|
||||
"April Night"
|
||||
]})=====";
|
||||
|
||||
#endif
|
||||
|
717
wled00/WS2812FX_fcn.cpp
Normal file
717
wled00/WS2812FX_fcn.cpp
Normal file
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
WS2812FX_fcn.cpp contains all utility functions
|
||||
Harm Aldick - 2016
|
||||
www.aldick.org
|
||||
LICENSE
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Harm Aldick
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Modified heavily for WLED
|
||||
*/
|
||||
|
||||
#include "WS2812FX.h"
|
||||
#include "palettes.h"
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
|
||||
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
|
||||
{
|
||||
if (supportWhite == _rgbwMode && countPixels == _length && _locked != NULL) return;
|
||||
RESET_RUNTIME;
|
||||
_rgbwMode = supportWhite;
|
||||
_skipFirstMode = skipFirst;
|
||||
_length = countPixels;
|
||||
|
||||
uint8_t ty = 1;
|
||||
if (supportWhite) ty =2;
|
||||
uint16_t lengthRaw = _length;
|
||||
if (_skipFirstMode) lengthRaw += LED_SKIP_AMOUNT;
|
||||
bus->Begin((NeoPixelType)ty, lengthRaw);
|
||||
|
||||
if (_locked != NULL) delete _locked;
|
||||
_locked = new byte[_length];
|
||||
|
||||
_segments[0].start = 0;
|
||||
_segments[0].stop = _length -1;
|
||||
|
||||
unlockAll();
|
||||
setBrightness(_brightness);
|
||||
}
|
||||
|
||||
void WS2812FX::service() {
|
||||
unsigned long now = millis(); // Be aware, millis() rolls over every 49 days
|
||||
bool doShow = false;
|
||||
for(uint8_t i=0; i < _num_segments; i++)
|
||||
{
|
||||
_segment_index = i;
|
||||
if(now > SEGMENT_RUNTIME.next_time || _triggered)
|
||||
{
|
||||
doShow = true;
|
||||
handle_palette();
|
||||
uint16_t delay = (this->*_mode[SEGMENT.mode])();
|
||||
SEGMENT_RUNTIME.next_time = now + max(delay, 5);
|
||||
SEGMENT_RUNTIME.counter_mode_call++;
|
||||
}
|
||||
}
|
||||
if(doShow) {
|
||||
show();
|
||||
}
|
||||
_triggered = false;
|
||||
}
|
||||
|
||||
bool WS2812FX::modeUsesLock(uint8_t m)
|
||||
{
|
||||
if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE ||
|
||||
m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH ||
|
||||
m == FX_MODE_RIPPLE) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
||||
uint8_t w = (c >> 24) & 0xFF;
|
||||
uint8_t r = (c >> 16) & 0xFF;
|
||||
uint8_t g = (c >> 8) & 0xFF;
|
||||
uint8_t b = c & 0xFF;
|
||||
setPixelColor(n, r, g, b, w);
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
if (_locked[i] && !_modeUsesLock) return;
|
||||
if (_reverseMode) i = _length - 1 -i;
|
||||
if (IS_REVERSE) i = SEGMENT.stop - (i - SEGMENT.start); //reverse just individual segment
|
||||
byte tmpg = g;
|
||||
switch (colorOrder) //0 = Grb, default
|
||||
{
|
||||
case 0: break; //0 = Grb, default
|
||||
case 1: g = r; r = tmpg; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = b; b = tmpg; break; //2 = Brg
|
||||
case 3: g = b; b = r; r = tmpg; //3 = Rbg
|
||||
}
|
||||
if (!_cronixieMode)
|
||||
{
|
||||
if (_skipFirstMode)
|
||||
{
|
||||
if (i < LED_SKIP_AMOUNT) bus->SetPixelColor(i, RgbwColor(0,0,0,0));
|
||||
i += LED_SKIP_AMOUNT;
|
||||
}
|
||||
|
||||
bus->SetPixelColor(i, RgbwColor(r,g,b,w));
|
||||
} else {
|
||||
if(i>6)return;
|
||||
byte o = 10*i;
|
||||
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
|
||||
{
|
||||
byte r2 = (_segments[0].colors[1] >>16) & 0xFF;
|
||||
byte g2 = (_segments[0].colors[1] >> 8) & 0xFF;
|
||||
byte b2 = (_segments[0].colors[1] ) & 0xFF;
|
||||
byte w2 = (_segments[0].colors[1] >>24) & 0xFF;
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(r2,g2,b2,w2));
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(0,0,0,0));
|
||||
}
|
||||
}
|
||||
if (_skipFirstMode) o += LED_SKIP_AMOUNT;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: bus->SetPixelColor(o+5, RgbwColor(r,g,b,w)); break;
|
||||
case 1: bus->SetPixelColor(o+0, RgbwColor(r,g,b,w)); break;
|
||||
case 2: bus->SetPixelColor(o+6, RgbwColor(r,g,b,w)); break;
|
||||
case 3: bus->SetPixelColor(o+1, RgbwColor(r,g,b,w)); break;
|
||||
case 4: bus->SetPixelColor(o+7, RgbwColor(r,g,b,w)); break;
|
||||
case 5: bus->SetPixelColor(o+2, RgbwColor(r,g,b,w)); break;
|
||||
case 6: bus->SetPixelColor(o+8, RgbwColor(r,g,b,w)); break;
|
||||
case 7: bus->SetPixelColor(o+3, RgbwColor(r,g,b,w)); break;
|
||||
case 8: bus->SetPixelColor(o+9, RgbwColor(r,g,b,w)); break;
|
||||
case 9: bus->SetPixelColor(o+4, RgbwColor(r,g,b,w)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setReverseMode(bool b)
|
||||
{
|
||||
_reverseMode = b;
|
||||
}
|
||||
|
||||
void WS2812FX::driverModeCronixie(bool b)
|
||||
{
|
||||
_cronixieMode = b;
|
||||
_segments[0].stop = (b) ? 5 : _length-1;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieBacklight(bool b)
|
||||
{
|
||||
_cronixieBacklightEnabled = b;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieDigits(byte d[])
|
||||
{
|
||||
for (int i = 0; i<6; i++)
|
||||
{
|
||||
_cronixieDigits[i] = d[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//DISCLAIMER
|
||||
//The following function attemps to calculate the current LED power usage,
|
||||
//and will limit the brightness to stay below a set amperage threshold.
|
||||
//It is NOT a measurement and NOT guaranteed to stay within the ablMilliampsMax margin.
|
||||
//Stay safe with high amperage and have a reasonable safety margin!
|
||||
//I am NOT to be held liable for burned down garages!
|
||||
|
||||
//fine tune power estimation constants for your setup
|
||||
#define PU_PER_MA 3600 //power units per milliamperere for accurate power estimation
|
||||
//formula: 195075 divided by mA per fully lit LED, here ~54mA)
|
||||
//lowering the value increases the estimated usage and therefore makes the ABL more aggressive
|
||||
|
||||
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
|
||||
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
||||
|
||||
void WS2812FX::show(void) {
|
||||
//power limit calculation
|
||||
//each LED can draw up 195075 "power units" (approx. 53mA)
|
||||
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
||||
//so A=2,R=255,G=0,B=0 would use 510 PU per LED (1mA is about 3700 PU)
|
||||
|
||||
if (ablMilliampsMax > 149 && ablMilliampsMax < 65000) //lower numbers and 65000 turn off calculation
|
||||
{
|
||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * PU_PER_MA; //100mA for ESP power
|
||||
if (powerBudget > PU_PER_MA * _length) //each LED uses about 1mA in standby, exclude that from power budget
|
||||
{
|
||||
powerBudget -= PU_PER_MA * _length;
|
||||
} else
|
||||
{
|
||||
powerBudget = 0;
|
||||
}
|
||||
|
||||
uint32_t powerSum = 0;
|
||||
|
||||
for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED
|
||||
{
|
||||
RgbwColor c = bus->GetPixelColorRgbw(i);
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
}
|
||||
|
||||
if (_rgbwMode) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
{
|
||||
powerSum *= 3;
|
||||
powerSum >> 2; //same as /= 4
|
||||
}
|
||||
|
||||
uint32_t powerSum0 = powerSum;
|
||||
powerSum *= _brightness;
|
||||
|
||||
if (powerSum > powerBudget) //scale brightness down to stay in current limit
|
||||
{
|
||||
float scale = (float)powerBudget / (float)powerSum;
|
||||
uint16_t scaleI = scale * 255;
|
||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
||||
uint8_t newBri = scale8(_brightness, scaleB);
|
||||
bus->SetBrightness(newBri);
|
||||
currentMilliamps = (powerSum0 * newBri) / PU_PER_MA;
|
||||
} else
|
||||
{
|
||||
currentMilliamps = powerSum / PU_PER_MA;
|
||||
bus->SetBrightness(_brightness);
|
||||
}
|
||||
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
||||
currentMilliamps += _length; //add standby power back to estimate
|
||||
} else {
|
||||
currentMilliamps = 0;
|
||||
}
|
||||
|
||||
bus->Show();
|
||||
}
|
||||
|
||||
void WS2812FX::trigger() {
|
||||
_triggered = true;
|
||||
}
|
||||
|
||||
void WS2812FX::setMode(uint8_t m) {
|
||||
RESET_RUNTIME;
|
||||
bool ua = modeUsesLock(_segments[0].mode) && !modeUsesLock(m);
|
||||
if (m > MODE_COUNT - 1) m = MODE_COUNT - 1;
|
||||
_segments[0].mode = m;
|
||||
if (ua) unlockAll();
|
||||
_modeUsesLock = modeUsesLock(_segments[0].mode);
|
||||
setBrightness(_brightness);
|
||||
}
|
||||
|
||||
//TODO transitions
|
||||
|
||||
void WS2812FX::setSpeed(uint8_t s) {
|
||||
_segments[0].speed = s;
|
||||
}
|
||||
|
||||
void WS2812FX::setIntensity(uint8_t in) {
|
||||
_segments[0].intensity = in;
|
||||
}
|
||||
|
||||
void WS2812FX::setPalette(uint8_t p) {
|
||||
_segments[0].palette = p;
|
||||
}
|
||||
|
||||
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p) {
|
||||
bool changed = false;
|
||||
m = constrain(m, 0, MODE_COUNT - 1);
|
||||
if (m != _segments[0].mode) { setMode(m); changed = true; }
|
||||
if (s != _segments[0].speed) { setSpeed(s); changed = true; }
|
||||
if (i != _segments[0].intensity) { setIntensity(i); changed = true; }
|
||||
if (p != _segments[0].palette) { setPalette(p); changed = true; }
|
||||
return changed;
|
||||
}
|
||||
|
||||
void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||
setColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
|
||||
}
|
||||
|
||||
void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
|
||||
setSecondaryColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b);
|
||||
}
|
||||
|
||||
void WS2812FX::setColor(uint32_t c) {
|
||||
_segments[0].colors[0] = c;
|
||||
}
|
||||
|
||||
void WS2812FX::setSecondaryColor(uint32_t c) {
|
||||
_segments[0].colors[1] = c;
|
||||
}
|
||||
|
||||
void WS2812FX::setBrightness(uint8_t b) {
|
||||
if (_brightness == b) return;
|
||||
_brightness = b;
|
||||
bus->SetBrightness(_brightness);
|
||||
show();
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getMode(void) {
|
||||
return _segments[0].mode;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getSpeed(void) {
|
||||
return _segments[0].speed;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getBrightness(void) {
|
||||
return _brightness;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getNumSegments(void) {
|
||||
return _num_segments;
|
||||
}
|
||||
|
||||
void WS2812FX::setNumSegments(uint8_t n) {
|
||||
_num_segments = n;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getColor(void) {
|
||||
return _segments[0].colors[0];
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
if (_reverseMode) i = _length- 1 -i;
|
||||
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
|
||||
if (_cronixieMode)
|
||||
{
|
||||
if(i>6)return 0;
|
||||
byte o = 10*i;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: i=o+5; break;
|
||||
case 1: i=o+0; break;
|
||||
case 2: i=o+6; break;
|
||||
case 3: i=o+1; break;
|
||||
case 4: i=o+7; break;
|
||||
case 5: i=o+2; break;
|
||||
case 6: i=o+8; break;
|
||||
case 7: i=o+3; break;
|
||||
case 8: i=o+9; break;
|
||||
case 9: i=o+4; break;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
RgbwColor lColor = bus->GetPixelColorRgbw(i);
|
||||
byte r = lColor.R, g = lColor.G, b = lColor.B;
|
||||
switch (colorOrder)
|
||||
{
|
||||
case 0: break; //0 = Grb
|
||||
case 1: r = lColor.G; g = lColor.R; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = lColor.B; b = lColor.G; break; //2 = Brg
|
||||
case 3: r = lColor.B; g = lColor.R; b = lColor.G; //3 = Rbg
|
||||
}
|
||||
return ( (lColor.W << 24) | (r << 16) | (g << 8) | (b) );
|
||||
}
|
||||
|
||||
WS2812FX::Segment WS2812FX::getSegment(void) {
|
||||
return SEGMENT;
|
||||
}
|
||||
|
||||
WS2812FX::Segment_runtime WS2812FX::getSegmentRuntime(void) {
|
||||
return SEGMENT_RUNTIME;
|
||||
}
|
||||
|
||||
WS2812FX::Segment* WS2812FX::getSegments(void) {
|
||||
return _segments;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint8_t speed, uint8_t intensity, bool reverse) {
|
||||
uint32_t colors[] = {color, 0, 0};
|
||||
setSegment(n, start, stop, mode, colors, speed, intensity, reverse);
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, bool reverse) {
|
||||
setSegment(n, start, stop, mode, colors, speed, intensity, (uint8_t)(reverse ? REVERSE : NO_OPTIONS));
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint8_t speed, uint8_t intensity, uint8_t options) {
|
||||
if(n < (sizeof(_segments) / sizeof(_segments[0]))) {
|
||||
if(n + 1 > _num_segments) _num_segments = n + 1;
|
||||
_segments[n].start = start;
|
||||
_segments[n].stop = stop;
|
||||
_segments[n].mode = mode;
|
||||
_segments[n].speed = speed;
|
||||
_segments[n].intensity = intensity;
|
||||
_segments[n].options = options;
|
||||
|
||||
for(uint8_t i=0; i<NUM_COLORS; i++) {
|
||||
_segments[n].colors[i] = colors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::resetSegments() {
|
||||
memset(_segments, 0, sizeof(_segments));
|
||||
memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
|
||||
_segment_index = 0;
|
||||
_num_segments = 1;
|
||||
setSegment(0, 0, 7, FX_MODE_STATIC, (const uint32_t[]){DEFAULT_COLOR, 0, 0}, DEFAULT_SPEED, 128, NO_OPTIONS);
|
||||
}
|
||||
|
||||
void WS2812FX::setIndividual(uint16_t i, uint32_t col)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
if (i >= 0 && i < _length)
|
||||
{
|
||||
_locked[i] = false;
|
||||
setPixelColor(i, col);
|
||||
_locked[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
||||
{
|
||||
if (i2 >= i)
|
||||
{
|
||||
for (uint16_t x = i; x <= i2; x++) setIndividual(x,col);
|
||||
} else
|
||||
{
|
||||
for (uint16_t x = i2; x <= i; x++) setIndividual(x,col);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::lock(uint16_t i)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
if (i >= 0 && i < _length) _locked[i] = true;
|
||||
}
|
||||
|
||||
void WS2812FX::lockRange(uint16_t i, uint16_t i2)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
for (uint16_t x = i; x <= i2; x++)
|
||||
{
|
||||
if (i >= 0 && i < _length) _locked[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::unlock(uint16_t i)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
if (i >= 0 && i < _length) _locked[i] = false;
|
||||
}
|
||||
|
||||
void WS2812FX::unlockRange(uint16_t i, uint16_t i2)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
for (uint16_t x = i; x < i2; x++)
|
||||
{
|
||||
if (x >= 0 && x < _length) _locked[x] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::unlockAll()
|
||||
{
|
||||
for (int i=0; i < _length; i++) _locked[i] = false;
|
||||
}
|
||||
|
||||
void WS2812FX::setTransitionMode(bool t)
|
||||
{
|
||||
SEGMENT_RUNTIME.trans_act = (t) ? 1:2;
|
||||
if (!t) return;
|
||||
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
|
||||
if (SEGMENT.mode == FX_MODE_STATIC && SEGMENT_RUNTIME.next_time > waitMax) SEGMENT_RUNTIME.next_time = waitMax;
|
||||
}
|
||||
|
||||
/*
|
||||
* color blend function
|
||||
*/
|
||||
uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend) {
|
||||
if(blend == 0) return color1;
|
||||
if(blend == 255) return color2;
|
||||
|
||||
int w1 = (color1 >> 24) & 0xff;
|
||||
int r1 = (color1 >> 16) & 0xff;
|
||||
int g1 = (color1 >> 8) & 0xff;
|
||||
int b1 = color1 & 0xff;
|
||||
|
||||
int w2 = (color2 >> 24) & 0xff;
|
||||
int r2 = (color2 >> 16) & 0xff;
|
||||
int g2 = (color2 >> 8) & 0xff;
|
||||
int b2 = color2 & 0xff;
|
||||
|
||||
uint32_t w3 = ((w2 * blend) + (w1 * (255 - blend))) >> 8;
|
||||
uint32_t r3 = ((r2 * blend) + (r1 * (255 - blend))) >> 8;
|
||||
uint32_t g3 = ((g2 * blend) + (g1 * (255 - blend))) >> 8;
|
||||
uint32_t b3 = ((b2 * blend) + (b1 * (255 - blend))) >> 8;
|
||||
|
||||
return ((w3 << 24) | (r3 << 16) | (g3 << 8) | (b3));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills segment with color
|
||||
*/
|
||||
void WS2812FX::fill(uint32_t c) {
|
||||
for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) {
|
||||
setPixelColor(i, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fade out function, higher rate = quicker fade
|
||||
*/
|
||||
void WS2812FX::fade_out(uint8_t rate) {
|
||||
rate = (255-rate) >> 1;
|
||||
float mappedRate = float(rate) +1.1;
|
||||
|
||||
uint32_t color = SEGMENT.colors[1]; // target color
|
||||
int w2 = (color >> 24) & 0xff;
|
||||
int r2 = (color >> 16) & 0xff;
|
||||
int g2 = (color >> 8) & 0xff;
|
||||
int b2 = color & 0xff;
|
||||
|
||||
for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) {
|
||||
color = getPixelColor(i);
|
||||
int w1 = (color >> 24) & 0xff;
|
||||
int r1 = (color >> 16) & 0xff;
|
||||
int g1 = (color >> 8) & 0xff;
|
||||
int b1 = color & 0xff;
|
||||
|
||||
int wdelta = (w2 - w1) / mappedRate;
|
||||
int rdelta = (r2 - r1) / mappedRate;
|
||||
int gdelta = (g2 - g1) / mappedRate;
|
||||
int bdelta = (b2 - b1) / mappedRate;
|
||||
|
||||
// if fade isn't complete, make sure delta is at least 1 (fixes rounding issues)
|
||||
wdelta += (w2 == w1) ? 0 : (w2 > w1) ? 1 : -1;
|
||||
rdelta += (r2 == r1) ? 0 : (r2 > r1) ? 1 : -1;
|
||||
gdelta += (g2 == g1) ? 0 : (g2 > g1) ? 1 : -1;
|
||||
bdelta += (b2 == b1) ? 0 : (b2 > b1) ? 1 : -1;
|
||||
|
||||
setPixelColor(i, r1 + rdelta, g1 + gdelta, b1 + bdelta, w1 + wdelta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* blurs segment content, source: FastLED colorutils.cpp
|
||||
*/
|
||||
void WS2812FX::blur(uint8_t blur_amount)
|
||||
{
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for(uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++)
|
||||
{
|
||||
CRGB cur = fastled_from_col(getPixelColor(i));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if(i > SEGMENT.start) {
|
||||
uint32_t c = getPixelColor(i-1);
|
||||
uint8_t r = (c >> 16 & 0xFF);
|
||||
uint8_t g = (c >> 8 & 0xFF);
|
||||
uint8_t b = (c & 0xFF);
|
||||
setPixelColor(i-1, qadd8(r, part.red), qadd8(g, part.green), qadd8(b, part.blue));
|
||||
}
|
||||
setPixelColor(i,cur.red, cur.green, cur.blue);
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a value 0 to 255 in to get a color value.
|
||||
* The colours are a transition r -> g -> b -> back to r
|
||||
* Inspired by the Adafruit examples.
|
||||
*/
|
||||
uint32_t WS2812FX::color_wheel(uint8_t pos) {
|
||||
if (SEGMENT.palette) return color_from_palette(pos, false, true, 0);
|
||||
pos = 255 - pos;
|
||||
if(pos < 85) {
|
||||
return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
|
||||
} else if(pos < 170) {
|
||||
pos -= 85;
|
||||
return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
|
||||
} else {
|
||||
pos -= 170;
|
||||
return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new, random wheel index with a minimum distance of 42 from pos.
|
||||
*/
|
||||
uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
|
||||
uint8_t r = 0, x = 0, y = 0, d = 0;
|
||||
|
||||
while(d < 42) {
|
||||
r = random8();
|
||||
x = abs(pos - r);
|
||||
y = 255 - x;
|
||||
d = min(x, y);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
CRGB WS2812FX::fastled_from_col(uint32_t color)
|
||||
{
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = (color >> 16 & 0xFF);
|
||||
fastled_col.green = (color >> 8 & 0xFF);
|
||||
fastled_col.blue = (color & 0xFF);
|
||||
return fastled_col;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FastLED palette modes helper function. Limitation: Due to memory reasons, multiple active segments with FastLED will disable the Palette transitions
|
||||
*/
|
||||
void WS2812FX::handle_palette(void)
|
||||
{
|
||||
bool singleSegmentMode = (_segment_index == _segment_index_palette_last);
|
||||
_segment_index_palette_last = _segment_index;
|
||||
|
||||
byte paletteIndex = SEGMENT.palette;
|
||||
if ((SEGMENT.mode >= FX_MODE_METEOR) && SEGMENT.palette == 0) paletteIndex = 4;
|
||||
|
||||
switch (paletteIndex)
|
||||
{
|
||||
case 0: {//default palette. Differs depending on effect
|
||||
switch (SEGMENT.mode)
|
||||
{
|
||||
case FX_MODE_FIRE_2012 : targetPalette = gGradientPalettes[22]; break;//heat palette
|
||||
case FX_MODE_COLORWAVES : targetPalette = gGradientPalettes[13]; break;//landscape 33
|
||||
case FX_MODE_FILLNOISE8 : targetPalette = OceanColors_p; break;
|
||||
case FX_MODE_NOISE16_1 : targetPalette = gGradientPalettes[17]; break;//Drywet
|
||||
case FX_MODE_NOISE16_2 : targetPalette = gGradientPalettes[30]; break;//Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : targetPalette = gGradientPalettes[22]; break;//heat palette
|
||||
case FX_MODE_NOISE16_4 : targetPalette = gGradientPalettes[13]; break;//landscape 33
|
||||
|
||||
default: targetPalette = PartyColors_p; break;//palette, bpm
|
||||
}
|
||||
break;}
|
||||
case 1: {//periodically replace palette with a random one. Doesn't work with multiple FastLED segments
|
||||
if (!singleSegmentMode)
|
||||
{
|
||||
targetPalette = PartyColors_p; break; //fallback
|
||||
}
|
||||
if (millis() - _lastPaletteChange > 1000 + ((uint32_t)(255-SEGMENT.intensity))*100)
|
||||
{
|
||||
targetPalette = CRGBPalette16(
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)),
|
||||
CHSV(random8(), 192, random8(128, 255)),
|
||||
CHSV(random8(), 255, random8(128, 255)));
|
||||
_lastPaletteChange = millis();
|
||||
} break;}
|
||||
case 2: {//primary color only
|
||||
CRGB prim = fastled_from_col(SEGMENT.colors[0]);
|
||||
targetPalette = CRGBPalette16(prim); break;}
|
||||
case 3: {//based on primary
|
||||
//considering performance implications
|
||||
CRGB prim = fastled_from_col(SEGMENT.colors[0]);
|
||||
CHSV prim_hsv = rgb2hsv_approximate(prim);
|
||||
targetPalette = CRGBPalette16(
|
||||
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v), //color itself
|
||||
CHSV(prim_hsv.h, max(prim_hsv.s - 50,0), prim_hsv.v), //less saturated
|
||||
CHSV(prim_hsv.h, prim_hsv.s, max(prim_hsv.v - 50,0)), //darker
|
||||
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v)); //color itself
|
||||
break;}
|
||||
case 4: {//primary + secondary
|
||||
CRGB prim = fastled_from_col(SEGMENT.colors[0]);
|
||||
CRGB sec = fastled_from_col(SEGMENT.colors[1]);
|
||||
targetPalette = CRGBPalette16(sec,prim); break;}
|
||||
case 5: {//based on primary + secondary
|
||||
CRGB prim = fastled_from_col(SEGMENT.colors[0]);
|
||||
CRGB sec = fastled_from_col(SEGMENT.colors[1]);
|
||||
targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;}
|
||||
case 6: //Party colors
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 7: //Cloud colors
|
||||
targetPalette = CloudColors_p; break;
|
||||
case 8: //Lava colors
|
||||
targetPalette = LavaColors_p; break;
|
||||
case 9: //Ocean colors
|
||||
targetPalette = OceanColors_p; break;
|
||||
case 10: //Forest colors
|
||||
targetPalette = ForestColors_p; break;
|
||||
case 11: //Rainbow colors
|
||||
targetPalette = RainbowColors_p; break;
|
||||
case 12: //Rainbow stripe colors
|
||||
targetPalette = RainbowStripeColors_p; break;
|
||||
default: //progmem palettes
|
||||
targetPalette = gGradientPalettes[constrain(SEGMENT.palette -13, 0, gGradientPaletteCount -1)];
|
||||
}
|
||||
|
||||
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode
|
||||
{
|
||||
nblendPaletteTowardPalette(currentPalette, targetPalette, 48);
|
||||
} else
|
||||
{
|
||||
currentPalette = targetPalette;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri)
|
||||
{
|
||||
if (SEGMENT.palette == 0 && mcol < 3) return SEGMENT.colors[mcol]; //WS2812FX default
|
||||
uint8_t paletteIndex = i;
|
||||
if (mapping) paletteIndex = map(i,SEGMENT.start,SEGMENT.stop,0,255);
|
||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||
CRGB fastled_col;
|
||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||
return fastled_col.r*65536 + fastled_col.g*256 + fastled_col.b;
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head><meta charset="utf-8"><meta name="theme-color" content="#fff">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
|
||||
<title>WLED 0.8.0</title>
|
||||
<title>WLED 0.8.3</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var w=window.getComputedStyle(d.querySelector("html"));
|
||||
@@ -18,6 +18,9 @@
|
||||
var nState = 0;
|
||||
var cv=0;
|
||||
var lm=0;
|
||||
var fxi=0;
|
||||
var fpi=0;
|
||||
var fxn=1;
|
||||
aC="";
|
||||
bC="";
|
||||
dC="";
|
||||
@@ -26,17 +29,22 @@
|
||||
{
|
||||
return d.getElementById(s);
|
||||
}
|
||||
|
||||
function Startup()
|
||||
function UCol()
|
||||
{
|
||||
var w=window.getComputedStyle(d.querySelector("html"));
|
||||
aC = w.getPropertyValue("--aCol");
|
||||
bC = w.getPropertyValue("--bCol");
|
||||
dC = w.getPropertyValue("--dCol");
|
||||
d.querySelector("meta[name=theme-color]").setAttribute("content",bC);
|
||||
}
|
||||
function Startup()
|
||||
{
|
||||
var w=window.getComputedStyle(d.querySelector("html"));
|
||||
UCol();
|
||||
CV(0);
|
||||
setInterval('GIO()', 5000);
|
||||
setInterval(GIO, 5000);
|
||||
GIO();
|
||||
setTimeout(function(){fillfx(0);}, 500);
|
||||
setTimeout(function(){fillfx(1);}, 750);
|
||||
}
|
||||
function GIO()
|
||||
{
|
||||
@@ -57,17 +65,29 @@
|
||||
} else {
|
||||
uwv = false;
|
||||
}
|
||||
Cf.TX.selectedIndex = this.responseXML.getElementsByTagName('fx')[0].childNodes[0].nodeValue;
|
||||
Cf.FP.selectedIndex = this.responseXML.getElementsByTagName('fp')[0].childNodes[0].nodeValue;
|
||||
fxi = this.responseXML.getElementsByTagName('fx')[0].childNodes[0].nodeValue;
|
||||
fpi = this.responseXML.getElementsByTagName('fp')[0].childNodes[0].nodeValue;
|
||||
d.Cf.SX.value = this.responseXML.getElementsByTagName('sx')[0].childNodes[0].nodeValue;
|
||||
d.Cf.IX.value = this.responseXML.getElementsByTagName('ix')[0].childNodes[0].nodeValue;
|
||||
nla = (this.responseXML.getElementsByTagName('nl')[0].innerHTML)!=0?true:false;
|
||||
if(firstload){
|
||||
d.Cf.NC.checked = (this.responseXML.getElementsByTagName('nf')[0].innerHTML)!=0?true:false;
|
||||
d.Cf.SN.value = this.responseXML.getElementsByTagName('nd')[0].childNodes[0].nodeValue;
|
||||
d.Cf.ST.value = this.responseXML.getElementsByTagName('nt')[0].childNodes[0].nodeValue;
|
||||
CV(parseInt(this.responseXML.getElementsByTagName('md')[0].childNodes[0].nodeValue));
|
||||
}firstload=false;
|
||||
d.Cf.NC.checked = (this.responseXML.getElementsByTagName('nf')[0].innerHTML)!=0?true:false;
|
||||
d.Cf.SN.value = this.responseXML.getElementsByTagName('nd')[0].childNodes[0].nodeValue;
|
||||
d.Cf.ST.value = this.responseXML.getElementsByTagName('nt')[0].childNodes[0].nodeValue;
|
||||
d.documentElement.style.setProperty("--aCol",this.responseXML.getElementsByTagName('ca')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--bCol",this.responseXML.getElementsByTagName('cb')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--cCol",this.responseXML.getElementsByTagName('cc')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--dCol",this.responseXML.getElementsByTagName('cd')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--sCol",this.responseXML.getElementsByTagName('cu')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--tCol",this.responseXML.getElementsByTagName('ct')[0].childNodes[0].nodeValue);
|
||||
d.documentElement.style.setProperty("--cFn",this.responseXML.getElementsByTagName('cf')[0].childNodes[0].nodeValue);
|
||||
UCol();
|
||||
CV(parseInt(this.responseXML.getElementsByTagName('md')[0].childNodes[0].nodeValue));
|
||||
}else{
|
||||
Cf.TX.selectedIndex = fxi;
|
||||
Cf.IX.selectedIndex = fpi;
|
||||
}
|
||||
firstload=false;
|
||||
nState = 0;
|
||||
nState = (this.responseXML.getElementsByTagName('nr')[0].innerHTML)!=0?1:0;
|
||||
nState += (this.responseXML.getElementsByTagName('ns')[0].innerHTML)!=0?2:0;
|
||||
@@ -77,6 +97,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstload) resp+="&IT"
|
||||
request.open("GET", "win" +resp +nocache, true);
|
||||
request.send(null);
|
||||
resp="";
|
||||
@@ -172,7 +193,7 @@
|
||||
case 3: gId("path1").style.fill = aC; gId("path2").style.fill = aC;
|
||||
}
|
||||
tgb.style.fill=(Cf.SA.value>0)?aC:dC;
|
||||
fpX.style.display=(Cf.TX.selectedIndex>64)?"block":"none";
|
||||
fpX.style.display=(Cf.TX.selectedIndex>0)?"block":"none";
|
||||
fof.style.fill=(Cf.TX.selectedIndex>64)?aC:dC;
|
||||
fmr.style.fill=(Cf.TX.selectedIndex<1)?aC:dC;
|
||||
}
|
||||
@@ -192,10 +213,10 @@
|
||||
function SwFX(s)
|
||||
{
|
||||
var n=Cf.TX.selectedIndex+s;
|
||||
if (n==-1||n==74) return;
|
||||
if (n==-1||n==fxn) return;
|
||||
Cf.TX.selectedIndex =n;
|
||||
if (n < 0) Cf.TX.selectedIndex = 0;
|
||||
if (n > 73) Cf.TX.selectedIndex = 65;
|
||||
if (n > fxn) Cf.TX.selectedIndex = Math.min(65,fxn-1);
|
||||
GX();
|
||||
}
|
||||
function TgHSB()
|
||||
@@ -302,7 +323,6 @@
|
||||
rr=diffc(r);
|
||||
gg=diffc(g);
|
||||
bb=diffc(b);
|
||||
|
||||
if(r===v) {
|
||||
h=bb-gg;
|
||||
}else if (g===v){
|
||||
@@ -345,6 +365,32 @@
|
||||
{
|
||||
resp+="&PL=0";GIO();
|
||||
}
|
||||
function fillfx(fp)
|
||||
{
|
||||
e="<option>Error loading list!</option>";
|
||||
el = fp?Cf.FP:Cf.TX;
|
||||
fetch(fp?'/json/palettes':'/json/effects')
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
el.innerHTML=e;
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
var x="";
|
||||
var l=fp?json.palettes:json.effects;
|
||||
for (i in l) {
|
||||
x += "<option value=\""+i+"\">"+l[i]+" ("+i+")</option>";
|
||||
}
|
||||
el.innerHTML=x;
|
||||
el.selectedIndex=fp?fpi:fxi;
|
||||
if(!fp)fxn=l.length;
|
||||
UV();
|
||||
})
|
||||
.catch(function () {
|
||||
el.innerHTML=e;
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
:root {
|
||||
@@ -586,80 +632,7 @@
|
||||
<svg id="fmf" onclick="SwFX(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg>
|
||||
<svg id="fof" onclick="SwFX(99)"><use xlink:href="#lnr-rocket"></use></svg><br><br>
|
||||
<select name="TX" onchange="GX()">
|
||||
<option value="0" selected>Solid (0)</option>
|
||||
<option value="1">Blink (1)</option>
|
||||
<option value="2">Breath (2)</option>
|
||||
<option value="3">Wipe (3)</option>
|
||||
<option value="4">Wipe Random (4)</option>
|
||||
<option value="5">Color R (5)</option>
|
||||
<option value="6">Sweep (6)</option>
|
||||
<option value="7">Dynamic (7)</option>
|
||||
<option value="8">Colorloop (8)</option>
|
||||
<option value="9">Rainbow (9)</option>
|
||||
<option value="10">Scan (10)</option>
|
||||
<option value="11">Scan x2 (11)</option>
|
||||
<option value="12">Fade (12)</option>
|
||||
<option value="13">Chase (13)</option>
|
||||
<option value="14">Chase Cl (14)</option>
|
||||
<option value="15">Running (15)</option>
|
||||
<option value="16">Twinkle (16)</option>
|
||||
<option value="17">Twinkle R (17)</option>
|
||||
<option value="18">Twinkle Fade (18)</option>
|
||||
<option value="19">Twinkle RF (19)</option>
|
||||
<option value="20">Sparkle (20)</option>
|
||||
<option value="21">Sparkle Inv (21)</option>
|
||||
<option value="22">Sparkle Inv+ (22)</option>
|
||||
<option value="23">Strobe (23)</option>
|
||||
<option value="24">Strobe Cl (24)</option>
|
||||
<option value="25">Strobe + (25)</option>
|
||||
<option value="26">Blink Cl (26)</option>
|
||||
<option value="27">Android (27)</option>
|
||||
<option value="28">Chase (28)</option>
|
||||
<option value="29">Chase R (29)</option>
|
||||
<option value="30">Chase Rainbow (30)</option>
|
||||
<option value="31">Chase Flash (31)</option>
|
||||
<option value="32">Chase RF (32)</option>
|
||||
<option value="33">Chase Cl Inv (33)</option>
|
||||
<option value="34">Colorful (34)</option>
|
||||
<option value="35">Traffic Light (35)</option>
|
||||
<option value="36">Sweep R(36)</option>
|
||||
<option value="37">Running 2 (37)</option>
|
||||
<option value="38">Red/Blue (38)</option>
|
||||
<option value="39">Running R (39)</option>
|
||||
<option value="40">Scanner (40)</option>
|
||||
<option value="41">Lighthouse (41)</option>
|
||||
<option value="42">Fireworks (42)</option>
|
||||
<option value="43">Fireworks R (43)</option>
|
||||
<option value="44">Christmas (44)</option>
|
||||
<option value="45">Fire Flicker (45)</option>
|
||||
<option value="46">Gradient (46)</option>
|
||||
<option value="47">Loading (47)</option>
|
||||
<option value="48">Wipe IO (48)</option>
|
||||
<option value="49">Wipe II (49)</option>
|
||||
<option value="50">Wipe OO (50)</option>
|
||||
<option value="51">Wipe OI (51)</option>
|
||||
<option value="52">Circus (52)</option>
|
||||
<option value="53">Halloween (53)</option>
|
||||
<option value="54">Tricolor Chase (54)</option>
|
||||
<option value="55">Tricolor Wipe (55)</option>
|
||||
<option value="56">Tricolor Fade (56)</option>
|
||||
<option value="57">Lighting (57)</option>
|
||||
<option value="58">ICU (58)</option>
|
||||
<option value="59">Multi Comet (59)</option>
|
||||
<option value="60">Scanner x2 (60)</option>
|
||||
<option value="61">Random Chase (61)</option>
|
||||
<option value="62">Oscillate (62)</option>
|
||||
<option value="63">Pride 2015 (63)</option>
|
||||
<option value="64">Juggle (64)</option>
|
||||
<option value="65">Palette (65)</option>
|
||||
<option value="66">Fire 2012 (66)</option>
|
||||
<option value="67">Colorwaves (67)</option>
|
||||
<option value="68">BPM (68)</option>
|
||||
<option value="69">Fill Noise 8 (69)</option>
|
||||
<option value="70">Noise 16 1 (70)</option>
|
||||
<option value="71">Noise 16 2 (71)</option>
|
||||
<option value="72">Noise 16 3 (72)</option>
|
||||
<option value="73">Noise 16 4 (73)</option>
|
||||
<option>Loading...</option>
|
||||
</select><br><br>
|
||||
Set secondary color to
|
||||
<button type="button" onclick="CS(0)">White</button>
|
||||
@@ -671,51 +644,7 @@
|
||||
<div id="fpX">
|
||||
<br>FastLED Palette<br><br>
|
||||
<select name="FP" onchange="GP()">
|
||||
<option value="0" selected>Default</option>
|
||||
<option value="1">Random Cycle</option>
|
||||
<option value="2">Primary Color Only</option>
|
||||
<option value="3">Based on Primary</option>
|
||||
<option value="4">Set Colors Only</option>
|
||||
<option value="5">Based on Set Colors</option>
|
||||
<option value="6">Party</option>
|
||||
<option value="7">Cloud</option>
|
||||
<option value="8">Lava</option>
|
||||
<option value="9">Ocean</option>
|
||||
<option value="10">Forest</option>
|
||||
<option value="11">Rainbow</option>
|
||||
<option value="12">Rainbow Stripe</option>
|
||||
<option value="13">Sunset</option>
|
||||
<option value="14">Rivendell</option>
|
||||
<option value="15">Breeze</option>
|
||||
<option value="16">Red & Blue</option>
|
||||
<option value="17">Yellowout</option>
|
||||
<option value="18">Analogous</option>
|
||||
<option value="19">Splash</option>
|
||||
<option value="20">Pastel</option>
|
||||
<option value="21">Sunset2</option>
|
||||
<option value="22">Beech</option>
|
||||
<option value="23">Vintage</option>
|
||||
<option value="24">Departure</option>
|
||||
<option value="25">Landscape</option>
|
||||
<option value="26">Beach</option>
|
||||
<option value="27">Sherbet</option>
|
||||
<option value="28">Hult</option>
|
||||
<option value="29">Hult64</option>
|
||||
<option value="30">Drywet</option>
|
||||
<option value="31">Jul</option>
|
||||
<option value="32">Grintage</option>
|
||||
<option value="33">Rewhi</option>
|
||||
<option value="34">Tertiary</option>
|
||||
<option value="35">Fire</option>
|
||||
<option value="36">Icefire</option>
|
||||
<option value="37">Cyane</option>
|
||||
<option value="38">Light Pink</option>
|
||||
<option value="39">Autumn</option>
|
||||
<option value="40">Magenta</option>
|
||||
<option value="41">Magred</option>
|
||||
<option value="42">Yelmag</option>
|
||||
<option value="43">Yelblu</option>
|
||||
<option value="44">Orange & Teal</option>
|
||||
<option>Loading...</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="slX" class="sl">
|
||||
@@ -730,14 +659,14 @@
|
||||
<svg id="psn" onclick="SwitchPS(1)"><use xlink:href="#lnr-arrow-right-circle"></use></svg>
|
||||
<svg id="pss" onclick="PSIO(true)"><use xlink:href="#lnr-arrow-down-circle"></use></svg>
|
||||
<br><input id="psI" name = "FF" type="number" value="1" min="1" max="25" step="1"><br><br>
|
||||
Click checkmark to apply <input type="checkbox" checked="true" name="BC"> brightness, <input type="checkbox" checked="true" name="CC"> color and <input type="checkbox" checked="true" name="FC"> effects.<br><br>
|
||||
Click checkmark to apply <input type="checkbox" checked name="CC"> color, <input type="checkbox" checked name="FC"> effects and <input type="checkbox" name="BC"> brightness.<br><br>
|
||||
Cycle through presets <input id="cy1" name="P1" type="number" value="1" min="1" max="25" step="1"> to <input id="cy2" name="P2" type="number" value="5" min="1" max="25" step="1">, keep each for <input id="cyT" name="PT" type="number" value="1250" min="50" max="65501" step="1">ms: <input type="checkbox" name="CY" onclick="uCY()"><br><br>
|
||||
<button type="button" onclick="R()">Apply boot config</button><br>
|
||||
</div>
|
||||
<div id="tlN" class="tools">
|
||||
Timed Light<br><br>
|
||||
<svg id="ntb" onclick="TgNl()"><use xlink:href="#lnr-power-switch"></use></svg><br><br>
|
||||
Gradually dim down <input type="checkbox" checked="true" name="NC"><br>
|
||||
Gradually dim down <input type="checkbox" checked name="NC"><br>
|
||||
1st slider sets duration (1-255min), 2nd sets target brightness.
|
||||
<div id="slN" class="sl">
|
||||
<input type="range" title="Duration" class="sds" name="SN" value="60" min="1" max="255" step="1"></div>
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta content='width=device-width' name='viewport'>
|
||||
<title>WLED Message</title>
|
||||
<script>
|
||||
function B() {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content='width=device-width' name='viewport'>
|
||||
<title>WLED Setup</title>
|
||||
<style>
|
||||
:root {
|
||||
@@ -14,9 +15,7 @@
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
text-align: center;
|
||||
background: linear-gradient(var(--bCol),black);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
color: var(--dCol);
|
||||
}
|
||||
|
658
wled00/html_classic.h
Normal file
658
wled00/html_classic.h
Normal file
@@ -0,0 +1,658 @@
|
||||
/*
|
||||
* Binary arrays for the classic desktop UI index page.
|
||||
* gzip is used for smaller size and improved speeds.
|
||||
*
|
||||
* Workflow for creating them from HTML source:
|
||||
* 1. Minify HTML (https://htmlcompressor.com/compressor/) (optional)
|
||||
* 2. Compress with gzip (https://online-converting.com/archives/convert-to-gzip/)
|
||||
* 3. Convert gzip binary to c array (https://sourceforge.net/projects/bin2header/)
|
||||
* alternative: https://littlevgl.com/image-to-c-array (raw)
|
||||
* 4. update length value
|
||||
*/
|
||||
|
||||
const uint16_t PAGE_index0_L = 10264;
|
||||
|
||||
const char PAGE_index0[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x08, 0x67, 0x5e, 0x61, 0x5c, 0x00, 0x03, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65,
|
||||
0x73, 0x73, 0x65, 0x64, 0x20, 0x28, 0x37, 0x29, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, 0xcc, 0x5a,
|
||||
0xe9, 0x72, 0xdb, 0x46, 0xb6, 0xfe, 0xaf, 0xa7, 0x80, 0xe9, 0x4a, 0x4c, 0x46, 0x04, 0x88, 0x9d,
|
||||
0x00, 0x29, 0x28, 0x65, 0x2b, 0xde, 0xaa, 0x1c, 0x45, 0x65, 0x69, 0x62, 0xa5, 0x32, 0x29, 0x17,
|
||||
0x88, 0x85, 0xc4, 0x18, 0x04, 0x68, 0x00, 0xa4, 0xa4, 0x30, 0x7a, 0xf7, 0xf9, 0x4e, 0x77, 0x93,
|
||||
0x04, 0xa8, 0x8d, 0xf4, 0x64, 0xe6, 0x5e, 0x57, 0x19, 0x40, 0xf7, 0x39, 0xdd, 0x67, 0x5f, 0xba,
|
||||
0xa9, 0xa3, 0x67, 0x3f, 0xfd, 0x72, 0x72, 0xf1, 0xdb, 0xd9, 0x6b, 0x69, 0x52, 0x4d, 0xd3, 0xe3,
|
||||
0x23, 0xf1, 0x8c, 0xfc, 0xf0, 0xf8, 0x68, 0x1a, 0x55, 0xbe, 0x14, 0x4c, 0xfc, 0xa2, 0x8c, 0x2a,
|
||||
0x6f, 0x5e, 0xc5, 0xb2, 0x23, 0xe6, 0x32, 0x7f, 0x1a, 0x79, 0xd5, 0x24, 0x9a, 0x46, 0x72, 0x90,
|
||||
0xa7, 0x79, 0x21, 0x05, 0x79, 0x56, 0x45, 0x59, 0xe5, 0x3d, 0x8f, 0xe3, 0xf8, 0xf8, 0x28, 0x4d,
|
||||
0xb2, 0x2f, 0x52, 0x11, 0xa5, 0xde, 0x8b, 0x72, 0x92, 0x17, 0x55, 0x30, 0xaf, 0xa4, 0x04, 0x18,
|
||||
0x2f, 0xa4, 0xea, 0x66, 0x16, 0x79, 0xc9, 0xd4, 0x1f, 0x47, 0xbd, 0x6b, 0x99, 0xa6, 0xa4, 0x49,
|
||||
0x11, 0xc5, 0xde, 0x8b, 0x5e, 0xec, 0x2f, 0x68, 0xa8, 0xe0, 0xf1, 0xa2, 0x77, 0x7c, 0x54, 0x25,
|
||||
0x55, 0x1a, 0x1d, 0x7f, 0xfa, 0xf0, 0xfa, 0x27, 0x49, 0x55, 0x1c, 0xc5, 0x38, 0xea, 0xf1, 0x19,
|
||||
0xe9, 0xa8, 0x0c, 0x8a, 0x64, 0x56, 0x1d, 0x2f, 0xfc, 0x42, 0x0a, 0xbd, 0x30, 0x0f, 0xe6, 0x53,
|
||||
0x90, 0x1d, 0xd2, 0xf0, 0xca, 0xbb, 0x4a, 0xb2, 0x30, 0xbf, 0x52, 0xc6, 0x51, 0x75, 0x92, 0x4f,
|
||||
0x67, 0xf3, 0x2a, 0x0a, 0xcf, 0xab, 0x9b, 0x34, 0x6a, 0x87, 0xca, 0xd7, 0x79, 0x54, 0xdc, 0x9c,
|
||||
0x47, 0x69, 0x14, 0x54, 0x79, 0xd1, 0x6e, 0x91, 0x8c, 0xad, 0x4e, 0x67, 0x58, 0x44, 0xe5, 0xcc,
|
||||
0x6b, 0xb5, 0xd8, 0xf2, 0x2c, 0xf5, 0xbd, 0xd8, 0x4f, 0xcb, 0x88, 0x8f, 0x8a, 0xc6, 0xa8, 0xac,
|
||||
0x8f, 0xca, 0x2a, 0xaf, 0x8d, 0xe6, 0x57, 0x8b, 0x3a, 0x6c, 0x14, 0x7b, 0x55, 0x31, 0xe7, 0x83,
|
||||
0x38, 0x29, 0xca, 0x2a, 0xcd, 0xfd, 0x70, 0x33, 0x95, 0xfa, 0x65, 0x55, 0x5e, 0x7b, 0x2a, 0xdf,
|
||||
0xf6, 0xbc, 0xf2, 0xab, 0x48, 0x0c, 0x82, 0x85, 0xf8, 0x48, 0xa7, 0xe2, 0x23, 0xbe, 0x4e, 0x56,
|
||||
0x5f, 0xb3, 0xf5, 0xd7, 0x75, 0xe6, 0x69, 0x43, 0xff, 0x84, 0xb8, 0x1e, 0xb1, 0x67, 0xc8, 0x9e,
|
||||
0xf1, 0x3c, 0x0b, 0xaa, 0x04, 0xfa, 0x1c, 0xbf, 0x0f, 0xdb, 0x65, 0xe7, 0x60, 0x59, 0x44, 0xd5,
|
||||
0xbc, 0xc8, 0xa4, 0x90, 0xb4, 0xf1, 0x3a, 0x8d, 0x48, 0x4b, 0xaf, 0x6e, 0x18, 0x6c, 0x78, 0x7b,
|
||||
0xb0, 0xc6, 0xfe, 0xc7, 0x49, 0x9e, 0xb6, 0x81, 0x8d, 0x0d, 0x99, 0xde, 0xce, 0x8a, 0x7c, 0x16,
|
||||
0x15, 0xd5, 0xcd, 0xaf, 0x7e, 0x3a, 0x8f, 0xda, 0x2d, 0x59, 0xf6, 0x81, 0xd0, 0xea, 0x10, 0xa9,
|
||||
0xfb, 0xe1, 0x23, 0x0e, 0x0f, 0x1f, 0x82, 0x87, 0x02, 0xbe, 0x6d, 0x01, 0xf2, 0xa2, 0xdf, 0xb7,
|
||||
0xbd, 0xe8, 0x8f, 0x56, 0x47, 0x81, 0xa7, 0xbd, 0xac, 0xaa, 0x22, 0x19, 0xc1, 0x7c, 0xed, 0x96,
|
||||
0x70, 0xab, 0x56, 0x77, 0x74, 0xd2, 0xe0, 0x1b, 0x8a, 0x2b, 0xaa, 0xf9, 0x8c, 0x58, 0xff, 0x46,
|
||||
0xd3, 0x73, 0xc9, 0x87, 0x27, 0xbf, 0xb6, 0xd5, 0xce, 0x10, 0x44, 0xdf, 0x83, 0x50, 0xb1, 0xf0,
|
||||
0xd3, 0xf6, 0xdb, 0xf7, 0xbf, 0x74, 0x2d, 0x55, 0xc5, 0x2c, 0xbe, 0xda, 0x0c, 0x76, 0x91, 0x4c,
|
||||
0xa3, 0x7c, 0x5e, 0xb5, 0x57, 0xe4, 0xdb, 0x9d, 0x65, 0x9c, 0xa4, 0x69, 0x7c, 0x4d, 0x6b, 0x6f,
|
||||
0x09, 0xfb, 0x09, 0x34, 0x8d, 0xd0, 0xfa, 0x96, 0xda, 0x90, 0x81, 0x6d, 0x7f, 0xb0, 0xcc, 0xf2,
|
||||
0xc0, 0x0f, 0x26, 0x91, 0xd7, 0xfa, 0x7e, 0xfd, 0x75, 0xf8, 0xb3, 0x5f, 0x4d, 0x94, 0xc2, 0x87,
|
||||
0x48, 0xd3, 0x76, 0xe7, 0x07, 0x4d, 0x65, 0xff, 0x98, 0xfd, 0x8b, 0x08, 0xf2, 0x94, 0x95, 0x97,
|
||||
0x45, 0x57, 0xd2, 0xe5, 0xcf, 0x1f, 0xde, 0x55, 0xd5, 0xec, 0x23, 0x9f, 0x6a, 0x93, 0x3b, 0xb3,
|
||||
0x2f, 0x25, 0xcf, 0x0a, 0x84, 0xef, 0x4d, 0x49, 0xde, 0x85, 0xe8, 0xcd, 0xc6, 0x91, 0xb7, 0xe1,
|
||||
0xe9, 0x60, 0x99, 0xc4, 0xed, 0x6a, 0x92, 0x94, 0x0a, 0x43, 0xe2, 0x2e, 0xe8, 0x99, 0x9d, 0xf5,
|
||||
0x34, 0x2d, 0x9b, 0x97, 0x9e, 0xa7, 0x43, 0xac, 0x1a, 0x6e, 0x39, 0xcb, 0xb3, 0x32, 0x02, 0xcd,
|
||||
0x67, 0x5e, 0x36, 0x4f, 0xd3, 0xce, 0x32, 0x54, 0x4e, 0x62, 0xe5, 0xfc, 0xa5, 0xb2, 0x20, 0x5b,
|
||||
0x7b, 0xdb, 0x58, 0x35, 0xbf, 0x2b, 0x5f, 0xdd, 0x5c, 0xf8, 0xe3, 0x53, 0x18, 0xbb, 0xfd, 0xc2,
|
||||
0x0f, 0x5e, 0x74, 0x7e, 0x57, 0xff, 0x50, 0x82, 0x49, 0x92, 0x86, 0xa7, 0x79, 0x18, 0x95, 0x34,
|
||||
0xca, 0xf0, 0xc1, 0x5c, 0x66, 0xc8, 0x37, 0xfd, 0xb8, 0xdf, 0xa6, 0x41, 0xba, 0xcb, 0xa6, 0x6f,
|
||||
0xbf, 0x61, 0x53, 0xed, 0xa9, 0x4d, 0x5f, 0x7d, 0xc3, 0xa6, 0xfa, 0xc3, 0x9b, 0xde, 0xa3, 0xee,
|
||||
0x07, 0x76, 0xba, 0x5a, 0x3c, 0x2a, 0xf3, 0xb1, 0xa7, 0xae, 0x2c, 0xf4, 0x69, 0x3f, 0x16, 0x9f,
|
||||
0xd8, 0x78, 0x48, 0xf9, 0x8e, 0xa5, 0xb3, 0xdb, 0x08, 0x49, 0x6f, 0xb9, 0x49, 0x7f, 0x70, 0x6d,
|
||||
0x24, 0xac, 0x1d, 0xa9, 0xc4, 0xd7, 0x8f, 0x53, 0xa1, 0x8c, 0xb7, 0xeb, 0x56, 0xb3, 0x5d, 0xac,
|
||||
0x7f, 0xb9, 0x9f, 0x16, 0xca, 0x27, 0xf8, 0x63, 0x9b, 0xbe, 0xdf, 0x73, 0xd3, 0xe4, 0x89, 0x4d,
|
||||
0xa9, 0x04, 0xed, 0x6a, 0xff, 0x4c, 0xf8, 0x7c, 0x92, 0x65, 0x51, 0xf1, 0xee, 0xe2, 0xe7, 0x0f,
|
||||
0x9d, 0x67, 0x9e, 0xfa, 0x23, 0x19, 0x66, 0xc0, 0xcd, 0x01, 0x57, 0x5a, 0xd7, 0x1f, 0xe1, 0x0a,
|
||||
0xa7, 0x27, 0x20, 0x1d, 0x05, 0x5f, 0xa2, 0x70, 0x77, 0x32, 0xf1, 0x13, 0x64, 0xb8, 0x76, 0x4f,
|
||||
0xf7, 0x53, 0x44, 0x16, 0xee, 0x62, 0xb2, 0x8b, 0x3d, 0x37, 0xad, 0x9e, 0xda, 0x74, 0xd5, 0x2e,
|
||||
0x88, 0xc5, 0xc8, 0x74, 0x28, 0x11, 0x54, 0x71, 0x56, 0x65, 0x6b, 0x5d, 0xf1, 0xba, 0xbb, 0xc6,
|
||||
0xb3, 0xff, 0x28, 0xcd, 0xce, 0xae, 0x44, 0x47, 0x7b, 0x11, 0x1d, 0xfd, 0x3d, 0x44, 0x83, 0xbd,
|
||||
0x88, 0x3e, 0x9e, 0xb8, 0x77, 0x26, 0x1a, 0xee, 0x45, 0xf4, 0x71, 0x3f, 0xd9, 0x99, 0x68, 0xb9,
|
||||
0x17, 0xd1, 0xf9, 0xdf, 0x43, 0xb4, 0xda, 0x8b, 0xe8, 0xe3, 0xce, 0xbb, 0xbb, 0x4d, 0xdf, 0x64,
|
||||
0xbb, 0xd3, 0x8c, 0x9f, 0xa0, 0xb9, 0xe9, 0x91, 0x66, 0x74, 0x04, 0x40, 0x8b, 0xb4, 0x6b, 0xda,
|
||||
0x98, 0x3e, 0x61, 0xb8, 0x8e, 0xa8, 0x1e, 0x08, 0xf3, 0x8b, 0x4b, 0xc8, 0x40, 0xdd, 0x59, 0x14,
|
||||
0xbe, 0xcf, 0xc2, 0xe8, 0xda, 0x43, 0x15, 0x19, 0xf2, 0xe4, 0xba, 0x35, 0x3f, 0x4b, 0xa8, 0xc6,
|
||||
0xac, 0x7b, 0x6a, 0x9e, 0x7f, 0xd6, 0x3d, 0xb4, 0xf8, 0xd8, 0x39, 0xb1, 0x15, 0xf7, 0x25, 0x36,
|
||||
0x6d, 0xb0, 0xda, 0xe8, 0x70, 0xf7, 0x9d, 0xca, 0xfb, 0x76, 0xd2, 0xb1, 0x53, 0xd8, 0x5c, 0x71,
|
||||
0x82, 0xe6, 0xbf, 0x64, 0x6b, 0x5a, 0x50, 0x48, 0xd0, 0x6a, 0xae, 0xda, 0x35, 0xcd, 0x85, 0xdb,
|
||||
0xe4, 0x86, 0xff, 0xf8, 0x15, 0x46, 0xba, 0xc5, 0xbf, 0x83, 0x46, 0xce, 0xa7, 0xad, 0x0e, 0xd1,
|
||||
0x56, 0xbe, 0xbf, 0x68, 0x1d, 0xac, 0x3b, 0xc3, 0x59, 0x94, 0xb5, 0x5b, 0x6f, 0x5f, 0x5f, 0xb4,
|
||||
0xba, 0x2d, 0xb4, 0xcc, 0xad, 0x43, 0x86, 0x24, 0x1a, 0xcf, 0x2e, 0xa5, 0xf5, 0x4d, 0x17, 0x59,
|
||||
0x46, 0x59, 0xd8, 0x66, 0xad, 0xde, 0xfa, 0x9c, 0x54, 0xef, 0x5e, 0x4f, 0xda, 0xec, 0x94, 0xc1,
|
||||
0x69, 0xbc, 0x44, 0xd3, 0x5a, 0xeb, 0x06, 0x87, 0xab, 0xf9, 0x8f, 0x62, 0xfe, 0xe3, 0xd6, 0xfc,
|
||||
0x5b, 0x31, 0xff, 0x76, 0x6b, 0xfe, 0x95, 0x98, 0x17, 0x6d, 0x15, 0x15, 0x31, 0x34, 0x18, 0x6b,
|
||||
0x51, 0x3e, 0x09, 0xb0, 0x68, 0x69, 0xb8, 0xe4, 0xbc, 0x4d, 0xaf, 0xb3, 0x76, 0x59, 0x67, 0xed,
|
||||
0xcd, 0x25, 0x5f, 0xb4, 0xed, 0x67, 0x6b, 0x9a, 0xe7, 0x02, 0x61, 0xd5, 0x22, 0xac, 0x01, 0xef,
|
||||
0x05, 0x60, 0x55, 0xe6, 0x1f, 0x22, 0x17, 0x55, 0x1f, 0xdf, 0xbe, 0x5a, 0x1d, 0x45, 0x8a, 0xee,
|
||||
0xb8, 0x3b, 0xea, 0x26, 0xdd, 0xb8, 0x3b, 0xeb, 0x7e, 0xed, 0xf2, 0x93, 0xe9, 0xc4, 0xe3, 0x05,
|
||||
0xed, 0x1d, 0xdf, 0xa7, 0x5b, 0x8a, 0xf1, 0xb9, 0x18, 0x2f, 0x3c, 0xdd, 0xb2, 0x86, 0x89, 0xc7,
|
||||
0xda, 0xfe, 0x38, 0xcd, 0x71, 0x4e, 0x99, 0xfc, 0x60, 0x77, 0x86, 0xb1, 0x87, 0x97, 0x9c, 0x0c,
|
||||
0x67, 0xde, 0xe2, 0x87, 0xb6, 0x26, 0xe3, 0xe8, 0xf6, 0x95, 0x7f, 0xc5, 0x3f, 0xe0, 0xbb, 0xe2,
|
||||
0xdf, 0x34, 0xec, 0xd0, 0xb8, 0xbc, 0x4a, 0xaa, 0x60, 0xd2, 0x4e, 0xbe, 0xb3, 0x3b, 0xcb, 0xc0,
|
||||
0x2f, 0x23, 0x49, 0x1d, 0x14, 0xde, 0xa2, 0x3b, 0xf6, 0xaa, 0xee, 0xc8, 0x9b, 0x0d, 0x47, 0x68,
|
||||
0xf7, 0xbf, 0x0c, 0x19, 0x40, 0x03, 0xe0, 0x2b, 0x00, 0x8b, 0x6d, 0x80, 0x0e, 0xc0, 0x4c, 0x00,
|
||||
0xaa, 0x3a, 0xc0, 0x10, 0x80, 0xaf, 0x00, 0x2c, 0xea, 0x00, 0x13, 0x80, 0x0a, 0x80, 0xd9, 0x36,
|
||||
0xc0, 0x12, 0xc4, 0x09, 0xf0, 0x15, 0xea, 0x6a, 0x36, 0xf6, 0xc5, 0x56, 0x4f, 0x3e, 0xde, 0x6a,
|
||||
0xa7, 0x47, 0x43, 0xf2, 0xaf, 0x86, 0x96, 0xcf, 0x1a, 0x46, 0x3d, 0xe3, 0xa6, 0x79, 0x73, 0xb6,
|
||||
0x65, 0xd4, 0x3b, 0xd6, 0x41, 0xf2, 0x5a, 0xf0, 0x33, 0x0f, 0x8e, 0xed, 0x9d, 0x93, 0x34, 0x2f,
|
||||
0xa3, 0xf3, 0xa8, 0xaa, 0x92, 0x6c, 0x5c, 0x02, 0x91, 0x4e, 0xcb, 0xad, 0x32, 0x7d, 0x49, 0x07,
|
||||
0x4f, 0x96, 0x4e, 0xc3, 0xa4, 0x9c, 0xa5, 0xfe, 0x8d, 0xd7, 0xca, 0xf2, 0x2c, 0x6a, 0x09, 0x78,
|
||||
0x31, 0x1e, 0x3d, 0x8e, 0x30, 0x29, 0x1f, 0x87, 0xa7, 0x9f, 0x1e, 0x85, 0x57, 0xe9, 0xe5, 0x13,
|
||||
0xf0, 0xb3, 0x27, 0xe0, 0xa7, 0x0f, 0xc1, 0x21, 0xf7, 0xe2, 0x48, 0x67, 0xe7, 0x38, 0x0a, 0xa4,
|
||||
0x87, 0xd9, 0x19, 0xa5, 0x79, 0xf0, 0xa5, 0xf5, 0x88, 0x42, 0x04, 0xc2, 0xed, 0x81, 0xf0, 0xb3,
|
||||
0xc5, 0xda, 0xcb, 0x1e, 0x51, 0x92, 0x58, 0xc4, 0xae, 0x34, 0x1a, 0x0e, 0xf8, 0xb0, 0xde, 0x36,
|
||||
0x4b, 0xb4, 0xa6, 0x6b, 0x3e, 0xac, 0x0a, 0xb1, 0xa4, 0xe1, 0xaf, 0x0f, 0x2b, 0xf6, 0x2e, 0xb6,
|
||||
0x39, 0x78, 0x58, 0x8d, 0x6b, 0xb1, 0x83, 0x05, 0x1c, 0x7c, 0x1a, 0x8e, 0x04, 0x02, 0x9d, 0xec,
|
||||
0xbd, 0x76, 0x3a, 0x3d, 0x56, 0x3b, 0x3f, 0xfa, 0x27, 0x83, 0xf0, 0xa4, 0xee, 0x74, 0xd0, 0x85,
|
||||
0x3e, 0x89, 0xae, 0xdb, 0x45, 0x14, 0x76, 0xc7, 0x45, 0x14, 0x65, 0xdd, 0x11, 0x55, 0x3d, 0x9e,
|
||||
0x20, 0xc6, 0x23, 0x8f, 0x46, 0x7f, 0xb5, 0x19, 0xe4, 0xe8, 0xc8, 0xe9, 0xfc, 0x45, 0x88, 0x47,
|
||||
0x47, 0x9a, 0x4d, 0x99, 0x96, 0xae, 0x6d, 0x5e, 0x3c, 0x7f, 0x71, 0xd8, 0x56, 0xaf, 0xc5, 0xc1,
|
||||
0xff, 0x10, 0x4b, 0x3a, 0x4a, 0x95, 0x9f, 0x57, 0x05, 0xdc, 0xb6, 0x0d, 0x34, 0xa5, 0x4c, 0x93,
|
||||
0x20, 0x6a, 0x6b, 0x9d, 0x1a, 0xcd, 0x14, 0xb0, 0xc2, 0x0f, 0xdb, 0x2c, 0x01, 0x75, 0xc4, 0xfd,
|
||||
0x4f, 0x0b, 0xb3, 0x91, 0x5f, 0xc8, 0x04, 0x49, 0x50, 0x48, 0xda, 0xad, 0xc3, 0xd1, 0xc9, 0x21,
|
||||
0x92, 0xff, 0xe1, 0x9a, 0x45, 0x86, 0x7e, 0xd8, 0xea, 0x34, 0xb2, 0x3b, 0x65, 0xba, 0x03, 0x1c,
|
||||
0x1a, 0x46, 0x79, 0x78, 0x23, 0x04, 0x1e, 0xf9, 0xc1, 0x97, 0x71, 0x91, 0xcf, 0xb3, 0xd0, 0x5b,
|
||||
0x91, 0xaa, 0x45, 0x74, 0xb7, 0x16, 0xcd, 0xdd, 0x5a, 0x24, 0xb3, 0x8b, 0x91, 0x77, 0xe7, 0xbb,
|
||||
0xa1, 0xc6, 0xd7, 0x4d, 0xed, 0xb2, 0x9c, 0xb0, 0x9d, 0xb7, 0x37, 0x0a, 0xcf, 0xd2, 0x26, 0x3a,
|
||||
0x8e, 0x4f, 0x6b, 0x50, 0xf5, 0x20, 0x48, 0xb8, 0x2f, 0xaf, 0xf2, 0x10, 0xb2, 0xee, 0xc4, 0x33,
|
||||
0x24, 0x60, 0x6d, 0xed, 0x03, 0x6c, 0x29, 0x56, 0xac, 0x41, 0xfa, 0x1d, 0xd0, 0x5d, 0x9f, 0xbe,
|
||||
0x67, 0x0b, 0x7f, 0xd7, 0x2d, 0xf4, 0x6f, 0xe1, 0xc2, 0x3f, 0xb9, 0xc7, 0xf1, 0xf7, 0xe3, 0xc2,
|
||||
0x27, 0xe7, 0xad, 0xc6, 0x4d, 0x95, 0xd5, 0xca, 0xf9, 0x46, 0xe5, 0xf1, 0xec, 0x72, 0x2b, 0x40,
|
||||
0xda, 0x0f, 0x98, 0x48, 0x04, 0xce, 0x40, 0xe4, 0xa1, 0x38, 0x8f, 0xb7, 0x77, 0xbf, 0xb3, 0xca,
|
||||
0x36, 0xd7, 0x64, 0xa6, 0xc5, 0x53, 0xd8, 0x47, 0xda, 0x3d, 0x71, 0x77, 0x31, 0xbe, 0x10, 0x17,
|
||||
0x5c, 0x4d, 0xee, 0x37, 0x85, 0xe3, 0xc2, 0x53, 0x5b, 0xc3, 0xfa, 0xbd, 0x95, 0xca, 0x3b, 0xd1,
|
||||
0x3a, 0x86, 0x4e, 0xa1, 0x70, 0x7f, 0xad, 0x3f, 0xbf, 0x7a, 0x73, 0xc9, 0xae, 0x57, 0xd9, 0xf5,
|
||||
0xad, 0x77, 0x0f, 0x5f, 0x87, 0x25, 0xe5, 0xdc, 0xcc, 0xf3, 0x64, 0xed, 0xaf, 0xbf, 0xf0, 0x8a,
|
||||
0xaf, 0xb3, 0x0e, 0x8f, 0xc5, 0xe1, 0x7d, 0xcd, 0x6e, 0xc6, 0xb0, 0x8f, 0xd4, 0xce, 0x7d, 0x40,
|
||||
0x95, 0x01, 0x8f, 0x69, 0x8b, 0xfb, 0xc0, 0xac, 0x5d, 0x98, 0x26, 0x59, 0xdb, 0xb6, 0xba, 0xc0,
|
||||
0x91, 0x35, 0x30, 0x7c, 0xd9, 0xe4, 0xf7, 0x62, 0xfc, 0xee, 0xfc, 0x95, 0x50, 0x49, 0x40, 0x85,
|
||||
0xe0, 0x60, 0x89, 0x77, 0xe7, 0x47, 0x76, 0xed, 0x39, 0xc0, 0x53, 0x5b, 0x77, 0xe2, 0xbf, 0x22,
|
||||
0x99, 0x51, 0x1b, 0x59, 0x17, 0x96, 0x22, 0xe5, 0xec, 0xbc, 0x7d, 0xcd, 0x72, 0x01, 0x95, 0xdb,
|
||||
0x37, 0x42, 0x6b, 0xeb, 0xf3, 0x40, 0x63, 0xba, 0x73, 0x78, 0x4d, 0x1c, 0x37, 0xe6, 0x60, 0xa7,
|
||||
0xe6, 0x52, 0xed, 0x0e, 0xca, 0xb1, 0x6e, 0x6d, 0xe1, 0xe8, 0x56, 0x5d, 0x88, 0xb3, 0x97, 0xd5,
|
||||
0xa6, 0xf6, 0xf3, 0xa5, 0xaf, 0xd6, 0x37, 0x19, 0xf0, 0xb4, 0xef, 0xcf, 0x5e, 0x7a, 0x1a, 0x3c,
|
||||
0x8d, 0xde, 0xb0, 0x6e, 0x1d, 0xef, 0xa4, 0x89, 0x77, 0x22, 0xf0, 0x4e, 0xb6, 0xf1, 0xde, 0x34,
|
||||
0xf1, 0x2e, 0x05, 0xde, 0x25, 0xe1, 0xd5, 0x39, 0x39, 0x87, 0x43, 0x94, 0xd4, 0x4f, 0x30, 0x9e,
|
||||
0x48, 0x12, 0x36, 0x5a, 0xf9, 0xce, 0xd9, 0xb9, 0xb7, 0xda, 0xb7, 0x21, 0xd0, 0xb6, 0x8f, 0x9d,
|
||||
0x7d, 0x78, 0x08, 0xef, 0xe0, 0x8e, 0xcb, 0xfd, 0x82, 0x96, 0x7d, 0xd3, 0xb1, 0x1c, 0x2c, 0xe9,
|
||||
0xd7, 0x07, 0x76, 0xff, 0x56, 0x36, 0x73, 0x1c, 0x82, 0x38, 0x08, 0x5f, 0xdd, 0xdf, 0x05, 0x94,
|
||||
0x55, 0xbc, 0x0d, 0x48, 0x32, 0x2a, 0x0d, 0xac, 0x41, 0x28, 0x47, 0x71, 0x87, 0x61, 0x14, 0x81,
|
||||
0xd7, 0xea, 0x95, 0x82, 0x16, 0x56, 0x8d, 0xe2, 0xcd, 0xd5, 0xde, 0xba, 0x9f, 0x6a, 0x76, 0x50,
|
||||
0x9c, 0x1f, 0x8e, 0xb5, 0xc5, 0x50, 0x78, 0x2f, 0x43, 0x2b, 0xba, 0xf7, 0xb0, 0xc4, 0x79, 0x6d,
|
||||
0x78, 0xef, 0x79, 0x7b, 0xd3, 0xbb, 0x1d, 0x2c, 0xb7, 0xbb, 0x37, 0xee, 0xb9, 0x4d, 0x05, 0x35,
|
||||
0x3c, 0xf8, 0x62, 0x7c, 0xca, 0x7e, 0xde, 0xa0, 0x8b, 0xb5, 0x67, 0x78, 0xb0, 0x78, 0x42, 0x29,
|
||||
0x58, 0x1b, 0xe2, 0x14, 0x86, 0x38, 0x6c, 0x5c, 0x61, 0xad, 0xbb, 0xff, 0xd3, 0x8b, 0x35, 0xe8,
|
||||
0xa2, 0x01, 0x6a, 0x6f, 0xdd, 0xa5, 0x91, 0xc7, 0x9c, 0xbe, 0xe1, 0x1e, 0x83, 0x37, 0x79, 0x0c,
|
||||
0xe3, 0xab, 0x46, 0x43, 0x7d, 0x38, 0xa3, 0x80, 0x45, 0xc6, 0x21, 0x3f, 0x74, 0x1e, 0x32, 0x0e,
|
||||
0xd9, 0xf7, 0xb1, 0xd1, 0x59, 0x9f, 0x6d, 0x1f, 0xa8, 0x59, 0xeb, 0x13, 0xcc, 0xa9, 0xa7, 0x7e,
|
||||
0xff, 0xf1, 0x94, 0xc8, 0x34, 0xbb, 0xfc, 0x2d, 0xb8, 0xd6, 0xda, 0x6a, 0xf6, 0x37, 0x70, 0xed,
|
||||
0xee, 0x7a, 0xe3, 0x0e, 0x5c, 0x7b, 0x58, 0x0c, 0x5e, 0xe5, 0x45, 0x87, 0x83, 0x9e, 0x02, 0x4d,
|
||||
0xc5, 0xa8, 0x5b, 0x78, 0x7e, 0x31, 0x66, 0x77, 0x16, 0x74, 0xfc, 0xef, 0xe1, 0x90, 0x83, 0x03,
|
||||
0xc1, 0x66, 0x4a, 0xe3, 0x53, 0xa3, 0xda, 0x94, 0xce, 0xa7, 0x26, 0xdd, 0x12, 0x87, 0x22, 0x9e,
|
||||
0xdf, 0xfc, 0x55, 0x8f, 0xd2, 0x0d, 0x93, 0x38, 0xf6, 0x16, 0xf2, 0x3a, 0xed, 0xd5, 0xa6, 0x83,
|
||||
0xcd, 0x0f, 0x1c, 0xc1, 0xaa, 0xf7, 0x69, 0x2f, 0xe4, 0xa0, 0xd3, 0xb3, 0x7b, 0x04, 0x3f, 0xd4,
|
||||
0x7a, 0xfa, 0xf0, 0x96, 0x65, 0x1e, 0xda, 0x84, 0x2e, 0xc7, 0x27, 0x5e, 0xb9, 0x4a, 0xfe, 0x4b,
|
||||
0x1c, 0xc8, 0x30, 0xdd, 0x5b, 0x0c, 0x8b, 0x82, 0x7d, 0x05, 0xed, 0x02, 0x67, 0x83, 0xb1, 0xf8,
|
||||
0x1e, 0x77, 0x86, 0xa3, 0x91, 0xf8, 0x1e, 0xb1, 0xa0, 0x2f, 0x3c, 0xcf, 0x5b, 0xd0, 0x16, 0xa3,
|
||||
0x91, 0x3c, 0x1e, 0xf3, 0x4d, 0x24, 0xcc, 0x8f, 0x57, 0xf3, 0x6d, 0xad, 0x67, 0x74, 0x0e, 0x8b,
|
||||
0x42, 0x1e, 0x8d, 0x36, 0xd0, 0xd1, 0x1a, 0xaa, 0x13, 0x74, 0x3c, 0x96, 0x8b, 0x62, 0xc8, 0x0e,
|
||||
0xed, 0x93, 0x23, 0x62, 0xe8, 0x10, 0xb9, 0x71, 0x8d, 0x3c, 0x39, 0xd6, 0x30, 0x25, 0xd3, 0x14,
|
||||
0x43, 0x29, 0x51, 0xc6, 0x1a, 0xa7, 0x48, 0x6f, 0x32, 0x6c, 0x9c, 0x22, 0xbd, 0xb2, 0x11, 0xa6,
|
||||
0xe7, 0xed, 0x84, 0x82, 0x53, 0x9c, 0x09, 0xef, 0xf1, 0x99, 0x4f, 0x0f, 0x39, 0xcb, 0xab, 0x87,
|
||||
0xbc, 0xe4, 0xe3, 0x96, 0x03, 0xd5, 0x1c, 0xe4, 0x6c, 0xab, 0x9f, 0x5e, 0x03, 0x4e, 0x5a, 0x5b,
|
||||
0x87, 0xc2, 0xcd, 0x66, 0x2c, 0x28, 0xee, 0x38, 0xd2, 0xfc, 0xe4, 0xb7, 0xf6, 0x3a, 0xbf, 0x36,
|
||||
0x52, 0xf9, 0x6f, 0xf5, 0x80, 0x3b, 0xf9, 0x8d, 0x07, 0x1c, 0xde, 0xeb, 0x54, 0x8e, 0xbc, 0xaa,
|
||||
0xf1, 0x63, 0xe1, 0x99, 0xb6, 0x15, 0xcc, 0x67, 0xba, 0x00, 0xe8, 0xdb, 0x80, 0x0b, 0x01, 0x58,
|
||||
0xc5, 0xf8, 0x1d, 0x86, 0x3e, 0xd6, 0xcf, 0x9d, 0x67, 0x2c, 0x96, 0xef, 0xe0, 0x88, 0x9f, 0xf9,
|
||||
0xe2, 0x19, 0x50, 0x23, 0xaf, 0x75, 0x94, 0xcf, 0x68, 0xfa, 0xf8, 0x75, 0x51, 0xe4, 0x85, 0x44,
|
||||
0x97, 0x31, 0xc8, 0x4d, 0x68, 0xd0, 0xcb, 0xea, 0xd9, 0x51, 0x4f, 0xc0, 0x5a, 0xc3, 0x28, 0xf5,
|
||||
0xe2, 0xd9, 0x8f, 0xec, 0x10, 0x3b, 0x60, 0xe5, 0x7d, 0x18, 0x47, 0x64, 0x2c, 0x4c, 0xbe, 0xe8,
|
||||
0xfd, 0xab, 0xcc, 0xb3, 0xde, 0xcc, 0x4f, 0x91, 0xd7, 0xa2, 0xf2, 0xc5, 0x40, 0x4c, 0x44, 0x71,
|
||||
0x8c, 0xfa, 0x5f, 0xbe, 0xc0, 0x69, 0x60, 0x12, 0x21, 0x00, 0xa2, 0xd2, 0x3b, 0xa6, 0xf4, 0xf8,
|
||||
0x0c, 0x5f, 0x4a, 0xfe, 0xa5, 0xb3, 0x8c, 0xd2, 0xda, 0x85, 0x12, 0xe5, 0x6d, 0xf1, 0x33, 0x30,
|
||||
0xc1, 0x69, 0x07, 0x62, 0x5b, 0x2c, 0xa6, 0x21, 0x56, 0x53, 0xc0, 0x5e, 0xaf, 0x7e, 0x03, 0x67,
|
||||
0x1c, 0x11, 0x40, 0x59, 0x91, 0x1e, 0xb0, 0x91, 0xa0, 0x8b, 0x2e, 0xae, 0x68, 0x27, 0x52, 0x82,
|
||||
0xc3, 0x46, 0x67, 0x79, 0x7d, 0xb8, 0x16, 0x54, 0xe2, 0x0e, 0xf8, 0xcf, 0x56, 0xeb, 0x30, 0x39,
|
||||
0x6c, 0xfd, 0xb3, 0x75, 0xdc, 0x3a, 0x4c, 0x7f, 0x4f, 0xfe, 0x38, 0x6c, 0x49, 0x6d, 0x36, 0xd3,
|
||||
0xa9, 0x49, 0x7d, 0x7b, 0xd0, 0xe0, 0xf1, 0x1a, 0x6a, 0xb8, 0x73, 0xcf, 0xf7, 0x63, 0x3c, 0x4b,
|
||||
0x06, 0x74, 0x0d, 0x48, 0xa2, 0x41, 0xa9, 0xf4, 0xa3, 0x77, 0xaa, 0xa4, 0x51, 0x36, 0xae, 0x26,
|
||||
0xe2, 0xb6, 0xab, 0xa3, 0x04, 0x3e, 0x53, 0xd6, 0xe6, 0xb7, 0xd6, 0x6d, 0xd9, 0x3b, 0xb7, 0x47,
|
||||
0x3d, 0xf1, 0xd7, 0x02, 0xd2, 0x11, 0x2b, 0x35, 0xc7, 0x83, 0x22, 0xcf, 0xab, 0x25, 0xbf, 0xe3,
|
||||
0x1f, 0x3c, 0x0f, 0xdd, 0x91, 0xa1, 0xa9, 0x43, 0x7e, 0xfb, 0x3e, 0x78, 0xae, 0x8e, 0x8c, 0xc0,
|
||||
0x0a, 0x87, 0xfc, 0x5e, 0x7c, 0xf0, 0x5c, 0x0b, 0xf5, 0xbe, 0xa1, 0x0d, 0xf9, 0x8d, 0xf5, 0xe0,
|
||||
0xb9, 0xa1, 0x3b, 0x41, 0x40, 0xc3, 0x92, 0x23, 0xab, 0xb4, 0xb0, 0x6a, 0x82, 0x82, 0x37, 0xd9,
|
||||
0xe0, 0xd7, 0xa8, 0x08, 0xfd, 0xcc, 0xbf, 0x55, 0x82, 0xaa, 0x48, 0x3f, 0x8f, 0xf2, 0xeb, 0xe5,
|
||||
0x14, 0xe9, 0x2d, 0xc9, 0x06, 0xfe, 0xbc, 0xca, 0x87, 0x57, 0x49, 0x58, 0x4d, 0x06, 0x8e, 0xba,
|
||||
0xb8, 0x1a, 0x6e, 0xce, 0x53, 0xfc, 0xc7, 0xef, 0x01, 0x0c, 0xd0, 0xe6, 0xc4, 0x3b, 0xc3, 0x59,
|
||||
0x5e, 0x26, 0x24, 0xd6, 0xc0, 0x1f, 0x95, 0x79, 0x3a, 0xaf, 0xa2, 0x61, 0x95, 0xcf, 0x06, 0x96,
|
||||
0xf5, 0xdd, 0x30, 0x8d, 0xe2, 0x6a, 0x60, 0xa9, 0xdf, 0x0d, 0xab, 0xc2, 0xcf, 0x4a, 0x18, 0x64,
|
||||
0x3a, 0x60, 0x5f, 0x29, 0x2a, 0x43, 0x5b, 0x06, 0xa0, 0x4b, 0x0f, 0x9c, 0xa5, 0x92, 0xb4, 0x8a,
|
||||
0x8a, 0x41, 0x58, 0xe4, 0x33, 0xb9, 0x9c, 0xf8, 0x61, 0x7e, 0x05, 0xe8, 0xec, 0x5a, 0x62, 0x0f,
|
||||
0xfa, 0xcf, 0xc9, 0x91, 0x34, 0x9d, 0xce, 0xad, 0x52, 0x86, 0xe5, 0x92, 0x33, 0x87, 0x43, 0xe7,
|
||||
0x77, 0xc3, 0x49, 0x94, 0x8c, 0x27, 0xd5, 0x40, 0xd3, 0x17, 0x93, 0x21, 0xe7, 0x5f, 0x26, 0x06,
|
||||
0x30, 0x04, 0x6a, 0x2a, 0x44, 0x92, 0x19, 0x2f, 0x4c, 0x2e, 0x31, 0x51, 0xb0, 0x55, 0xf5, 0x19,
|
||||
0xb1, 0x4a, 0x08, 0xde, 0xef, 0x2f, 0xae, 0x6e, 0x9f, 0x97, 0xe9, 0xcb, 0x65, 0x0d, 0xac, 0x02,
|
||||
0xbc, 0x51, 0xc6, 0x60, 0xfb, 0xc4, 0x5a, 0xe5, 0x12, 0xdb, 0x16, 0x47, 0x68, 0x20, 0x75, 0x6f,
|
||||
0xa2, 0x34, 0xcd, 0xaf, 0x3a, 0xb4, 0xcb, 0xc7, 0xe5, 0xee, 0xcb, 0x70, 0xc0, 0x66, 0x6b, 0xde,
|
||||
0xee, 0xb1, 0x86, 0x9d, 0xcf, 0xd9, 0xaa, 0x57, 0x7b, 0xac, 0x62, 0x27, 0x7d, 0x5a, 0xf4, 0x69,
|
||||
0x8f, 0x45, 0x57, 0x93, 0xa4, 0xe2, 0xab, 0xde, 0xed, 0xb4, 0x8a, 0x2e, 0x16, 0xf2, 0x82, 0x7e,
|
||||
0xd9, 0x17, 0x0a, 0x11, 0xd7, 0x0c, 0xc1, 0x8d, 0xcf, 0xef, 0x1a, 0xba, 0x8b, 0x24, 0x47, 0x04,
|
||||
0xaf, 0xe5, 0x3e, 0xdf, 0x69, 0x5b, 0x6c, 0x72, 0x53, 0x13, 0xfb, 0x74, 0x0f, 0x09, 0x90, 0x66,
|
||||
0xbe, 0xce, 0xf3, 0xa4, 0xe4, 0x52, 0x5c, 0xec, 0xb1, 0x72, 0x65, 0x51, 0xa5, 0xca, 0xf3, 0xb4,
|
||||
0xfc, 0x8f, 0x7d, 0xeb, 0xf2, 0x9b, 0xd4, 0xfe, 0x7e, 0x5f, 0x5f, 0xa2, 0x9b, 0x91, 0x65, 0x9c,
|
||||
0x67, 0x95, 0x1c, 0xfb, 0xd3, 0x24, 0xbd, 0x59, 0x85, 0xef, 0x9b, 0xac, 0xd3, 0x7d, 0x17, 0xa5,
|
||||
0x8b, 0xa8, 0x4a, 0x02, 0xbf, 0x5b, 0x22, 0x32, 0xe5, 0x32, 0x2a, 0x92, 0x78, 0x58, 0x45, 0xd7,
|
||||
0x95, 0xec, 0xa7, 0xc9, 0x38, 0x1b, 0x04, 0x11, 0xfd, 0xb1, 0xc9, 0x63, 0x4e, 0xcf, 0x37, 0xa3,
|
||||
0xbc, 0xd4, 0xe1, 0x44, 0x3b, 0xeb, 0x90, 0xa4, 0xf0, 0x14, 0x29, 0x45, 0xad, 0x27, 0x91, 0x22,
|
||||
0x9a, 0x45, 0x7e, 0x35, 0xc8, 0x72, 0xf1, 0x55, 0x87, 0xf9, 0x55, 0xe5, 0x07, 0x13, 0x6a, 0xb1,
|
||||
0x06, 0x71, 0x72, 0x1d, 0x85, 0xc3, 0x7a, 0xc6, 0xa1, 0x24, 0xd6, 0xb9, 0xa5, 0xbf, 0x8b, 0x59,
|
||||
0xd6, 0x68, 0xdc, 0x26, 0x71, 0xe1, 0x4f, 0xa3, 0xa5, 0xe8, 0xce, 0x07, 0xd4, 0x9c, 0x0f, 0x47,
|
||||
0x79, 0x11, 0x22, 0xa9, 0xa8, 0xfb, 0x65, 0x97, 0xe1, 0x03, 0x19, 0x50, 0x50, 0xb3, 0x29, 0x01,
|
||||
0xfc, 0xc7, 0x09, 0xef, 0xb6, 0x5c, 0x8c, 0xd9, 0x9f, 0xdb, 0x08, 0xa9, 0x42, 0x96, 0x47, 0x45,
|
||||
0x4a, 0xd3, 0x37, 0xd4, 0x34, 0x75, 0x81, 0xde, 0x71, 0xcf, 0xf4, 0x98, 0x64, 0xb3, 0x79, 0xb5,
|
||||
0xdc, 0x4f, 0xe8, 0x07, 0x7c, 0x63, 0xe3, 0x11, 0xb7, 0xa3, 0x79, 0x55, 0xe5, 0x59, 0xdd, 0xf1,
|
||||
0x6a, 0x66, 0x6f, 0x98, 0x88, 0x0b, 0x23, 0xb4, 0xaf, 0x58, 0xc1, 0x44, 0x82, 0x92, 0x92, 0x50,
|
||||
0xaa, 0xe3, 0x8b, 0xa0, 0x18, 0xe5, 0xd8, 0x74, 0x3a, 0xd0, 0xa0, 0xd3, 0xbf, 0x9b, 0x5f, 0x5e,
|
||||
0xa6, 0x77, 0xe1, 0xb7, 0xda, 0x81, 0xdf, 0xbf, 0x9b, 0x3b, 0x66, 0xa3, 0xdf, 0xd9, 0x1f, 0x18,
|
||||
0x66, 0xf3, 0xe9, 0x28, 0x2a, 0xfe, 0xf8, 0xbb, 0x38, 0xe5, 0x4e, 0x64, 0x44, 0xd3, 0x3a, 0x0d,
|
||||
0x96, 0x7c, 0xff, 0x58, 0xca, 0x57, 0xd1, 0xe8, 0x4b, 0x82, 0xc0, 0x9e, 0x21, 0xe6, 0x30, 0x17,
|
||||
0x44, 0x3c, 0x52, 0x84, 0xcb, 0xcb, 0x26, 0x04, 0x51, 0xef, 0xae, 0x1b, 0xc4, 0x79, 0x30, 0x2f,
|
||||
0x97, 0xf9, 0xbc, 0xa2, 0xc8, 0x1f, 0xdc, 0x87, 0x31, 0x58, 0x6d, 0x5d, 0x82, 0x9f, 0xa8, 0x90,
|
||||
0x8b, 0x79, 0x96, 0xf9, 0xa3, 0x34, 0x92, 0xe1, 0xfd, 0xc1, 0x97, 0x87, 0x8a, 0x75, 0x30, 0x2f,
|
||||
0x4a, 0x08, 0x37, 0xcb, 0x93, 0xed, 0x14, 0x53, 0x93, 0x68, 0x07, 0x6a, 0xd5, 0x04, 0x3a, 0xdc,
|
||||
0xd3, 0xe3, 0x37, 0x11, 0xb6, 0xca, 0xc9, 0xda, 0x56, 0x6d, 0xe7, 0xe8, 0x3e, 0xb7, 0x42, 0x93,
|
||||
0xd3, 0xc7, 0x15, 0xc9, 0x72, 0x3d, 0x7c, 0xfa, 0x5e, 0xce, 0xa7, 0xf9, 0x9f, 0x32, 0x1b, 0xfc,
|
||||
0xb7, 0x54, 0x53, 0x23, 0xf0, 0xbf, 0x56, 0xcb, 0x2e, 0xe2, 0x97, 0xdf, 0x2a, 0x37, 0xcb, 0xa3,
|
||||
0x33, 0xbf, 0xa0, 0xbf, 0xa0, 0xe5, 0x21, 0x20, 0x5a, 0xd1, 0x3a, 0xe0, 0xce, 0xcc, 0x43, 0x4c,
|
||||
0x50, 0xf2, 0x95, 0x51, 0xc9, 0xa3, 0xa2, 0x1e, 0x78, 0xcf, 0x9f, 0x54, 0xae, 0x58, 0x39, 0x87,
|
||||
0xe1, 0xf7, 0x5e, 0xc9, 0xed, 0xb1, 0xb7, 0x56, 0x6b, 0x26, 0xa1, 0x43, 0x02, 0x3b, 0x1b, 0x88,
|
||||
0x33, 0x82, 0x94, 0x84, 0xde, 0x24, 0x4f, 0xa1, 0x8b, 0x7f, 0x21, 0xb3, 0xb0, 0x19, 0x46, 0x95,
|
||||
0xca, 0x77, 0x2f, 0x28, 0xcb, 0xe3, 0x15, 0xfe, 0x51, 0x8f, 0xff, 0x8d, 0x34, 0x35, 0x02, 0x52,
|
||||
0x9e, 0xb1, 0x3f, 0x49, 0x58, 0xff, 0x59, 0xaa, 0x14, 0xd0, 0x6f, 0xfd, 0xde, 0xe7, 0xcf, 0xa8,
|
||||
0x9d, 0x49, 0xf6, 0x99, 0x16, 0x7f, 0xfe, 0xf8, 0xfa, 0xe5, 0x4f, 0xbf, 0x7d, 0xfe, 0x4c, 0x84,
|
||||
0x66, 0x7e, 0x26, 0x30, 0xe8, 0x0f, 0x01, 0x8e, 0x3f, 0xf0, 0x13, 0xa2, 0xa2, 0x28, 0xd8, 0x1c,
|
||||
0x30, 0x42, 0x59, 0x8c, 0x25, 0x46, 0xc7, 0xbb, 0x5b, 0x19, 0xb9, 0xb8, 0xea, 0x4a, 0x0a, 0x75,
|
||||
0x98, 0x2f, 0xa2, 0x22, 0x86, 0xe6, 0x07, 0x93, 0x24, 0x0c, 0x23, 0x1c, 0xc7, 0xa2, 0xa2, 0xc4,
|
||||
0x0a, 0x4f, 0x53, 0x34, 0xe9, 0x7a, 0x9a, 0x66, 0xa5, 0x37, 0xa9, 0xaa, 0xd9, 0xa0, 0xd7, 0xbb,
|
||||
0xba, 0xba, 0x52, 0xae, 0x0c, 0x25, 0x2f, 0xc6, 0x3d, 0x1d, 0x27, 0x98, 0x1e, 0xa8, 0x80, 0x56,
|
||||
0x18, 0xc5, 0xe5, 0xb1, 0xd4, 0xeb, 0x7d, 0x60, 0x4d, 0x08, 0xfd, 0x19, 0x76, 0xa9, 0x04, 0xf9,
|
||||
0xb4, 0x17, 0xa3, 0x11, 0x04, 0x27, 0x37, 0xd3, 0x51, 0x9e, 0x92, 0x5a, 0xd2, 0xac, 0x90, 0x67,
|
||||
0x64, 0x5f, 0x99, 0x5f, 0x2b, 0x48, 0x8b, 0x24, 0xba, 0x7a, 0x95, 0xe3, 0xf4, 0xa8, 0x4a, 0xaa,
|
||||
0xa4, 0xa9, 0xba, 0xc9, 0x1e, 0xad, 0xe3, 0x23, 0xfa, 0x8d, 0x41, 0x0a, 0xbd, 0xd6, 0xcf, 0xa6,
|
||||
0x63, 0x2b, 0xa6, 0x64, 0x6b, 0xa6, 0x62, 0x06, 0x32, 0x9e, 0x9a, 0xe1, 0x48, 0xaa, 0xac, 0x5b,
|
||||
0x8a, 0x2d, 0x6b, 0x9a, 0x62, 0xda, 0x1a, 0xff, 0xa6, 0xc7, 0x42, 0x36, 0x6d, 0x55, 0x71, 0x02,
|
||||
0x75, 0x85, 0xc7, 0x10, 0x74, 0x06, 0x93, 0xd6, 0x58, 0x25, 0x1b, 0x72, 0x90, 0xb4, 0x06, 0x2d,
|
||||
0xc4, 0x52, 0x89, 0x2d, 0x75, 0xe5, 0x1a, 0x7c, 0xb3, 0xfe, 0x4f, 0x30, 0xd6, 0x23, 0xce, 0xee,
|
||||
0xf0, 0xe7, 0xf6, 0x75, 0xac, 0x96, 0xc1, 0xbc, 0x62, 0xf5, 0xc1, 0x9f, 0xe6, 0xba, 0xb2, 0xe1,
|
||||
0x2a, 0xae, 0x69, 0xca, 0x7a, 0x5f, 0x53, 0x2c, 0x03, 0x1b, 0xea, 0x8a, 0xd9, 0x97, 0x81, 0x67,
|
||||
0xe9, 0xce, 0xea, 0x25, 0x26, 0x35, 0xdb, 0x51, 0x5c, 0x7b, 0x35, 0xe2, 0x0b, 0xb0, 0x89, 0x63,
|
||||
0x2a, 0x86, 0x6b, 0x49, 0xba, 0xad, 0x38, 0x16, 0x38, 0xb2, 0xa1, 0x82, 0xbe, 0x23, 0xf5, 0xfb,
|
||||
0x8a, 0xdd, 0xc7, 0xb6, 0x06, 0xb0, 0x5c, 0x53, 0x32, 0x5d, 0x45, 0xb3, 0x64, 0xc0, 0x5c, 0xcd,
|
||||
0x82, 0x54, 0xd8, 0xa8, 0x4f, 0xdc, 0x1b, 0x58, 0x0a, 0x65, 0xba, 0xb6, 0x62, 0xeb, 0xa6, 0xac,
|
||||
0x19, 0xb6, 0x62, 0xa9, 0x9a, 0x84, 0x69, 0xcb, 0x92, 0x4d, 0x45, 0x35, 0x4c, 0x49, 0xef, 0x2b,
|
||||
0x8e, 0x6a, 0x49, 0x86, 0x62, 0x3b, 0x86, 0x84, 0xcd, 0x1c, 0x52, 0x58, 0x5f, 0xd1, 0x0d, 0xb3,
|
||||
0x94, 0xf9, 0x24, 0xc7, 0x90, 0xf9, 0xa4, 0x40, 0x81, 0x8c, 0x24, 0x97, 0x65, 0x49, 0xa6, 0xa6,
|
||||
0xd8, 0x16, 0xf1, 0xd1, 0x57, 0xfa, 0xaa, 0x8e, 0xa5, 0xd0, 0xc0, 0x66, 0x68, 0x68, 0xae, 0xa2,
|
||||
0xea, 0x3a, 0x59, 0xd5, 0x01, 0x51, 0x15, 0x1a, 0x07, 0xa7, 0x3a, 0x78, 0x32, 0x0c, 0x20, 0xd6,
|
||||
0x9f, 0x25, 0x7b, 0xca, 0x0d, 0xb8, 0xcc, 0x9e, 0xcc, 0x92, 0xb6, 0xa2, 0x39, 0x7d, 0xd9, 0xc5,
|
||||
0xb6, 0x16, 0x54, 0xd3, 0x57, 0x8c, 0xbe, 0xa0, 0xa2, 0xc9, 0x9c, 0x08, 0x89, 0x07, 0xb1, 0x74,
|
||||
0x2e, 0x97, 0xac, 0x6b, 0x8a, 0x6e, 0x43, 0xa7, 0x8e, 0xa2, 0x3b, 0x8e, 0x60, 0x5e, 0x16, 0xf2,
|
||||
0x11, 0x86, 0x2e, 0xd0, 0x25, 0xc2, 0x70, 0x05, 0x3a, 0x97, 0xae, 0xcf, 0xd1, 0x2d, 0xa6, 0x63,
|
||||
0x13, 0x36, 0x37, 0x14, 0x8d, 0x71, 0xde, 0x57, 0x4c, 0x28, 0x1e, 0x0a, 0x77, 0x74, 0xae, 0x53,
|
||||
0x03, 0x6f, 0xe8, 0xd4, 0x74, 0x5d, 0xc9, 0x82, 0xdf, 0x68, 0xb6, 0x64, 0xf7, 0x15, 0x4d, 0xe3,
|
||||
0x2b, 0xfb, 0x16, 0x5b, 0xa2, 0x43, 0x0d, 0x62, 0xc8, 0x8d, 0xe5, 0x70, 0x1f, 0x87, 0x87, 0x70,
|
||||
0xdf, 0xa0, 0xbd, 0x20, 0x80, 0xaa, 0x0b, 0xcb, 0x4b, 0xc2, 0x55, 0xb8, 0x73, 0x48, 0xec, 0x65,
|
||||
0x0b, 0xe7, 0x90, 0x9a, 0xce, 0xc1, 0x47, 0x35, 0x7f, 0xec, 0xf1, 0x20, 0x3b, 0xde, 0x8e, 0x36,
|
||||
0xba, 0x32, 0xda, 0x21, 0xca, 0x5c, 0xd7, 0x81, 0x17, 0x3b, 0xd0, 0xa7, 0x3e, 0x91, 0xfb, 0xb6,
|
||||
0xf3, 0x54, 0xa8, 0x95, 0xf7, 0x86, 0xd6, 0x84, 0x56, 0xf2, 0x00, 0x02, 0xa1, 0x4d, 0x9c, 0x69,
|
||||
0x9b, 0x38, 0x2b, 0xe5, 0xda, 0xcc, 0xe3, 0x91, 0xc5, 0x79, 0xb2, 0x6c, 0xe3, 0xff, 0x1d, 0x4f,
|
||||
0x86, 0xda, 0x7f, 0x8c, 0x27, 0xfd, 0x5b, 0x79, 0xd2, 0xbf, 0x89, 0xa7, 0xbe, 0x4d, 0x91, 0x64,
|
||||
0x39, 0x94, 0x20, 0x4d, 0x5d, 0x31, 0x4c, 0x4a, 0x40, 0x34, 0x29, 0x1b, 0xc8, 0x18, 0xe4, 0x4f,
|
||||
0xf4, 0x4d, 0x8f, 0xb2, 0x36, 0x21, 0xad, 0x67, 0x25, 0xbe, 0x01, 0x03, 0x49, 0x1b, 0x50, 0x6d,
|
||||
0x62, 0x83, 0xf6, 0x27, 0xa7, 0xa6, 0x5b, 0x36, 0x97, 0x1c, 0x1e, 0xcf, 0x25, 0x67, 0x02, 0x38,
|
||||
0xd6, 0x86, 0xd3, 0x92, 0x4f, 0x6c, 0x24, 0xda, 0x3c, 0xe4, 0x1a, 0x48, 0xae, 0x4d, 0x6c, 0xd4,
|
||||
0x26, 0x3f, 0x2a, 0xab, 0x28, 0x06, 0xf7, 0xc8, 0xaa, 0x6d, 0x64, 0xc5, 0xbc, 0x40, 0xb8, 0x57,
|
||||
0xe8, 0xf2, 0x5e, 0xa1, 0x91, 0xff, 0xd9, 0x22, 0xf7, 0x51, 0xe9, 0x2d, 0x4d, 0xff, 0x3f, 0x94,
|
||||
0xde, 0xe9, 0xab, 0x4f, 0x4b, 0xff, 0xa4, 0xa5, 0xb5, 0x1d, 0x2d, 0xbd, 0xf6, 0xf1, 0xff, 0x91,
|
||||
0xac, 0x0f, 0xe5, 0xb1, 0x69, 0x4e, 0x97, 0xc4, 0x4f, 0xe6, 0x31, 0x4b, 0x37, 0xc1, 0x34, 0xcd,
|
||||
0x12, 0xd7, 0xaa, 0xa2, 0xf5, 0x5d, 0x62, 0x1b, 0x49, 0xd3, 0xb5, 0x1d, 0xd9, 0x32, 0x91, 0xc1,
|
||||
0x61, 0x5b, 0x0c, 0x55, 0x17, 0xb5, 0xc5, 0x32, 0x50, 0x45, 0x4a, 0xf1, 0x46, 0x51, 0x51, 0x51,
|
||||
0x44, 0x57, 0x23, 0x81, 0x44, 0x25, 0x48, 0xb3, 0x14, 0x1d, 0xc9, 0x1a, 0xe5, 0x41, 0xc7, 0xf6,
|
||||
0xaa, 0x46, 0xb4, 0x6d, 0xc5, 0x75, 0x91, 0xc6, 0xa1, 0x19, 0x0b, 0x85, 0xc2, 0x30, 0x58, 0x39,
|
||||
0x37, 0x51, 0x75, 0x6d, 0xd4, 0x00, 0x83, 0x55, 0x68, 0x07, 0xcd, 0x93, 0x45, 0x35, 0xd9, 0x55,
|
||||
0x0c, 0xdd, 0x62, 0x39, 0xde, 0xd0, 0x0d, 0x09, 0x05, 0x4d, 0xb5, 0x54, 0xaa, 0x48, 0x26, 0xfa,
|
||||
0x06, 0xd4, 0x12, 0xdb, 0x94, 0x2d, 0x4b, 0x31, 0x49, 0x1a, 0xd4, 0x12, 0x13, 0x64, 0x40, 0x5a,
|
||||
0x87, 0xd6, 0x5c, 0x14, 0x16, 0x14, 0x28, 0xc5, 0x45, 0xe5, 0xd6, 0x55, 0x86, 0xa1, 0x2a, 0x86,
|
||||
0x61, 0x53, 0x47, 0xe0, 0xa2, 0xcd, 0x40, 0xfd, 0xd2, 0xf5, 0x12, 0x95, 0x90, 0x2a, 0x37, 0x8a,
|
||||
0x04, 0x4a, 0x95, 0xa1, 0xa8, 0x36, 0x4a, 0xbb, 0x03, 0x2e, 0x11, 0xa1, 0x60, 0x4b, 0xc5, 0x24,
|
||||
0x9a, 0x03, 0x03, 0x2d, 0x8d, 0xe9, 0xa0, 0x76, 0xba, 0x92, 0x06, 0x8d, 0xa3, 0x42, 0xaf, 0x87,
|
||||
0xae, 0xc1, 0x8d, 0x8b, 0x22, 0x85, 0xa2, 0xd4, 0xc7, 0x04, 0xc4, 0x05, 0x9b, 0x06, 0x5e, 0x8d,
|
||||
0x27, 0x2a, 0x9c, 0xa9, 0x99, 0xa4, 0x79, 0xec, 0xdf, 0xef, 0xc3, 0x96, 0x16, 0x76, 0xd0, 0x56,
|
||||
0x3b, 0xf0, 0x0d, 0x1d, 0x70, 0xad, 0xa9, 0x7d, 0xd4, 0x62, 0xa8, 0x80, 0xb8, 0xd6, 0x0c, 0x74,
|
||||
0x13, 0xa6, 0xed, 0x0a, 0xa6, 0x38, 0x87, 0xe4, 0x32, 0x1a, 0xf5, 0x0c, 0x00, 0x9b, 0x4c, 0x0e,
|
||||
0x53, 0x08, 0x15, 0xd0, 0xae, 0x0e, 0xf2, 0x1e, 0x59, 0xa1, 0x6f, 0x50, 0xa1, 0x74, 0x4c, 0x28,
|
||||
0x51, 0x85, 0x0c, 0x8e, 0xd0, 0x8c, 0x2d, 0x14, 0x65, 0x91, 0x12, 0x35, 0xdb, 0x96, 0x4c, 0xf8,
|
||||
0x10, 0x7a, 0x20, 0xa8, 0xc0, 0x42, 0x7c, 0x40, 0x3c, 0x98, 0x66, 0xa5, 0xee, 0x95, 0xfa, 0x5d,
|
||||
0x15, 0x75, 0x13, 0xba, 0x80, 0x8c, 0xae, 0x43, 0xfd, 0x99, 0x62, 0x50, 0x69, 0xdf, 0x32, 0xa4,
|
||||
0x18, 0xff, 0xf9, 0x33, 0xd4, 0x8c, 0x0e, 0xaa, 0x4f, 0xf8, 0x8e, 0x4b, 0xc9, 0x0e, 0xd5, 0xb8,
|
||||
0x6f, 0x6a, 0x64, 0x5b, 0xd7, 0x41, 0x3e, 0x07, 0x15, 0x0d, 0x60, 0x1d, 0x3e, 0xa6, 0xa2, 0x39,
|
||||
0x5b, 0x8d, 0x4d, 0x9d, 0xf6, 0x25, 0x25, 0xe9, 0x36, 0x78, 0x83, 0x85, 0x75, 0xaa, 0xd4, 0x16,
|
||||
0x78, 0x24, 0xaf, 0x68, 0x3c, 0x35, 0xc7, 0x65, 0x8d, 0x95, 0x8a, 0xe4, 0x0d, 0x4d, 0x6a, 0xa6,
|
||||
0x68, 0x03, 0xac, 0xd5, 0x2e, 0xab, 0x5d, 0x65, 0x0b, 0xd3, 0xc4, 0xac, 0x4b, 0x4d, 0x04, 0x9a,
|
||||
0x4c, 0xd2, 0x3b, 0xda, 0x33, 0x97, 0x01, 0x35, 0x34, 0xae, 0x16, 0x48, 0xae, 0x86, 0x78, 0xbb,
|
||||
0xd4, 0x78, 0x21, 0xb2, 0x74, 0xe8, 0x1a, 0xab, 0x55, 0x6a, 0x14, 0x11, 0xe5, 0x60, 0xdd, 0x80,
|
||||
0xd5, 0x90, 0x39, 0xa8, 0x24, 0xb9, 0xe8, 0x78, 0x6c, 0x97, 0xbd, 0xfa, 0x62, 0x92, 0x9a, 0x27,
|
||||
0x72, 0x70, 0x7b, 0x3d, 0xe6, 0x8b, 0x28, 0x99, 0x82, 0x45, 0xcd, 0xd0, 0x60, 0x5d, 0x00, 0x55,
|
||||
0x98, 0x12, 0xdd, 0x4c, 0x93, 0x81, 0x1d, 0x82, 0x38, 0xc8, 0xc7, 0x3b, 0xc4, 0xb0, 0x01, 0x53,
|
||||
0x91, 0x5b, 0xa9, 0x20, 0xd3, 0xb7, 0xac, 0x00, 0x11, 0xa0, 0xa9, 0x14, 0xc6, 0x26, 0xc2, 0xd0,
|
||||
0x91, 0x55, 0xf4, 0x6b, 0xba, 0x6c, 0x93, 0xaf, 0xc9, 0xd4, 0x7a, 0xc9, 0xb0, 0xbe, 0xdb, 0x67,
|
||||
0x99, 0xc5, 0x51, 0x0d, 0xb2, 0xb3, 0x46, 0xf9, 0x1b, 0x76, 0x31, 0xa9, 0xd5, 0x83, 0xc3, 0x20,
|
||||
0xa8, 0x11, 0xf9, 0xba, 0x46, 0x28, 0xae, 0x8e, 0xa4, 0x88, 0xa8, 0x40, 0x43, 0x6e, 0x93, 0x6f,
|
||||
0xea, 0x3a, 0x01, 0x5c, 0xea, 0x8e, 0x29, 0x0f, 0x1a, 0x26, 0xb9, 0x23, 0x9c, 0x19, 0x7a, 0x70,
|
||||
0x75, 0xf8, 0x1d, 0x19, 0xcf, 0x65, 0xed, 0x23, 0xfc, 0x4c, 0x8c, 0xe0, 0xe8, 0xae, 0x4b, 0x1a,
|
||||
0xb6, 0x6c, 0xa6, 0x24, 0x62, 0x80, 0x14, 0x8b, 0xd6, 0xce, 0x6c, 0x3e, 0xe1, 0xdf, 0x3a, 0xe5,
|
||||
0x4d, 0xec, 0xac, 0x92, 0x9f, 0xc2, 0xaa, 0xeb, 0xe5, 0x62, 0x33, 0xbc, 0x34, 0xc3, 0x90, 0xa8,
|
||||
0x4f, 0xa7, 0xee, 0x8e, 0x22, 0x55, 0x02, 0x44, 0x17, 0xec, 0xe8, 0x82, 0x37, 0x24, 0x1e, 0x0d,
|
||||
0x51, 0x45, 0x3e, 0xa5, 0x53, 0xee, 0x37, 0x55, 0x47, 0x76, 0xc8, 0x6b, 0x2c, 0x2e, 0x9b, 0x26,
|
||||
0x44, 0xa5, 0x68, 0x33, 0x0c, 0x83, 0xb6, 0x75, 0x1d, 0x17, 0xd1, 0xe6, 0xc2, 0x59, 0x6d, 0x2a,
|
||||
0x69, 0x92, 0x46, 0x34, 0x98, 0x66, 0xf0, 0x62, 0xed, 0x3b, 0x0e, 0x29, 0x64, 0x6f, 0x83, 0xb9,
|
||||
0x79, 0x1f, 0xfb, 0x23, 0xe8, 0xe8, 0x68, 0x20, 0x46, 0xe8, 0xb9, 0x01, 0x2b, 0x65, 0x16, 0xb9,
|
||||
0x20, 0x67, 0xc8, 0x0c, 0xe0, 0x30, 0x80, 0xa9, 0x06, 0x44, 0xa4, 0xcf, 0x62, 0x5d, 0xef, 0x53,
|
||||
0x48, 0x21, 0xc7, 0xea, 0x24, 0xb3, 0x6d, 0x38, 0xb2, 0xc6, 0x05, 0x62, 0xc4, 0xfa, 0x92, 0xb0,
|
||||
0x0d, 0xb7, 0x94, 0x24, 0x6c, 0xc3, 0x2d, 0x25, 0x35, 0xd8, 0x47, 0x80, 0x71, 0xe3, 0x30, 0x4b,
|
||||
0x49, 0xdc, 0x3a, 0xcc, 0x52, 0x12, 0xb7, 0x0e, 0x57, 0x87, 0xc4, 0xcc, 0x63, 0x30, 0x53, 0xb1,
|
||||
0xd6, 0x1d, 0x49, 0x8f, 0xeb, 0x53, 0x62, 0xda, 0x5d, 0x0d, 0xb8, 0x81, 0x44, 0xdb, 0xbd, 0x32,
|
||||
0x94, 0x54, 0x33, 0x11, 0x1d, 0xd5, 0xc8, 0x48, 0xb6, 0xcc, 0x6d, 0xc3, 0x0c, 0x45, 0x41, 0xb4,
|
||||
0x31, 0xb4, 0xcc, 0xd5, 0xc6, 0xec, 0x84, 0x00, 0x81, 0x69, 0x74, 0x66, 0x27, 0x93, 0x82, 0xa1,
|
||||
0xe6, 0x36, 0xcc, 0x36, 0xdc, 0x50, 0x36, 0xcb, 0x42, 0x14, 0xd1, 0xdc, 0x52, 0x52, 0xc3, 0x0d,
|
||||
0x35, 0xe2, 0xce, 0xa5, 0x88, 0x84, 0xa5, 0x58, 0xde, 0x23, 0xeb, 0x90, 0xa5, 0xa4, 0x95, 0xba,
|
||||
0x6c, 0xfe, 0x32, 0x49, 0xcd, 0xb4, 0x71, 0x5f, 0x65, 0x09, 0x71, 0x6d, 0x29, 0x64, 0x59, 0x66,
|
||||
0x02, 0x31, 0x2a, 0x61, 0x1a, 0x6e, 0x24, 0x36, 0x0f, 0xf5, 0x73, 0x0b, 0x06, 0x20, 0xe7, 0x30,
|
||||
0x2b, 0x69, 0x94, 0x6b, 0x6d, 0xd3, 0xe2, 0x56, 0xb2, 0x38, 0x21, 0x97, 0x5b, 0xc9, 0x95, 0x84,
|
||||
0x5d, 0x98, 0x95, 0x74, 0x89, 0xec, 0x62, 0x09, 0x23, 0x09, 0xce, 0x0d, 0x69, 0xc5, 0xb9, 0xc6,
|
||||
0x92, 0x0b, 0x33, 0x12, 0xb1, 0x89, 0x52, 0xc0, 0x8c, 0xa4, 0x3a, 0x5c, 0x19, 0x92, 0x70, 0x5a,
|
||||
0x32, 0x8c, 0xce, 0xad, 0x64, 0x33, 0x6d, 0x22, 0xa3, 0x33, 0x3b, 0xf5, 0x57, 0xa3, 0x55, 0x10,
|
||||
0xad, 0x6c, 0x54, 0xb7, 0x4d, 0xf3, 0xc9, 0xec, 0x43, 0x59, 0x92, 0xdb, 0x86, 0x19, 0x4a, 0x2c,
|
||||
0x17, 0x86, 0x92, 0x98, 0x71, 0x1c, 0x6e, 0x29, 0x89, 0x1b, 0x87, 0x59, 0x4a, 0xf0, 0x63, 0x0a,
|
||||
0xe6, 0x98, 0x6d, 0x6c, 0x61, 0x29, 0xc9, 0xe4, 0x59, 0x95, 0x5b, 0x8a, 0x0b, 0xb8, 0x32, 0x94,
|
||||
0xc4, 0x4d, 0xc3, 0x83, 0x08, 0x76, 0x72, 0xa1, 0x59, 0x6e, 0x27, 0xe1, 0xd8, 0xc2, 0x52, 0xb2,
|
||||
0xb0, 0x0d, 0xb7, 0x94, 0x08, 0x0f, 0x61, 0x29, 0xb9, 0x61, 0xa9, 0x52, 0xd8, 0x07, 0xc7, 0xea,
|
||||
0xda, 0x3c, 0xce, 0xd3, 0x3c, 0x86, 0x24, 0xb2, 0x94, 0xc4, 0x43, 0x48, 0xe2, 0x21, 0x24, 0xd5,
|
||||
0x29, 0xb9, 0x22, 0xbd, 0x09, 0x53, 0x89, 0xf4, 0xc6, 0x4d, 0x25, 0x37, 0x58, 0x67, 0xd9, 0xcd,
|
||||
0xe2, 0x86, 0xb2, 0x64, 0x61, 0x1b, 0x6e, 0x29, 0xb9, 0xa6, 0x0c, 0x5d, 0x16, 0xc6, 0x61, 0x96,
|
||||
0x92, 0x1b, 0xb6, 0x91, 0xff, 0x5d, 0xda, 0x15, 0xf5, 0xc6, 0x6d, 0x23, 0xe1, 0xbf, 0x42, 0xdc,
|
||||
0xbd, 0xf4, 0x80, 0xca, 0x15, 0x29, 0x91, 0xa2, 0x8a, 0x34, 0x40, 0x93, 0xbb, 0xb4, 0x05, 0x2e,
|
||||
0x81, 0x11, 0x07, 0xd7, 0xdc, 0xd3, 0x61, 0x23, 0x3b, 0x89, 0x91, 0x8d, 0x6d, 0x58, 0x4e, 0xda,
|
||||
0xe4, 0xd7, 0xdf, 0x7c, 0xdf, 0x8c, 0x76, 0x25, 0xed, 0xca, 0x51, 0x93, 0x07, 0xef, 0x2e, 0x2d,
|
||||
0x69, 0x48, 0x0e, 0x67, 0x86, 0x33, 0xdf, 0x8c, 0xa4, 0x11, 0x73, 0xa5, 0x35, 0x28, 0x91, 0x69,
|
||||
0xcc, 0xd8, 0xda, 0xd9, 0x12, 0x95, 0xce, 0x2c, 0x9d, 0xae, 0x8d, 0x59, 0xbb, 0xe9, 0x42, 0x9b,
|
||||
0x48, 0x63, 0xa1, 0x92, 0x1a, 0xb8, 0x61, 0xa1, 0x38, 0x9c, 0x41, 0xbd, 0x6d, 0x6d, 0x74, 0xa5,
|
||||
0x0a, 0x5b, 0x1b, 0x5d, 0xa9, 0x9d, 0x89, 0x30, 0x63, 0x1e, 0x48, 0x17, 0x2b, 0x95, 0xcc, 0xc4,
|
||||
0xe9, 0x4a, 0x15, 0x63, 0xe1, 0x6e, 0xd4, 0xc2, 0x65, 0x5b, 0x29, 0xb5, 0x70, 0x71, 0x6c, 0xc8,
|
||||
0x06, 0x6d, 0xc9, 0x7d, 0x01, 0xcc, 0x43, 0x6d, 0xdd, 0x44, 0xbd, 0xc4, 0x91, 0x92, 0x98, 0x1d,
|
||||
0x6e, 0xa5, 0x81, 0x29, 0x1c, 0xb0, 0x4c, 0x19, 0xbe, 0x9a, 0x8c, 0x14, 0xfb, 0x04, 0x1b, 0x9f,
|
||||
0x9f, 0x4a, 0x68, 0x60, 0x0e, 0x7a, 0x04, 0x42, 0x11, 0x69, 0x7a, 0x64, 0xcf, 0x14, 0x0d, 0xaa,
|
||||
0x82, 0x62, 0x52, 0xe2, 0x4b, 0xb5, 0x5e, 0x9c, 0x37, 0xd9, 0x9c, 0x21, 0xac, 0x00, 0x13, 0x1a,
|
||||
0x59, 0x85, 0x00, 0xc1, 0x91, 0x88, 0xbf, 0x24, 0x74, 0x91, 0x1b, 0x42, 0x09, 0xa1, 0xd5, 0xbd,
|
||||
0xa7, 0x4e, 0x45, 0x14, 0xff, 0x84, 0xa6, 0xb0, 0x6c, 0x70, 0x7a, 0x2d, 0x9b, 0x34, 0xdc, 0xbb,
|
||||
0x26, 0x5a, 0x43, 0x76, 0x79, 0x9f, 0x83, 0xa2, 0x46, 0xa9, 0x15, 0x47, 0x07, 0x0e, 0x61, 0x4d,
|
||||
0x6f, 0x16, 0xfe, 0x52, 0x85, 0x7d, 0x5b, 0x7f, 0x37, 0x70, 0xd0, 0x54, 0x9f, 0x80, 0x6e, 0x04,
|
||||
0x76, 0xc6, 0xcb, 0xbd, 0x03, 0xad, 0x4c, 0xb9, 0x6f, 0x68, 0xca, 0x1a, 0xe1, 0x70, 0x90, 0xab,
|
||||
0x2a, 0xd0, 0x4f, 0x29, 0x38, 0x1b, 0x8d, 0x8d, 0xad, 0x86, 0x77, 0x04, 0xe6, 0x07, 0x48, 0x12,
|
||||
0x66, 0x24, 0x2e, 0x9a, 0xcc, 0x45, 0x2c, 0xb8, 0xb5, 0x74, 0xba, 0x12, 0x8f, 0xa8, 0x86, 0x2a,
|
||||
0x33, 0xbc, 0xcd, 0x7e, 0x38, 0xda, 0xe9, 0xfc, 0x0b, 0x63, 0x86, 0xce, 0xbf, 0x20, 0x37, 0x52,
|
||||
0x31, 0xed, 0x51, 0x19, 0xe0, 0xc0, 0x8d, 0xa0, 0x0c, 0xa8, 0x75, 0xd0, 0x03, 0x03, 0xb4, 0x61,
|
||||
0x4c, 0x50, 0x1f, 0x3f, 0x15, 0x63, 0x66, 0x18, 0x1b, 0xd4, 0xf0, 0x0b, 0x23, 0x38, 0xff, 0xc2,
|
||||
0x98, 0x31, 0x22, 0x35, 0xcc, 0xbf, 0x30, 0x6e, 0x28, 0x03, 0x0a, 0xe5, 0xc6, 0x74, 0x6d, 0x94,
|
||||
0x01, 0x4e, 0xb9, 0xa1, 0xf3, 0x77, 0xd3, 0xf9, 0x5b, 0xb3, 0x1f, 0x18, 0x50, 0x0c, 0xfc, 0x50,
|
||||
0x69, 0x30, 0x6e, 0x75, 0xc6, 0x01, 0x78, 0xc4, 0x58, 0x52, 0x8a, 0x83, 0x23, 0x3b, 0x6a, 0xeb,
|
||||
0xd2, 0x16, 0x40, 0x19, 0xe0, 0xc8, 0x8d, 0xc8, 0x51, 0x33, 0x08, 0x29, 0x9b, 0x60, 0x0d, 0x5b,
|
||||
0xcf, 0xd2, 0x29, 0x27, 0x8c, 0x03, 0x53, 0x41, 0xd0, 0xdf, 0x8d, 0x79, 0x57, 0xca, 0x81, 0x22,
|
||||
0xb0, 0x33, 0xe3, 0x80, 0xb2, 0x83, 0x0c, 0xa8, 0x1c, 0xd9, 0x51, 0x2b, 0x03, 0x9c, 0x71, 0xc3,
|
||||
0x46, 0x63, 0x63, 0x23, 0x03, 0x1c, 0xb9, 0x61, 0x02, 0xde, 0xb8, 0x09, 0x3b, 0xdc, 0x20, 0x0e,
|
||||
0xc5, 0xa0, 0x0d, 0xaa, 0x1c, 0xc5, 0xe4, 0x70, 0xd3, 0x71, 0xfe, 0xa6, 0x1b, 0xce, 0xd4, 0xc1,
|
||||
0xb8, 0x31, 0xed, 0x51, 0x19, 0xa0, 0xca, 0xa1, 0x0c, 0xa8, 0x8b, 0x31, 0x03, 0xac, 0x31, 0x88,
|
||||
0x83, 0xce, 0xd9, 0x8d, 0x99, 0x61, 0x9f, 0x6a, 0xc2, 0xca, 0xb6, 0x50, 0x75, 0x30, 0x66, 0xa8,
|
||||
0x3a, 0x18, 0x2f, 0x75, 0xfe, 0xa6, 0x1c, 0xc6, 0x00, 0x55, 0x0e, 0x37, 0x5d, 0x1b, 0x65, 0x80,
|
||||
0x2a, 0x87, 0x9b, 0xa8, 0xc3, 0x30, 0x7f, 0x6b, 0x1e, 0x8b, 0xf1, 0x61, 0x41, 0x52, 0x92, 0x80,
|
||||
0xa6, 0xfb, 0xb2, 0x10, 0xf7, 0xcb, 0x4a, 0xbe, 0x30, 0xcf, 0x45, 0x39, 0x50, 0xd3, 0x55, 0x63,
|
||||
0x39, 0xba, 0x2f, 0x5b, 0xfc, 0x7e, 0x69, 0xb7, 0xee, 0xbe, 0xe8, 0x71, 0xf5, 0x8b, 0xee, 0xf2,
|
||||
0x8a, 0x00, 0xe2, 0xed, 0xc5, 0xe6, 0x76, 0x0d, 0x9c, 0x39, 0x01, 0xe5, 0xb1, 0xb5, 0x12, 0x4e,
|
||||
0x3f, 0x89, 0xb2, 0xa5, 0x78, 0xca, 0x08, 0xf6, 0x26, 0xc0, 0xc2, 0x88, 0xa0, 0xe5, 0x84, 0x2c,
|
||||
0xde, 0x74, 0x38, 0xc1, 0x06, 0x08, 0x44, 0x39, 0xcb, 0x8e, 0xa0, 0xb8, 0x79, 0x90, 0xe5, 0xf2,
|
||||
0x01, 0x4e, 0xad, 0x97, 0x78, 0x83, 0xdc, 0x4b, 0xb5, 0xb8, 0xc1, 0xb2, 0xb9, 0x62, 0xb3, 0x44,
|
||||
0x60, 0x8b, 0x6f, 0xd9, 0xa5, 0x12, 0x02, 0x8a, 0x40, 0xc0, 0xdf, 0xe7, 0x9d, 0x15, 0xa9, 0x24,
|
||||
0x2c, 0xcd, 0xb2, 0x1b, 0xc8, 0x35, 0x4d, 0x44, 0x1c, 0xcf, 0x60, 0x49, 0xf6, 0x85, 0xa1, 0x19,
|
||||
0x2a, 0x19, 0x55, 0x26, 0xab, 0x6b, 0xdd, 0x03, 0xbc, 0xc4, 0xcc, 0x11, 0x11, 0xa6, 0xf4, 0x05,
|
||||
0xa7, 0x43, 0x3e, 0xed, 0x37, 0xc4, 0x50, 0xd4, 0x10, 0x53, 0xae, 0x08, 0x16, 0x42, 0x31, 0xb0,
|
||||
0xd5, 0x47, 0xc4, 0xa0, 0x1e, 0x0a, 0xd2, 0x8a, 0xd3, 0x25, 0xbb, 0x6a, 0x88, 0x9e, 0xbe, 0x44,
|
||||
0x43, 0x3d, 0xad, 0xc5, 0x50, 0xd4, 0x70, 0x50, 0x2a, 0x84, 0xf0, 0x51, 0x7c, 0x4d, 0xd9, 0xd6,
|
||||
0x52, 0x39, 0xec, 0x04, 0x40, 0x60, 0xa2, 0xb8, 0x84, 0x12, 0xc9, 0x9a, 0x49, 0x4f, 0x08, 0x01,
|
||||
0x1a, 0x64, 0x0a, 0xec, 0xc4, 0x3a, 0x29, 0x6e, 0x22, 0x4a, 0x51, 0x37, 0x4e, 0x42, 0xe7, 0x2c,
|
||||
0xfe, 0xbe, 0x75, 0xa7, 0xbd, 0x97, 0xbb, 0xa6, 0x4d, 0xa3, 0xd4, 0xa1, 0x0f, 0xd3, 0x71, 0xa3,
|
||||
0xe9, 0xc8, 0x31, 0xd1, 0x17, 0xc4, 0x9e, 0xe8, 0x19, 0x46, 0x20, 0x66, 0xba, 0xce, 0xca, 0x13,
|
||||
0x67, 0x3c, 0x41, 0xe8, 0x8f, 0x7c, 0x47, 0x12, 0xad, 0x8e, 0xe2, 0xf7, 0xc3, 0xb7, 0x80, 0xeb,
|
||||
0x2c, 0x2b, 0x5b, 0xa7, 0x81, 0xd9, 0x6e, 0x60, 0xb6, 0x87, 0x25, 0x80, 0xcb, 0x56, 0x8a, 0x96,
|
||||
0x32, 0x2d, 0x51, 0xd2, 0x75, 0x00, 0x7a, 0xde, 0xc0, 0xac, 0xe9, 0x4a, 0xba, 0x61, 0x25, 0x2b,
|
||||
0xf8, 0x3b, 0x62, 0xfb, 0x11, 0x2b, 0x6a, 0x14, 0x41, 0x51, 0x50, 0xb9, 0xd0, 0xc6, 0xe7, 0xa7,
|
||||
0x36, 0x05, 0xe8, 0x47, 0x47, 0xd1, 0x68, 0x33, 0xd4, 0x31, 0xc0, 0x41, 0x83, 0xff, 0x96, 0x7c,
|
||||
0x6d, 0x0d, 0xfd, 0x84, 0x7d, 0x89, 0x10, 0x1c, 0x4e, 0xbb, 0x12, 0x27, 0x21, 0xc0, 0x91, 0x90,
|
||||
0xfd, 0x2a, 0x20, 0xcd, 0x20, 0xff, 0xaf, 0x64, 0xb8, 0x95, 0x4c, 0x19, 0x8e, 0x9b, 0x44, 0xd3,
|
||||
0xd9, 0x33, 0x74, 0x17, 0xeb, 0x02, 0x30, 0x48, 0x0c, 0xe2, 0x49, 0x8a, 0xc2, 0x25, 0xf1, 0x30,
|
||||
0xe8, 0x8f, 0x0b, 0x5f, 0xe0, 0xe5, 0x89, 0xad, 0x8c, 0x50, 0x98, 0xf6, 0xa4, 0xca, 0x20, 0x5d,
|
||||
0x01, 0x12, 0x01, 0x52, 0x07, 0xe6, 0xd9, 0xc9, 0xc5, 0x70, 0xb2, 0x84, 0xcd, 0x70, 0xd1, 0x11,
|
||||
0xd7, 0x07, 0xc0, 0xc7, 0xda, 0xb1, 0xcc, 0x1f, 0x51, 0x40, 0xbd, 0x6b, 0x0f, 0x03, 0x29, 0x87,
|
||||
0x79, 0x15, 0x9c, 0x4f, 0xd2, 0xf9, 0x4c, 0x3e, 0x73, 0x83, 0x0c, 0x0c, 0x37, 0x4c, 0xb1, 0x6f,
|
||||
0x31, 0x21, 0x11, 0xd2, 0x00, 0xd0, 0x6a, 0x2b, 0x65, 0x71, 0x25, 0xac, 0x6f, 0xc1, 0x52, 0x40,
|
||||
0x7d, 0xe2, 0x24, 0x01, 0x78, 0x94, 0x51, 0x21, 0xad, 0x22, 0x04, 0x22, 0x80, 0x8c, 0x5a, 0x61,
|
||||
0x1b, 0xb6, 0x24, 0xa0, 0x2c, 0x11, 0x68, 0xc0, 0x53, 0x8d, 0xde, 0x8e, 0x15, 0x7a, 0xac, 0x43,
|
||||
0x3e, 0xa6, 0x8e, 0x09, 0x09, 0xad, 0x4a, 0x36, 0x5d, 0xe0, 0x31, 0x1e, 0x7d, 0x59, 0x1f, 0xd6,
|
||||
0xe7, 0xd0, 0x5e, 0x61, 0x32, 0xfa, 0xbb, 0xcd, 0xed, 0x0a, 0x8b, 0xd1, 0x08, 0x61, 0x64, 0x68,
|
||||
0xf6, 0x36, 0xa3, 0x8c, 0xb4, 0x19, 0x08, 0xf7, 0x3c, 0x13, 0x4b, 0x22, 0x1b, 0x21, 0x8a, 0x77,
|
||||
0x89, 0x70, 0x64, 0x2b, 0x3a, 0xd9, 0xd2, 0x7b, 0x45, 0x82, 0xaa, 0xf5, 0x61, 0x68, 0x3b, 0x6b,
|
||||
0xc3, 0xa5, 0x01, 0xbd, 0x9a, 0xbb, 0xbd, 0xb0, 0xd8, 0x7b, 0xa6, 0x9f, 0x90, 0xb0, 0x68, 0x80,
|
||||
0x9e, 0x08, 0xd1, 0xe4, 0x81, 0x45, 0xb4, 0xb2, 0x4b, 0x89, 0xd0, 0x34, 0xf4, 0xbe, 0x4b, 0xf4,
|
||||
0x16, 0x4f, 0x40, 0x57, 0xf8, 0x08, 0x7c, 0x22, 0xca, 0x35, 0xed, 0x56, 0xb4, 0x92, 0xb9, 0xad,
|
||||
0x16, 0x03, 0x03, 0x1b, 0xe4, 0x1c, 0x09, 0xfa, 0xf4, 0x3b, 0x76, 0x12, 0xf9, 0x34, 0x42, 0x46,
|
||||
0x3f, 0x5b, 0x6e, 0x38, 0x1e, 0x0d, 0xe0, 0x24, 0xa1, 0xa1, 0x8a, 0xb7, 0xbe, 0xee, 0x3d, 0x6c,
|
||||
0x4f, 0x50, 0x84, 0x2d, 0x10, 0x9c, 0x63, 0xc6, 0xab, 0xae, 0xf2, 0x16, 0x94, 0x31, 0x1d, 0x74,
|
||||
0x14, 0xa1, 0xb6, 0x01, 0x07, 0x43, 0x4d, 0xe8, 0xb0, 0xab, 0xe9, 0x64, 0x67, 0x62, 0x7a, 0x58,
|
||||
0x59, 0x22, 0xc2, 0xb0, 0x35, 0xc2, 0x2c, 0x4c, 0x85, 0xad, 0xde, 0xc3, 0xc2, 0x06, 0x71, 0x4d,
|
||||
0xa0, 0xb6, 0x7a, 0xc8, 0xe9, 0xa1, 0xad, 0xd2, 0x73, 0x46, 0xcf, 0x59, 0x6f, 0x4e, 0x7b, 0xeb,
|
||||
0x5a, 0x0d, 0xe2, 0xc4, 0xc9, 0xa6, 0x8c, 0x84, 0x1a, 0x91, 0x7d, 0x05, 0xdf, 0x0c, 0x43, 0x54,
|
||||
0xe7, 0x3a, 0xf7, 0x0a, 0x73, 0x81, 0x95, 0x55, 0xa5, 0xf3, 0x72, 0x3a, 0xaf, 0xed, 0xc0, 0x0f,
|
||||
0x67, 0xfc, 0x70, 0xca, 0x2e, 0x67, 0xec, 0xea, 0xc0, 0x6a, 0x20, 0x57, 0x00, 0xea, 0xa8, 0xdf,
|
||||
0x50, 0x25, 0x78, 0x76, 0xe4, 0xb1, 0x53, 0x1e, 0xcb, 0x9a, 0xd7, 0x1e, 0x71, 0xb8, 0x27, 0xca,
|
||||
0x90, 0x24, 0x40, 0x11, 0x53, 0x52, 0x11, 0x22, 0x11, 0xb5, 0xe3, 0x6f, 0xdd, 0x25, 0x81, 0x89,
|
||||
0x23, 0x04, 0x41, 0xf2, 0x26, 0xc3, 0xef, 0x97, 0xa1, 0x53, 0xf5, 0x20, 0x20, 0xa4, 0x20, 0x02,
|
||||
0x02, 0x83, 0x53, 0x03, 0xb9, 0x0c, 0x90, 0xa1, 0x04, 0x24, 0x20, 0x46, 0xac, 0x44, 0x44, 0x9c,
|
||||
0x23, 0xe6, 0xe4, 0xa4, 0xd2, 0xe0, 0x4b, 0x4e, 0x81, 0xa9, 0xc0, 0x82, 0x61, 0xe7, 0x6c, 0x10,
|
||||
0xd1, 0x09, 0xb7, 0x24, 0x90, 0xda, 0x7a, 0xd8, 0x5f, 0xa6, 0x00, 0xf5, 0x3b, 0xc0, 0x50, 0x56,
|
||||
0x1e, 0x38, 0xb3, 0x08, 0x0a, 0x44, 0xac, 0xcc, 0x25, 0x28, 0xd5, 0x04, 0x63, 0xe1, 0x6f, 0x0a,
|
||||
0x91, 0x86, 0x1e, 0x74, 0x82, 0x77, 0x8d, 0x90, 0x71, 0x4b, 0xc0, 0x50, 0xe4, 0x5d, 0x54, 0xab,
|
||||
0x84, 0x58, 0x0f, 0x6d, 0x67, 0x6d, 0x84, 0x37, 0x89, 0x3d, 0x57, 0xe8, 0xab, 0x04, 0xb3, 0x18,
|
||||
0x57, 0x67, 0xa5, 0xe3, 0x06, 0x3a, 0xd6, 0xbd, 0xd3, 0xee, 0x9d, 0x8e, 0xaa, 0xb6, 0xef, 0xd4,
|
||||
0x45, 0x73, 0x4c, 0x81, 0xd7, 0x8a, 0x24, 0x88, 0x53, 0xc9, 0xc5, 0x8f, 0x9c, 0x92, 0xb3, 0x29,
|
||||
0x19, 0x1f, 0x9c, 0xf1, 0xc1, 0x29, 0x9b, 0x80, 0x11, 0x90, 0x4d, 0x9d, 0x74, 0x15, 0x10, 0xbb,
|
||||
0x97, 0x19, 0x44, 0x10, 0x54, 0x93, 0x9d, 0xc6, 0x5b, 0x6d, 0xac, 0x41, 0x1a, 0x6f, 0xaf, 0xfb,
|
||||
0x7e, 0x4d, 0xbe, 0xa0, 0x56, 0xf7, 0x34, 0x56, 0x62, 0xe9, 0xb6, 0x21, 0x8b, 0xdc, 0xb4, 0x40,
|
||||
0x73, 0xf1, 0x0d, 0xb9, 0x04, 0x56, 0xcc, 0x4f, 0xa7, 0xbf, 0xe1, 0xda, 0x95, 0xd8, 0x03, 0xaa,
|
||||
0x44, 0x56, 0xb6, 0x44, 0x8f, 0xf5, 0x53, 0x8f, 0x59, 0x83, 0xc7, 0x65, 0xb3, 0xde, 0x1a, 0x31,
|
||||
0xe0, 0xdf, 0x13, 0xe2, 0xc3, 0xff, 0xbb, 0x62, 0xdf, 0xcb, 0x31, 0x1a, 0xb0, 0x42, 0x6c, 0xba,
|
||||
0xd1, 0x79, 0x6e, 0x18, 0x87, 0xd3, 0x73, 0xb6, 0xd3, 0x4e, 0xf2, 0xbc, 0xd3, 0x6e, 0x44, 0xa2,
|
||||
0x39, 0x4a, 0x42, 0x58, 0x20, 0x22, 0x8e, 0x89, 0x7a, 0xd1, 0x43, 0xac, 0x59, 0xdd, 0x32, 0xab,
|
||||
0x00, 0x41, 0x61, 0xa3, 0xf7, 0x95, 0x4a, 0x11, 0xb3, 0xde, 0x7a, 0xa4, 0xc0, 0x91, 0x76, 0x3b,
|
||||
0xed, 0x35, 0xbb, 0x79, 0xef, 0x4a, 0x78, 0x4f, 0x5e, 0x5c, 0x90, 0x11, 0x7d, 0xbf, 0x48, 0xdf,
|
||||
0x2b, 0xfd, 0x6e, 0x3c, 0xf3, 0x63, 0xeb, 0x50, 0x6d, 0x67, 0x5c, 0xcd, 0x2b, 0x44, 0x64, 0x73,
|
||||
0x7b, 0x7b, 0xfd, 0x07, 0x8b, 0x84, 0x8b, 0xee, 0xf2, 0xb6, 0xdb, 0x5e, 0xac, 0x10, 0x17, 0xc3,
|
||||
0xce, 0x99, 0xf2, 0x10, 0x95, 0xe9, 0x46, 0x18, 0x3a, 0x32, 0x1c, 0x53, 0xf0, 0xdc, 0x19, 0x78,
|
||||
0x3e, 0xb4, 0x7b, 0x03, 0xe4, 0x1d, 0x01, 0xf9, 0x68, 0x87, 0x51, 0x5e, 0xa0, 0xa7, 0x0f, 0xdf,
|
||||
0x4a, 0x66, 0xdf, 0x1e, 0x80, 0x7b, 0xbb, 0x4c, 0xa9, 0xb4, 0x07, 0xbd, 0x4c, 0x2f, 0x0b, 0xc5,
|
||||
0x94, 0x7c, 0x28, 0x86, 0xeb, 0x26, 0xe9, 0x80, 0xbc, 0x4b, 0x07, 0xec, 0x4e, 0x9b, 0x4c, 0x22,
|
||||
0xec, 0x32, 0x00, 0x76, 0xd9, 0x30, 0x87, 0x59, 0x2f, 0x9f, 0x27, 0x2e, 0xb7, 0x65, 0x92, 0x4a,
|
||||
0x4d, 0x1c, 0x15, 0xe3, 0x8c, 0x52, 0xc1, 0xcf, 0xde, 0xfe, 0x57, 0x8c, 0xfe, 0xa7, 0x9f, 0xe2,
|
||||
0x00, 0xd8, 0xc5, 0xda, 0x76, 0xe3, 0x13, 0x95, 0x44, 0xbf, 0x94, 0xa1, 0x3a, 0x16, 0x4e, 0x79,
|
||||
0x19, 0x16, 0xd1, 0x53, 0x4f, 0x08, 0x70, 0x1b, 0xc4, 0x3f, 0x14, 0x5e, 0xe1, 0x93, 0x62, 0x15,
|
||||
0x4d, 0xbd, 0x47, 0x8a, 0x97, 0x07, 0x8d, 0x28, 0xdd, 0x5e, 0xf5, 0x4d, 0xf0, 0xe6, 0x5a, 0x23,
|
||||
0xc6, 0x15, 0x79, 0x1e, 0x38, 0xa6, 0x09, 0xf9, 0xc2, 0xf4, 0x36, 0x06, 0x66, 0x90, 0xba, 0xa1,
|
||||
0x2e, 0xe0, 0xde, 0x92, 0x83, 0x79, 0x81, 0xd1, 0xdb, 0xc2, 0x2e, 0xdf, 0x1a, 0x39, 0x67, 0xe4,
|
||||
0xbb, 0xfd, 0x48, 0xe2, 0xf1, 0x91, 0x14, 0x35, 0x47, 0xc9, 0xcf, 0x82, 0x4a, 0xd6, 0x50, 0xaf,
|
||||
0x12, 0x8c, 0x38, 0x94, 0x91, 0x8d, 0xbe, 0x18, 0x6b, 0x99, 0x1d, 0x2a, 0x1a, 0xb2, 0xa6, 0x18,
|
||||
0xf3, 0x46, 0xf6, 0x01, 0xb3, 0x42, 0xf2, 0x83, 0x5d, 0x05, 0xd5, 0x36, 0xff, 0x17, 0x94, 0x8b,
|
||||
0x25, 0xef, 0xeb, 0xb5, 0x2b, 0xc3, 0x67, 0x47, 0x3c, 0x60, 0xda, 0x55, 0x4c, 0xd4, 0x6b, 0x29,
|
||||
0x37, 0xb5, 0x53, 0xaf, 0x62, 0xaa, 0x5f, 0x33, 0x05, 0xa8, 0x8b, 0x99, 0x7e, 0xcd, 0x14, 0x28,
|
||||
0xb9, 0xa9, 0x7e, 0xcd, 0xd4, 0x2f, 0xcf, 0xd4, 0x32, 0xcc, 0xd4, 0x37, 0xb8, 0xa9, 0x7e, 0xcd,
|
||||
0x94, 0x3f, 0xb8, 0x99, 0x7e, 0xcd, 0x14, 0x28, 0x17, 0x53, 0xfd, 0x2a, 0xee, 0xd5, 0xaf, 0x99,
|
||||
0x8e, 0x1c, 0x51, 0xa6, 0xfe, 0x50, 0x6d, 0x4c, 0xbf, 0xa6, 0xba, 0x79, 0x24, 0xdb, 0xdb, 0x1f,
|
||||
0xd1, 0xd7, 0x65, 0xfd, 0x6a, 0x72, 0xa2, 0x74, 0x0d, 0xfa, 0x35, 0x15, 0xa2, 0x91, 0x86, 0x8d,
|
||||
0xb7, 0xb6, 0xbc, 0xdb, 0x1e, 0x47, 0x9b, 0x6b, 0x53, 0x1c, 0xd7, 0xb0, 0xb9, 0x82, 0x0d, 0x2a,
|
||||
0x32, 0x2b, 0xbd, 0x71, 0xa3, 0x72, 0xa0, 0x7d, 0x59, 0xc2, 0xb8, 0xa4, 0x46, 0x35, 0x6c, 0x50,
|
||||
0xb0, 0x62, 0xae, 0x61, 0xa3, 0xa1, 0xc4, 0xe3, 0x43, 0x71, 0x23, 0x15, 0x73, 0x63, 0x15, 0x73,
|
||||
0x13, 0x15, 0x9b, 0xef, 0x63, 0x7b, 0x0d, 0x1b, 0xf3, 0x66, 0xd0, 0x2f, 0xf7, 0x55, 0xfa, 0x75,
|
||||
0x7b, 0xdd, 0xbd, 0xbb, 0x58, 0x83, 0x84, 0x24, 0xc4, 0x81, 0x4e, 0x8b, 0x1b, 0x8b, 0x46, 0x64,
|
||||
0x8c, 0x05, 0x11, 0x48, 0x06, 0xc4, 0x86, 0x59, 0x46, 0xcf, 0x0c, 0x51, 0xee, 0xf7, 0x4d, 0x67,
|
||||
0xff, 0xc2, 0xb7, 0xd3, 0x7f, 0xbb, 0xe1, 0xdf, 0xfb, 0xe6, 0x70, 0xc6, 0x67, 0xeb, 0x82, 0x25,
|
||||
0x41, 0x93, 0xa2, 0x94, 0x83, 0xc2, 0x9b, 0x7e, 0x5e, 0x6e, 0x73, 0x4f, 0x0d, 0xca, 0x41, 0xed,
|
||||
0x12, 0x3f, 0x8e, 0x49, 0x20, 0x56, 0x15, 0xc9, 0x28, 0xd6, 0x7c, 0x24, 0x96, 0xdb, 0x95, 0x0c,
|
||||
0x3f, 0x59, 0x3b, 0x81, 0x18, 0x8b, 0xbe, 0x44, 0x52, 0x5f, 0x02, 0x41, 0xa7, 0x04, 0x52, 0xfa,
|
||||
0x29, 0x51, 0x40, 0x8c, 0x1a, 0x79, 0x06, 0x89, 0xc1, 0xda, 0x48, 0x07, 0x4c, 0x3c, 0xcf, 0x26,
|
||||
0x33, 0x92, 0x0a, 0x48, 0x21, 0xd4, 0x99, 0x22, 0x02, 0x42, 0x55, 0xd0, 0x92, 0xbf, 0x80, 0xa2,
|
||||
0x44, 0x58, 0x98, 0xa1, 0xdd, 0x9c, 0x64, 0x40, 0x4c, 0xc8, 0xfc, 0xb4, 0xa8, 0xa9, 0x40, 0xb9,
|
||||
0x09, 0x40, 0x8e, 0x98, 0x92, 0xab, 0xa2, 0x96, 0x88, 0x34, 0x84, 0xa1, 0x86, 0x2f, 0x71, 0xac,
|
||||
0xbd, 0x38, 0x3e, 0x35, 0xcb, 0x34, 0x2b, 0x91, 0x18, 0x91, 0xd4, 0x56, 0xab, 0x40, 0x35, 0x95,
|
||||
0xd2, 0x30, 0xea, 0x2e, 0x80, 0x77, 0x78, 0xa4, 0xef, 0xc4, 0x2e, 0x64, 0x09, 0x0e, 0xab, 0xa0,
|
||||
0xb5, 0x38, 0xa8, 0x44, 0xc9, 0x94, 0xb2, 0x8c, 0x72, 0x40, 0xa6, 0x31, 0xc4, 0xf5, 0xf6, 0xf8,
|
||||
0x8d, 0x44, 0x81, 0x4c, 0x00, 0xe5, 0x0c, 0xf8, 0xfd, 0xf9, 0x69, 0xa8, 0x51, 0x24, 0x82, 0xc0,
|
||||
0x5d, 0xfa, 0x8b, 0x08, 0xb2, 0x23, 0xbe, 0x2d, 0xab, 0xdf, 0x6a, 0x9a, 0xb5, 0x2e, 0x44, 0x95,
|
||||
0x43, 0x0e, 0x28, 0x17, 0x09, 0x15, 0x53, 0xb7, 0x48, 0x7a, 0xd4, 0x12, 0x5e, 0x10, 0xf1, 0x0a,
|
||||
0x88, 0xfd, 0x4a, 0x8d, 0x20, 0x64, 0xc5, 0x23, 0xb3, 0x1e, 0x88, 0xf5, 0x1a, 0xe0, 0x8c, 0x55,
|
||||
0x64, 0x56, 0x14, 0x91, 0x1f, 0x00, 0x0a, 0x04, 0x34, 0xf0, 0xf0, 0xc1, 0x8c, 0x84, 0xf0, 0x41,
|
||||
0x62, 0x9d, 0x8a, 0xde, 0x6c, 0xac, 0xc1, 0xd2, 0xa2, 0x6a, 0x08, 0x60, 0x37, 0x25, 0xb1, 0xb7,
|
||||
0x94, 0x18, 0x39, 0x0a, 0x3b, 0x1a, 0x24, 0x0f, 0x6b, 0x2d, 0x04, 0x55, 0x34, 0x4d, 0x86, 0xde,
|
||||
0x60, 0x25, 0x2b, 0x9a, 0xf4, 0x93, 0x94, 0x83, 0x22, 0x21, 0xd2, 0x81, 0xac, 0x0a, 0x4c, 0x25,
|
||||
0x62, 0x86, 0x34, 0x7c, 0x21, 0xa9, 0x04, 0xfc, 0xa7, 0x84, 0x7a, 0x22, 0xeb, 0x83, 0xec, 0x10,
|
||||
0x1b, 0xcb, 0xf5, 0x7c, 0x48, 0x65, 0xa3, 0xde, 0xb4, 0x56, 0x63, 0x22, 0x73, 0x8d, 0x09, 0x4c,
|
||||
0x89, 0x80, 0x08, 0xa5, 0xd9, 0x4a, 0xc8, 0x2a, 0x43, 0x44, 0xa4, 0x9e, 0x03, 0x95, 0xb6, 0x4a,
|
||||
0x9a, 0xe5, 0x96, 0xd9, 0x10, 0x80, 0xcf, 0x84, 0xa1, 0x83, 0xc7, 0xa5, 0x59, 0x17, 0x2b, 0x33,
|
||||
0xbe, 0x64, 0xc4, 0x1c, 0xd4, 0x35, 0x2d, 0x59, 0x76, 0x1a, 0x10, 0x02, 0x23, 0x94, 0x67, 0x22,
|
||||
0x04, 0x85, 0xb9, 0x59, 0xa2, 0x43, 0x40, 0x6b, 0x72, 0x0c, 0x55, 0xa1, 0x05, 0xea, 0x42, 0x50,
|
||||
0x34, 0x5a, 0xb2, 0x36, 0x18, 0x89, 0x31, 0x44, 0xd5, 0xb2, 0x46, 0x28, 0x0a, 0x40, 0x08, 0xa6,
|
||||
0x25, 0xc1, 0x2c, 0xf7, 0x42, 0xe0, 0x9c, 0x6c, 0x3f, 0x03, 0x12, 0xc4, 0x8a, 0x97, 0x92, 0xc1,
|
||||
0x1b, 0x10, 0xb2, 0x44, 0x59, 0x06, 0x7e, 0x26, 0x26, 0x0e, 0x40, 0x98, 0xc3, 0x90, 0x5b, 0x08,
|
||||
0x56, 0x59, 0xa1, 0x2e, 0x86, 0x20, 0x13, 0xb2, 0x37, 0xd0, 0x22, 0xa6, 0x0d, 0x91, 0x8c, 0x47,
|
||||
0xb0, 0x85, 0x81, 0x66, 0x8f, 0xb0, 0x10, 0x80, 0x31, 0xf0, 0x7a, 0x56, 0x30, 0x30, 0xc9, 0xcb,
|
||||
0x59, 0xb6, 0x27, 0x4d, 0x84, 0x57, 0x0f, 0x48, 0x08, 0xc9, 0xc4, 0x36, 0x58, 0x43, 0xa6, 0xa4,
|
||||
0x38, 0x65, 0x65, 0x88, 0xba, 0x16, 0xdb, 0x96, 0x09, 0x7a, 0x87, 0xf0, 0xbb, 0x44, 0x88, 0x8f,
|
||||
0x42, 0x8e, 0x9a, 0xa0, 0xba, 0x57, 0x80, 0xa8, 0x25, 0x93, 0x6b, 0x44, 0xe2, 0x0d, 0x52, 0x93,
|
||||
0xb4, 0x1f, 0xc4, 0x4e, 0x6a, 0x24, 0x79, 0x1a, 0x4d, 0x4d, 0x06, 0x56, 0x40, 0xf9, 0xa8, 0x1a,
|
||||
0x29, 0x8a, 0x48, 0x4c, 0x2c, 0x31, 0x1c, 0xaf, 0x29, 0xef, 0x4e, 0x26, 0x0e, 0x68, 0x5e, 0x84,
|
||||
0x94, 0x29, 0x2d, 0x19, 0x9a, 0xc8, 0x3a, 0xb8, 0x83, 0x12, 0xdb, 0xc0, 0x14, 0xa2, 0x7d, 0xa1,
|
||||
0x2e, 0x4c, 0x02, 0x5a, 0x60, 0x84, 0xd5, 0x70, 0x4a, 0xd0, 0x2b, 0x58, 0x26, 0x5d, 0xb3, 0x78,
|
||||
0x0a, 0x09, 0x52, 0xec, 0x1a, 0x48, 0x7f, 0xb3, 0xac, 0x57, 0xbb, 0x0d, 0x36, 0x0a, 0xcf, 0x94,
|
||||
0x88, 0x96, 0x54, 0x34, 0x62, 0x42, 0x64, 0xf4, 0x29, 0x27, 0xcc, 0x85, 0x59, 0x80, 0x06, 0x59,
|
||||
0x00, 0x4c, 0xac, 0x42, 0x5a, 0x3c, 0x8b, 0x82, 0xf0, 0x13, 0xc2, 0x81, 0xe2, 0x2c, 0xe0, 0x24,
|
||||
0x28, 0x88, 0x93, 0x21, 0x5b, 0x0a, 0xa7, 0xc4, 0x0e, 0x13, 0x91, 0x31, 0xcd, 0x4c, 0x98, 0x36,
|
||||
0x0d, 0x33, 0x8f, 0x15, 0xcb, 0xa9, 0x1a, 0x74, 0xab, 0x2d, 0x85, 0x30, 0x4b, 0xa7, 0x0a, 0x22,
|
||||
0x8a, 0xd4, 0x70, 0x57, 0xaa, 0x59, 0xa5, 0xd0, 0x94, 0x44, 0x31, 0x91, 0x4d, 0x93, 0x21, 0xb6,
|
||||
0x2e, 0x13, 0xec, 0xa9, 0x01, 0x49, 0xef, 0x96, 0x7c, 0x10, 0x81, 0x3a, 0x11, 0xa1, 0xae, 0x1a,
|
||||
0xfa, 0x3b, 0xa2, 0xa7, 0x09, 0xd6, 0x32, 0x6a, 0xb6, 0xc3, 0x84, 0x49, 0x85, 0x8b, 0xf9, 0x3f,
|
||||
0x11, 0xf4, 0x3a, 0x02, 0x25, 0x07, 0xcc, 0x82, 0xca, 0x8f, 0xb6, 0x84, 0x68, 0x0e, 0x12, 0xaa,
|
||||
0x02, 0x5b, 0x69, 0xc4, 0x0e, 0x34, 0x0a, 0x55, 0xae, 0xb2, 0xbe, 0xc8, 0x9d, 0x4b, 0x6c, 0x06,
|
||||
0x88, 0x45, 0x65, 0x3e, 0x68, 0x5e, 0x34, 0xd5, 0x34, 0x0f, 0xb1, 0xe1, 0x6a, 0x01, 0xc7, 0x85,
|
||||
0x70, 0x00, 0x0f, 0x00, 0x98, 0xa2, 0xaa, 0x54, 0xed, 0x54, 0x4b, 0x14, 0x05, 0x63, 0x85, 0x21,
|
||||
0x4a, 0xb0, 0x55, 0x89, 0xf5, 0xee, 0x01, 0x94, 0x65, 0x7d, 0xac, 0x69, 0x3a, 0xfb, 0x51, 0x8b,
|
||||
0x6d, 0xb5, 0xc4, 0xf0, 0xa9, 0x8f, 0x2d, 0x83, 0x59, 0xb1, 0xf5, 0xb0, 0xac, 0x9d, 0x44, 0xfe,
|
||||
0xa8, 0x13, 0x83, 0x05, 0x52, 0x93, 0x95, 0x6b, 0x82, 0xa8, 0xf4, 0x01, 0xcb, 0x46, 0x51, 0x09,
|
||||
0x98, 0xc4, 0x8a, 0x89, 0xc6, 0x20, 0x93, 0x8f, 0x9a, 0xcb, 0x01, 0xa6, 0x0e, 0xfc, 0xc3, 0x7b,
|
||||
0x82, 0x7b, 0x31, 0xd1, 0x96, 0x7b, 0x61, 0x4a, 0x14, 0xb1, 0x89, 0x2d, 0xeb, 0xce, 0x2a, 0x45,
|
||||
0x6e, 0xc0, 0xbe, 0x44, 0x20, 0x2b, 0xcb, 0xfc, 0x51, 0x2b, 0x5e, 0x11, 0x6a, 0x4f, 0x0d, 0xb2,
|
||||
0xc5, 0x01, 0xc5, 0x57, 0x2e, 0x0b, 0x0b, 0x64, 0xbb, 0xe9, 0x64, 0x12, 0x8d, 0xb8, 0x7c, 0x58,
|
||||
0xa4, 0x08, 0x26, 0xd1, 0x11, 0xf1, 0xdc, 0x17, 0x71, 0x85, 0x57, 0x02, 0xa8, 0x1d, 0x90, 0xf1,
|
||||
0xe0, 0x96, 0x00, 0x96, 0xc6, 0x43, 0x33, 0x98, 0x02, 0xaf, 0x54, 0x15, 0x30, 0x0c, 0xec, 0xd4,
|
||||
0xc2, 0xe4, 0x96, 0x15, 0x45, 0x80, 0x94, 0x33, 0x0b, 0x81, 0x50, 0xc9, 0x58, 0x81, 0xc9, 0x28,
|
||||
0x16, 0x6e, 0x39, 0x3b, 0x00, 0xfa, 0x98, 0x6d, 0xe5, 0xe3, 0xe7, 0xa7, 0x4d, 0xc3, 0xe2, 0x2a,
|
||||
0x17, 0x31, 0x43, 0x00, 0x43, 0x80, 0x5f, 0xc5, 0x28, 0x8a, 0x3f, 0xde, 0x42, 0x07, 0x80, 0x29,
|
||||
0x52, 0x26, 0x22, 0xb7, 0x3f, 0x60, 0xca, 0x50, 0xb4, 0xa1, 0x5d, 0x92, 0xbf, 0xc8, 0x1a, 0xc9,
|
||||
0xfa, 0x7a, 0xe8, 0x77, 0x05, 0x7b, 0x85, 0xc2, 0x02, 0x16, 0x02, 0x12, 0xc2, 0x6e, 0xe0, 0x3a,
|
||||
0x54, 0x5c, 0x53, 0xd1, 0x65, 0x58, 0x73, 0x99, 0x4c, 0xf2, 0x19, 0x88, 0x2f, 0xd2, 0xcc, 0x91,
|
||||
0x59, 0x1a, 0x61, 0x0c, 0x3a, 0xe0, 0x27, 0x2a, 0x95, 0x70, 0xb6, 0x68, 0x85, 0xee, 0x2a, 0x38,
|
||||
0x81, 0x67, 0x73, 0x27, 0x68, 0x81, 0xee, 0xa3, 0xd8, 0x3f, 0x0e, 0xbd, 0x48, 0x9f, 0x8d, 0x90,
|
||||
0xda, 0xb7, 0x50, 0xbb, 0x55, 0x2a, 0xec, 0x89, 0x28, 0xdd, 0x04, 0x2c, 0x31, 0x5f, 0xac, 0x83,
|
||||
0x6f, 0x46, 0x93, 0x09, 0xcc, 0xa7, 0x7b, 0xec, 0x66, 0xd0, 0x4f, 0xb1, 0x06, 0x11, 0x05, 0x55,
|
||||
0x40, 0xf2, 0x51, 0x5f, 0x24, 0x3b, 0x46, 0x86, 0xa3, 0x5e, 0x06, 0xea, 0x77, 0x24, 0xae, 0xc9,
|
||||
0x8d, 0x55, 0x7c, 0x94, 0x1a, 0x9b, 0xb4, 0xec, 0xee, 0x0a, 0xc3, 0xe9, 0x39, 0xbb, 0x6b, 0xd6,
|
||||
0xa0, 0xd5, 0x9f, 0xae, 0xba, 0x2f, 0x78, 0x75, 0x72, 0x26, 0x9f, 0xcd, 0xa5, 0xe1, 0xad, 0x84,
|
||||
0x12, 0x34, 0xc9, 0x35, 0x98, 0xd9, 0x9a, 0xcb, 0xfd, 0x05, 0x44, 0x4a, 0x56, 0x3f, 0x57, 0x94,
|
||||
0x66, 0xf9, 0x42, 0x79, 0x1d, 0x92, 0x57, 0x25, 0x90, 0x53, 0x6e, 0x44, 0x2d, 0x6e, 0x33, 0x28,
|
||||
0x51, 0xd4, 0xc5, 0xdc, 0x80, 0x08, 0xac, 0x48, 0x91, 0xe8, 0x0e, 0x73, 0xf0, 0xb2, 0x15, 0xe9,
|
||||
0x97, 0xf8, 0x4d, 0xb9, 0xd4, 0x9c, 0x09, 0x53, 0x4d, 0x44, 0x5e, 0x40, 0x48, 0x5b, 0xd0, 0xdb,
|
||||
0xc0, 0xed, 0x14, 0x66, 0x58, 0x78, 0x02, 0xb3, 0x82, 0x8c, 0x79, 0x82, 0x8b, 0x08, 0xec, 0x31,
|
||||
0xb3, 0x82, 0x33, 0x69, 0x26, 0xca, 0xc2, 0xd1, 0x13, 0xbd, 0xeb, 0x04, 0x95, 0x6b, 0x30, 0x72,
|
||||
0x89, 0xb5, 0x24, 0xb1, 0x6d, 0xf4, 0x84, 0xec, 0xf4, 0xec, 0xe1, 0x0c, 0x9c, 0xad, 0xc7, 0x0b,
|
||||
0x3b, 0x1b, 0xc4, 0x31, 0x84, 0x06, 0xb0, 0x30, 0xef, 0x3c, 0xa1, 0x67, 0x80, 0x21, 0x24, 0xdc,
|
||||
0xe4, 0xc2, 0x64, 0xcc, 0xae, 0xed, 0x5b, 0x8d, 0xe8, 0x50, 0x80, 0x19, 0xb4, 0xac, 0x0c, 0x9b,
|
||||
0x23, 0x7d, 0x36, 0xad, 0x49, 0xad, 0x60, 0xcb, 0x7d, 0x4b, 0x96, 0x45, 0x99, 0xaa, 0x7e, 0xad,
|
||||
0x60, 0xf2, 0x04, 0x34, 0x3c, 0x16, 0x4c, 0xc4, 0xed, 0x38, 0x6b, 0xfa, 0x8d, 0x00, 0xd9, 0x76,
|
||||
0x94, 0x45, 0x5d, 0x02, 0xcb, 0xe2, 0x0e, 0x2c, 0x9b, 0xfb, 0x41, 0x26, 0x50, 0x41, 0x63, 0xf0,
|
||||
0xc4, 0xe2, 0x65, 0xb1, 0xa4, 0x4c, 0x97, 0xb2, 0xc6, 0x0f, 0xde, 0x31, 0x38, 0x5f, 0xc1, 0x9a,
|
||||
0xd8, 0x32, 0x21, 0x32, 0xd5, 0x95, 0x21, 0xe7, 0xe1, 0x6c, 0x54, 0x08, 0x08, 0xc8, 0x7a, 0xc8,
|
||||
0x06, 0x59, 0xef, 0x94, 0xd5, 0x28, 0xd4, 0xd5, 0x3c, 0xd8, 0xd0, 0x56, 0xd6, 0x13, 0xc0, 0x8b,
|
||||
0xda, 0x81, 0xb1, 0xbe, 0x30, 0xd6, 0x17, 0x64, 0x7d, 0xf0, 0x5b, 0x65, 0xb9, 0x33, 0xce, 0x8b,
|
||||
0xff, 0x38, 0x02, 0x28, 0xdb, 0x31, 0x40, 0xd9, 0x2e, 0x03, 0x94, 0xdd, 0x18, 0xf7, 0x1c, 0xaf,
|
||||
0xda, 0x08, 0x40, 0x1c, 0xb3, 0xf0, 0xcb, 0x90, 0xec, 0x76, 0x9c, 0x0d, 0x5f, 0x81, 0xae, 0xf6,
|
||||
0xd6, 0x6e, 0x07, 0xef, 0x51, 0xa9, 0x50, 0x05, 0x4d, 0x1f, 0x3b, 0xe8, 0xa1, 0x53, 0x3d, 0xe4,
|
||||
0x3e, 0xd7, 0xa2, 0x94, 0x80, 0x7a, 0x18, 0x9c, 0x29, 0xa2, 0x53, 0x45, 0xe4, 0x7d, 0x45, 0xac,
|
||||
0x34, 0x6f, 0x74, 0xab, 0xa5, 0x26, 0xd6, 0x4e, 0x75, 0xcf, 0xa9, 0x26, 0x86, 0xa1, 0x39, 0xa8,
|
||||
0xa2, 0x53, 0x55, 0x2c, 0x54, 0x13, 0x9d, 0x69, 0x62, 0x61, 0x9a, 0x48, 0xdd, 0xca, 0xba, 0xdc,
|
||||
0x1e, 0xba, 0x85, 0x7b, 0xa3, 0x74, 0xb9, 0x75, 0x85, 0xb9, 0xde, 0x6b, 0x62, 0x53, 0x3e, 0x63,
|
||||
0xe7, 0xfd, 0xe6, 0xf6, 0xdd, 0x7a, 0xe4, 0x47, 0xc1, 0x0d, 0x2b, 0xdb, 0x5f, 0x57, 0xc0, 0x5c,
|
||||
0xf7, 0xb3, 0xa2, 0xe5, 0x7a, 0x06, 0x0c, 0x25, 0x94, 0xee, 0x93, 0x56, 0x35, 0x20, 0x42, 0x53,
|
||||
0xf0, 0x72, 0x77, 0x62, 0xaf, 0x04, 0xaa, 0x39, 0x22, 0x34, 0xb4, 0xbb, 0xdd, 0x90, 0xdc, 0xfd,
|
||||
0x10, 0x6e, 0xbf, 0x0a, 0xc2, 0xad, 0xdd, 0x14, 0xe4, 0xd9, 0x1d, 0x1e, 0x00, 0x2f, 0xa7, 0x35,
|
||||
0xd9, 0x33, 0x22, 0x73, 0x3c, 0xeb, 0xf3, 0x9e, 0x6b, 0x10, 0xc1, 0xaf, 0x87, 0x4d, 0x17, 0x51,
|
||||
0xda, 0x45, 0x90, 0xf6, 0x58, 0x24, 0x05, 0xdf, 0xa3, 0xa9, 0x39, 0x94, 0xc4, 0x38, 0xa7, 0x3c,
|
||||
0x80, 0x1a, 0xf7, 0x09, 0x83, 0x71, 0x11, 0xcb, 0xd4, 0x9a, 0x1e, 0xd5, 0xce, 0x23, 0xa9, 0x8f,
|
||||
0x62, 0xa6, 0x49, 0x28, 0xac, 0xa1, 0xc1, 0xb4, 0xef, 0xca, 0xca, 0x19, 0xf4, 0x3b, 0x77, 0x87,
|
||||
0xba, 0x39, 0xa6, 0x30, 0xc5, 0x7a, 0xf3, 0x51, 0x84, 0x35, 0x6e, 0x69, 0x9b, 0xea, 0xe1, 0x56,
|
||||
0x2b, 0xcb, 0x97, 0x14, 0xa3, 0x7c, 0x49, 0x31, 0xce, 0x97, 0xac, 0x46, 0x49, 0xcf, 0xaf, 0xff,
|
||||
0xb8, 0xfa, 0xab, 0x20, 0x69, 0x92, 0x90, 0x13, 0x37, 0x02, 0xe6, 0x59, 0x0a, 0x62, 0x56, 0xc7,
|
||||
0x3f, 0x93, 0x9d, 0xdc, 0x17, 0x53, 0x4d, 0x98, 0xab, 0xcc, 0x92, 0x2a, 0xed, 0x55, 0xcd, 0xc0,
|
||||
0xd1, 0x09, 0xc4, 0x9a, 0x67, 0x10, 0x6b, 0x98, 0x41, 0xac, 0x61, 0x0a, 0xb1, 0xd6, 0x33, 0x88,
|
||||
0x35, 0xcc, 0x20, 0xd6, 0x74, 0xf0, 0xff, 0x29, 0xc4, 0xda, 0x4c, 0x21, 0xd6, 0x5d, 0xaa, 0x02,
|
||||
0xc9, 0x59, 0x91, 0x66, 0xa6, 0xf2, 0x44, 0xf7, 0x27, 0xb7, 0xb3, 0x1c, 0x02, 0xa1, 0xfd, 0x12,
|
||||
0xfe, 0xd9, 0x0d, 0x77, 0xc2, 0x2c, 0xe2, 0xa0, 0xfd, 0xa2, 0x7a, 0x1c, 0x2d, 0xe8, 0x2a, 0x6b,
|
||||
0x6e, 0x48, 0xb9, 0x62, 0x91, 0xd8, 0x41, 0x06, 0x42, 0xe5, 0x3a, 0x1e, 0x4f, 0x6c, 0x8d, 0xb4,
|
||||
0x62, 0x01, 0x41, 0x3d, 0x00, 0x32, 0x3f, 0xee, 0x00, 0xd2, 0xe1, 0x3e, 0xe8, 0x83, 0x3b, 0x25,
|
||||
0xf5, 0xd6, 0xc4, 0x11, 0x6c, 0x3a, 0xba, 0x41, 0xf1, 0xe3, 0x04, 0x20, 0xf5, 0x2c, 0x59, 0x22,
|
||||
0xfd, 0x35, 0x68, 0xee, 0x38, 0x07, 0x61, 0xc8, 0x28, 0x61, 0xd2, 0x62, 0x0c, 0x93, 0xf6, 0xb6,
|
||||
0x41, 0x57, 0xa6, 0x2b, 0xdc, 0x6f, 0x78, 0x44, 0x79, 0xe3, 0xf6, 0xbc, 0x81, 0x7b, 0xe1, 0x0c,
|
||||
0x1d, 0xf5, 0xd4, 0x43, 0x8f, 0xbb, 0x68, 0x8f, 0xaa, 0xd6, 0x0f, 0x7a, 0x13, 0xfa, 0x03, 0xde,
|
||||
0x92, 0xfe, 0xe0, 0xfc, 0xf2, 0x23, 0xb4, 0xec, 0xee, 0xd5, 0x23, 0xbb, 0x4d, 0x1e, 0x8f, 0x06,
|
||||
0xc2, 0xc3, 0xb4, 0xec, 0xce, 0x78, 0x1c, 0x7b, 0xf3, 0xca, 0x5d, 0x5f, 0x75, 0xdb, 0xcb, 0xee,
|
||||
0xdd, 0x4f, 0x7c, 0xec, 0xeb, 0xc3, 0x07, 0x1f, 0xfa, 0x0b, 0xf7, 0x27, 0x5e, 0x3d, 0xf6, 0x23,
|
||||
0x5f, 0x2a, 0xf6, 0xf7, 0xf9, 0xfd, 0xea, 0xd2, 0x9f, 0x9c, 0xf2, 0xf0, 0x81, 0xdd, 0xf6, 0x6e,
|
||||
0x84, 0xde, 0x9f, 0x8f, 0x09, 0xf1, 0x71, 0xa9, 0xc7, 0x49, 0xe1, 0x66, 0xdc, 0xe3, 0x24, 0x6e,
|
||||
0xfa, 0x3d, 0x89, 0xc7, 0xff, 0xf9, 0x2e, 0x2c, 0x10, 0x60, 0xfd, 0xdb, 0x71, 0x0a, 0xaf, 0xff,
|
||||
0x9c, 0x50, 0xa8, 0x16, 0x28, 0xa0, 0x1c, 0xe6, 0x38, 0x81, 0xab, 0xed, 0x84, 0x40, 0xbd, 0x40,
|
||||
0x00, 0x37, 0xe2, 0x2d, 0x10, 0xe8, 0xc7, 0x6c, 0x78, 0xb6, 0xc4, 0x04, 0x84, 0x38, 0xc7, 0x09,
|
||||
0xf4, 0x77, 0x63, 0x02, 0x67, 0x4b, 0x04, 0xba, 0xeb, 0x37, 0x93, 0xeb, 0x65, 0xe5, 0x2f, 0x3f,
|
||||
0xee, 0x56, 0xbc, 0x3b, 0x1f, 0x56, 0x7c, 0x78, 0x7c, 0xda, 0xc3, 0x07, 0x78, 0xe4, 0x0f, 0x79,
|
||||
0x24, 0xdf, 0xff, 0xeb, 0xf4, 0xd5, 0x73, 0x8f, 0x5f, 0x4b, 0xc7, 0xaf, 0x6e, 0x77, 0xd7, 0xf5,
|
||||
0xdb, 0x9f, 0xed, 0xba, 0x1e, 0xd2, 0xc4, 0xa7, 0x45, 0xb8, 0xfd, 0xd3, 0x22, 0x1c, 0xdf, 0x1e,
|
||||
0xf7, 0xd3, 0x23, 0xa6, 0xb4, 0xae, 0x2e, 0xfa, 0x7e, 0x38, 0xf9, 0xbc, 0x57, 0x7a, 0x67, 0x3f,
|
||||
0xdb, 0x33, 0xec, 0x4a, 0xf7, 0xfe, 0xf2, 0x0a, 0x9f, 0x9b, 0x3f, 0xf1, 0x50, 0x7e, 0xd7, 0xdf,
|
||||
0x5d, 0xdc, 0xfc, 0xe4, 0x31, 0x31, 0x7d, 0x8f, 0x16, 0x1e, 0x4b, 0x3f, 0x1b, 0x33, 0x9e, 0x7c,
|
||||
0x3e, 0x1a, 0xc8, 0xf3, 0x15, 0x03, 0xf9, 0xdb, 0xf3, 0x8b, 0x73, 0xc7, 0x37, 0x61, 0xfc, 0xed,
|
||||
0x60, 0x24, 0xcf, 0xbf, 0x61, 0x24, 0xdb, 0x5f, 0xd6, 0x74, 0xfe, 0x0b, 0x1e, 0xf0, 0xb5, 0xd4,
|
||||
0xfd, 0x2f, 0xdf, 0xd2, 0xfd, 0xa3, 0x35, 0xdd, 0x3f, 0x12, 0xf2, 0x4b, 0xbd, 0x3f, 0xfa, 0x8a,
|
||||
0xde, 0xa7, 0x63, 0x78, 0xdb, 0x8f, 0xc6, 0xf3, 0xeb, 0x8a, 0xf1, 0xfc, 0x2a, 0xa3, 0x99, 0x0f,
|
||||
0xe3, 0xd7, 0x23, 0xc3, 0xf0, 0x3a, 0x88, 0xf2, 0xa4, 0x0c, 0x71, 0x34, 0x10, 0x7b, 0xf9, 0xc3,
|
||||
0x01, 0x2b, 0xce, 0x56, 0x74, 0x7d, 0xb6, 0xb9, 0xfb, 0x70, 0xbb, 0xe1, 0x13, 0x14, 0xe7, 0x23,
|
||||
0x38, 0xfb, 0xea, 0x11, 0xcc, 0xc6, 0xf1, 0xfb, 0x9a, 0x25, 0xf9, 0x1d, 0xcf, 0x41, 0x5b, 0x5a,
|
||||
0x93, 0xdf, 0xbf, 0x5e, 0x22, 0xee, 0xb6, 0x2f, 0x47, 0x06, 0x5c, 0xec, 0xfb, 0xbf, 0xf8, 0x20,
|
||||
0x49, 0x77, 0xba, 0xb9, 0xba, 0xd8, 0x52, 0x7f, 0xe5, 0x6f, 0x6f, 0x04, 0xdf, 0xdf, 0xee, 0x2c,
|
||||
0x08, 0x1f, 0xb4, 0x5d, 0xb4, 0xed, 0x92, 0x15, 0x41, 0x85, 0xd0, 0x82, 0x29, 0xbd, 0x9e, 0x53,
|
||||
0xf1, 0x0b, 0x44, 0x0e, 0x6a, 0x48, 0x16, 0x08, 0xbe, 0x7f, 0x3d, 0x25, 0x78, 0x3f, 0xbd, 0x71,
|
||||
0xda, 0x7c, 0x69, 0x84, 0x33, 0x82, 0x8b, 0xd3, 0xd4, 0x44, 0xe1, 0xd4, 0x5e, 0xee, 0xb9, 0xc6,
|
||||
0xc7, 0x71, 0xe9, 0x22, 0xbd, 0x78, 0x39, 0x5a, 0x87, 0x97, 0x58, 0x07, 0x7b, 0xe0, 0xe6, 0xf8,
|
||||
0xd1, 0x32, 0xf6, 0x2f, 0x6c, 0xb2, 0xbc, 0x74, 0x4f, 0xeb, 0xec, 0xe2, 0xce, 0xf5, 0x17, 0xdd,
|
||||
0xf5, 0xd5, 0xf9, 0xe6, 0xf6, 0x93, 0xd3, 0x37, 0x7a, 0xde, 0x5d, 0x8b, 0x85, 0xe5, 0x13, 0xca,
|
||||
0x54, 0x60, 0xec, 0xf7, 0x6e, 0x93, 0x39, 0xfb, 0xae, 0xfc, 0xc7, 0x43, 0x0a, 0xce, 0x83, 0x1f,
|
||||
0xf4, 0xd8, 0xc3, 0x2f, 0x5d, 0x20, 0x8c, 0x7b, 0x84, 0x87, 0xd9, 0xad, 0xbe, 0x40, 0x76, 0xd2,
|
||||
0xe7, 0x7c, 0x0b, 0xe2, 0xea, 0x2b, 0x64, 0xe7, 0x3c, 0xbd, 0xbd, 0x94, 0xf8, 0xf5, 0xd3, 0xea,
|
||||
0x4b, 0x64, 0xaf, 0x3c, 0xfb, 0x63, 0x73, 0xe3, 0x4e, 0x7f, 0x38, 0xdb, 0x5f, 0x23, 0x0c, 0xf8,
|
||||
0xc2, 0x65, 0x51, 0x2e, 0x13, 0xb6, 0x59, 0x6f, 0x60, 0xd7, 0x6c, 0xa8, 0x83, 0x12, 0xbc, 0xbe,
|
||||
0x79, 0xa9, 0x9b, 0xd5, 0x93, 0x4d, 0x7f, 0x87, 0x37, 0x9a, 0x9e, 0xea, 0xb3, 0x55, 0x8f, 0xaf,
|
||||
0xe4, 0x93, 0xd3, 0xd1, 0x4a, 0x9e, 0xae, 0x5e, 0xc9, 0x99, 0xd6, 0xbf, 0x5c, 0xa3, 0xf5, 0xa6,
|
||||
0x8c, 0x67, 0x37, 0x17, 0x17, 0xe7, 0x87, 0x6a, 0xff, 0x72, 0xad, 0xda, 0xbf, 0x3c, 0x62, 0xfd,
|
||||
0x7e, 0xfb, 0x0b, 0xfd, 0xe3, 0xcd, 0x9b, 0x57, 0xfd, 0xe5, 0xdd, 0xa7, 0x83, 0x31, 0xfc, 0xf6,
|
||||
0x35, 0x63, 0x98, 0x19, 0xa0, 0xd3, 0xa9, 0x01, 0x7a, 0xb2, 0xf9, 0x78, 0x7d, 0x0b, 0x63, 0x77,
|
||||
0x7a, 0x7b, 0xd1, 0x5f, 0xdc, 0xf5, 0x07, 0x46, 0xe8, 0xa6, 0xdf, 0xee, 0x56, 0x99, 0x8f, 0x7b,
|
||||
0xe7, 0xb3, 0xcd, 0x97, 0xcc, 0xd0, 0x0c, 0x2c, 0x59, 0x72, 0x0f, 0x6f, 0x46, 0xfa, 0x6e, 0xcf,
|
||||
0xd4, 0xff, 0x56, 0xab, 0x74, 0xd3, 0x5f, 0x1d, 0x12, 0xfd, 0x56, 0xcb, 0x74, 0x23, 0x9e, 0xd1,
|
||||
0x64, 0xf2, 0x7c, 0x23, 0xd4, 0x7d, 0x34, 0x47, 0xe1, 0xef, 0x8c, 0x24, 0x18, 0xab, 0x2b, 0x4f,
|
||||
0xc2, 0xbf, 0x99, 0x78, 0x3f, 0x71, 0xa3, 0x47, 0xf4, 0xd9, 0xf2, 0x7a, 0x2e, 0xaf, 0xb7, 0xe5,
|
||||
0xb5, 0xd5, 0xdd, 0x5b, 0xa7, 0xc7, 0x18, 0x8f, 0xdb, 0xf1, 0x1a, 0xaa, 0xb6, 0xb9, 0xb9, 0xd9,
|
||||
0x7e, 0x9a, 0x48, 0x16, 0x0f, 0x8b, 0xbf, 0xe8, 0xec, 0x21, 0xd1, 0xe6, 0x27, 0x3e, 0x7e, 0xa8,
|
||||
0xe6, 0xec, 0xfb, 0x15, 0x27, 0x3f, 0x91, 0x93, 0xed, 0x49, 0xc7, 0x4e, 0x54, 0xf9, 0xf8, 0x15,
|
||||
0x3c, 0xf3, 0x91, 0x9c, 0xf9, 0x6a, 0xe7, 0x4c, 0x9e, 0xec, 0x47, 0xfa, 0x09, 0x30, 0xc0, 0xdd,
|
||||
0xdb, 0xdb, 0xeb, 0x0f, 0x6f, 0xde, 0xba, 0x1b, 0x15, 0x31, 0xb7, 0x67, 0x43, 0xf7, 0xc9, 0x2b,
|
||||
0x81, 0x53, 0xbf, 0x9a, 0x0d, 0x34, 0xc4, 0x23, 0x0a, 0xc1, 0x28, 0x84, 0x23, 0x14, 0xe2, 0x51,
|
||||
0x0a, 0xdf, 0xbb, 0x77, 0x17, 0x17, 0x37, 0xee, 0x62, 0xd3, 0xbd, 0x75, 0xd8, 0x1d, 0xc7, 0xd4,
|
||||
0x5e, 0x18, 0xb5, 0x17, 0xc7, 0xc6, 0x13, 0xa2, 0x2a, 0x5e, 0x54, 0xcd, 0x4b, 0x11, 0xc1, 0x9e,
|
||||
0x11, 0x7d, 0xdf, 0xff, 0x78, 0x0f, 0x83, 0x1e, 0xff, 0x77, 0x27, 0x47, 0x7c, 0xa0, 0xf7, 0x68,
|
||||
0xdb, 0xba, 0xc7, 0xaa, 0x3e, 0x97, 0x13, 0x7f, 0xe6, 0xca, 0xbe, 0xba, 0xbe, 0xbe, 0xc3, 0x3b,
|
||||
0xa5, 0x5f, 0x5f, 0xbe, 0xd9, 0xdb, 0x53, 0x90, 0x98, 0x69, 0xf7, 0xb3, 0xa9, 0x76, 0xe3, 0x0d,
|
||||
0xbc, 0xe7, 0xee, 0xdf, 0x58, 0x98, 0x03, 0xc5, 0xbe, 0x9a, 0xc4, 0x27, 0x78, 0x2f, 0xc0, 0x5f,
|
||||
0x8c, 0x18, 0x77, 0x14, 0x7f, 0xb9, 0xdd, 0x9c, 0x7f, 0xd8, 0x6c, 0x65, 0x98, 0xe7, 0x97, 0xef,
|
||||
0x1d, 0x34, 0x60, 0x85, 0x70, 0x3d, 0x7b, 0xac, 0x17, 0xfb, 0x5e, 0xb6, 0x5a, 0x3e, 0x63, 0xd1,
|
||||
0x51, 0x38, 0xce, 0x07, 0x0f, 0xf0, 0x3b, 0x84, 0xf8, 0x51, 0xd8, 0xfd, 0x8f, 0xef, 0x5d, 0x10,
|
||||
0xe9, 0xe3, 0x51, 0x89, 0xf7, 0xde, 0xc8, 0x26, 0x33, 0x96, 0xb5, 0x9d, 0x8d, 0x7d, 0xb6, 0xc2,
|
||||
0xc6, 0xfe, 0x73, 0xc9, 0xbf, 0x7c, 0x66, 0x6b, 0x9c, 0xca, 0x89, 0xc8, 0xec, 0x95, 0x6f, 0x66,
|
||||
0xd0, 0x5f, 0xac, 0x31, 0xe8, 0x2f, 0x74, 0xb4, 0xfb, 0x30, 0xeb, 0x70, 0x57, 0x79, 0x71, 0xaf,
|
||||
0x45, 0x9f, 0xd8, 0x70, 0x35, 0x21, 0x3f, 0x20, 0xec, 0xdb, 0xfd, 0x47, 0x1f, 0x4a, 0xab, 0xe1,
|
||||
0xe6, 0x6b, 0x87, 0x17, 0x56, 0x6c, 0x5e, 0x5d, 0x7f, 0xb8, 0xfb, 0xf1, 0xd5, 0x76, 0x73, 0xf5,
|
||||
0x4e, 0xce, 0xd2, 0xe3, 0xf2, 0x03, 0x4f, 0xe5, 0xc3, 0x23, 0xfa, 0xf0, 0x32, 0xf3, 0xff, 0x03,
|
||||
0x5d, 0x2f, 0xbc, 0xe7, 0xe2, 0x7c, 0x00, 0x00,
|
||||
};
|
1230
wled00/html_mobile.h
Normal file
1230
wled00/html_mobile.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -3,19 +3,14 @@
|
||||
*/
|
||||
|
||||
//common CSS of settings pages
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(
|
||||
body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:3em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );}</style>
|
||||
)=====";
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed}hr{border-color:var(--dCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:4em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );}td{padding:2px;}</style>)=====";
|
||||
|
||||
|
||||
//settings menu
|
||||
const char PAGE_settings0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head><title>WLED Settings</title>
|
||||
)=====";
|
||||
const char PAGE_settings0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><title>WLED Settings</title>)=====";
|
||||
|
||||
const char PAGE_settings1[] PROGMEM = R"=====(
|
||||
body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}html{--h:11.55vh}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),Helvetica,sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh}</style>
|
||||
const char PAGE_settings1[] PROGMEM = R"=====(body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}html{--h:11.55vh}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),Helvetica,sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh}</style>
|
||||
<script>function BB(){if(window.frameElement){document.getElementById("b").style.display="none";document.documentElement.style.setProperty("--h","13.86vh")}};</script>
|
||||
</head>
|
||||
<body onload=BB()>
|
||||
@@ -27,19 +22,15 @@ body{text-align:center;background:var(--cCol);height:100%;margin:0;background-at
|
||||
<form action=/settings/time><button type=submit>Time & Macros</button></form>
|
||||
<form action=/settings/sec><button type=submit>Security & Updates</button></form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//wifi settings
|
||||
const char PAGE_settings_wifi0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d = document;
|
||||
)=====";
|
||||
const char PAGE_settings_wifi0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d = document;)=====";
|
||||
|
||||
const char PAGE_settings_wifi1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
const char PAGE_settings_wifi1[] PROGMEM = R"=====(</head>
|
||||
<body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
@@ -76,51 +67,66 @@ AP IP: <span class="sip"> Not active </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//LED settings
|
||||
const char PAGE_settings_leds0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<title>LED Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");}function B(){window.history.back();}function GetV(){var d = document;
|
||||
)=====";
|
||||
const char PAGE_settings_leds0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<title>LED Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");}function B(){window.history.back();}function S(){GetV();UI();}function UI(){
|
||||
var myC=document.querySelectorAll('.wc'),l=myC.length;
|
||||
for (i = 0; i < l; i++){myC[i].style.display=(document.getElementById('rgbw').checked)?'inline':'none';}
|
||||
var val=Math.ceil((100+document.Sf.LC.value*55)/500)/2;
|
||||
val=(val>5)?Math.ceil(val):val;var s="";
|
||||
if (val<1.1){s="ESP 5V pin with 1A USB supply";}else{s="External 5V ";s+=val;s+="A supply connected to LEDs";}
|
||||
document.getElementById('psu').innerHTML=s;document.getElementById('ps2').innerHTML=val+"A = "+val*1000;
|
||||
}function GetV(){var d = document;)=====";
|
||||
|
||||
const char PAGE_settings_leds1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
<body onload="GetV()">
|
||||
const char PAGE_settings_leds1[] PROGMEM = R"=====(</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 setup</h2>
|
||||
LED count: <input name="LC" type="number" min="1" max="1200" required><br>
|
||||
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW"><br>
|
||||
<br>
|
||||
Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)<br>
|
||||
Turn on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
<br>
|
||||
LED count: <input name="LC" type="number" min="1" max="1200" oninput=UI() required><br>
|
||||
<i>Recommended power supply for brightest white:</i><br>
|
||||
<b><span id="psu">?</span></b><br><br>
|
||||
Maximum Current: <input name="MA" type="number" min="250" max="65000" required> mA<br>
|
||||
<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 5V supply, enter its rating.<br>
|
||||
"65000" completely diasbles the power calculation.<br>
|
||||
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
|
||||
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW" onchange=UI() id="rgbw"><br>
|
||||
Color order:
|
||||
<select name="CO">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
<option value="3">RBG</option></select>
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br><br>
|
||||
Default RGB color:
|
||||
<input name="CR" type="number" min="0" max="255" required>
|
||||
<input name="CG" type="number" min="0" max="255" required>
|
||||
<input name="CB" type="number" min="0" max="255" required><br>
|
||||
Default white value (only RGBW): <input name="CW" type="number" min="0" max="255" required><br>
|
||||
Auto-calculate white from RGB instead: <input type="checkbox" name="AW"><br>
|
||||
<span class="wc">Default white value: <input name="CW" type="number" min="0" max="255" required><br>
|
||||
Auto-calculate white from RGB instead: <input type="checkbox" name="AW"><br></span>
|
||||
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br>
|
||||
Default effect ID: <input name="FX" type="number" min="0" max="57" required><br>
|
||||
Default effect speed: <input name="SX" type="number" min="0" max="255" required><br>
|
||||
Default effect intensity: <input name="IX" type="number" min="0" max="255" required><br>
|
||||
Default effect palette: <input name="FP" type="number" min="0" max="255" required><br>
|
||||
Default secondary RGB(W):<br>
|
||||
Default secondary RGB<span class="wc">W</span>:<br>
|
||||
<input name="SR" type="number" min="0" max="255" required>
|
||||
<input name="SG" type="number" min="0" max="255" required>
|
||||
<input name="SB" type="number" min="0" max="255" required>
|
||||
<input name="SW" type="number" min="0" max="255" required><br>
|
||||
Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br>
|
||||
Save current preset cycle configuration as boot default: <input type="checkbox" name="PC"><br>
|
||||
<br>
|
||||
<span class="wc"><input name="SW" type="number" min="0" max="255" required></span><br>
|
||||
Ignore and use current color, brightness and effects: <input type="checkbox" name="IS"><br><br>
|
||||
Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)<br>
|
||||
Save current preset cycle configuration 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>
|
||||
Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br><br>
|
||||
Brightness factor: <input name="BF" type="number" min="0" max="255" required> %
|
||||
<h3>Transitions</h3>
|
||||
Crossfade: <input type="checkbox" name="TF"><br>
|
||||
@@ -140,25 +146,20 @@ Palette blending:
|
||||
<option value="3">None (not recommended)</option>
|
||||
</select><br>
|
||||
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
|
||||
Init LEDs after WiFi: <input type="checkbox" name="EI"><br>
|
||||
Skip first LED: <input type="checkbox" name="SL"><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//User Interface settings
|
||||
const char PAGE_settings_ui0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
const char PAGE_settings_ui0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<title>UI Settings</title><script>
|
||||
function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d = document;
|
||||
)=====";
|
||||
function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d = document;)=====";
|
||||
|
||||
const char PAGE_settings_ui1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
const char PAGE_settings_ui1[] PROGMEM = R"=====(</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
@@ -182,13 +183,13 @@ Color Theme:
|
||||
<option value="4">Electric</option>
|
||||
<option value="5">Mint</option>
|
||||
<option value="6">Amber</option>
|
||||
<option value="7">Club</option>
|
||||
<option value="7">Dark</option>
|
||||
<option value="8">Air</option>
|
||||
<option value="9">Nixie</option>
|
||||
<option value="10">Terminal</option>
|
||||
<option value="11">C64</option>
|
||||
<option value="12">Easter</option>
|
||||
<option value="13">Placeholder</option>
|
||||
<option value="13">Christmas</option>
|
||||
<option value="14">The End</option>
|
||||
<option value="15" id="co">Custom</option>
|
||||
</select><br>
|
||||
@@ -205,26 +206,24 @@ Make sure the font you use is installed on your system!<br>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//sync settings
|
||||
const char PAGE_settings_sync0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head><title>Sync Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d = document;
|
||||
)=====";
|
||||
const char PAGE_settings_sync0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><title>Sync Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d = document;)=====";
|
||||
|
||||
const char PAGE_settings_sync1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
const char PAGE_settings_sync1[] PROGMEM = R"=====(</head>
|
||||
<body onload="GetV()">
|
||||
<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>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
On/Off button enabled: <input type="checkbox" name="BT">
|
||||
On/Off button enabled: <input type="checkbox" name="BT"><br>
|
||||
Infrared receiver enabled: <input type="checkbox" name="IR"><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" maxlength="5" size="4"><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
@@ -237,7 +236,7 @@ Send notifications twice: <input type="checkbox" name="S2"><br>
|
||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
||||
<i>E1.31 (sACN)</i><br>
|
||||
Use E1.31 multicast: <input type="checkbox" name="EM"><br>
|
||||
E1.31 universe: <input name="EU" type="number" min="1" max="63999" required><br>
|
||||
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
|
||||
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
|
||||
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
|
||||
Force max brightness: <input type="checkbox" name="FB"><br>
|
||||
@@ -248,6 +247,10 @@ Enable UI access during realtime: <input type="checkbox" name="RU"> (can cause i
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input name="AI" maxlength="32">
|
||||
<h3>Blynk</h3>
|
||||
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
This impacts the responsiveness of the ESP8266.</b><br>
|
||||
For best results, only use one of these services at a time.<br>
|
||||
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
|
||||
<h3>MQTT</h3>
|
||||
@@ -270,21 +273,20 @@ Hue status: <span class="hms"> Internal ESP Error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//time and macro settings
|
||||
const char PAGE_settings_time0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head><title>Time Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function S(){GetV();Cs();}function gId(s){return document.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";}}function GetV(){var d = document;
|
||||
)=====";
|
||||
const char PAGE_settings_time0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><title>Time Settings</title>
|
||||
<script>var d=document;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){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";}}
|
||||
function BTa(){var ih="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Macro</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for (i=0;i<8;i++){ih+="<tr><td><input name=\"W"+i+"\" id=\"W"+i+"\" type=\"number\" style=\"display:none\"><input id=\"W"+i+"0\" type=\"checkbox\"></td><td><input name=\"H"+i+"\" type=\"number\" min=\"0\" max=\"24\"></td><td><input name=\"N"+i+"\" type=\"number\" min=\"0\" max=\"59\"></td><td><input name=\"T"+i+"\" type=\"number\" min=\"0\" max=\"16\"></td>";for (j=1;j<8;j++) ih+="<td><input id=\"W"+i+j+"\" type=\"checkbox\"></td>";}gId("TMT").innerHTML=ih;}
|
||||
function FC(){for(j=0;j<8;j++){for(i=0;i<8;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1;}}
|
||||
function Wd(){a=[0,0,0,0,0,0,0,0];for(i=0;i<8;i++){m=1;for(j=0;j<8;j++){a[i]+=gId("W"+i+j).checked*m;m*=2;}gId("W"+i).value=a[i];}}function GetV(){)=====";
|
||||
|
||||
const char PAGE_settings_time1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
const char PAGE_settings_time1[] PROGMEM = R"=====(</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<form id="form_s" name="Sf" method="post" onsubmit="Wd()">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Time setup</h2>
|
||||
@@ -329,7 +331,8 @@ Cronixie Display: <input name="CX" maxlength="6"><br>
|
||||
Cronixie Backlight: <input type="checkbox" name="CB"><br>
|
||||
</div>
|
||||
Countdown Mode: <input type="checkbox" name="CE"><br>
|
||||
Countdown Goal: 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>
|
||||
Countdown Goal:<br>
|
||||
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>Advanced Macros</h3>
|
||||
Define API macros here:<br>
|
||||
@@ -355,40 +358,23 @@ Alexa On/Off Macros: <input name="A0" type="number" min="0" max="16" required> <
|
||||
Button Macro: <input name="MP" type="number" min="0" max="16" required> Long Press: <input name="ML" type="number" min="0" max="16" required><br>
|
||||
Countdown-Over Macro: <input name="MC" type="number" min="0" max="16" required><br>
|
||||
Timed-Light-Over Macro: <input name="MN" type="number" min="0" max="16" required><br>
|
||||
Time-Controlled Macros (Hours/Minutes > Macro):<br>
|
||||
<input name="H0" type="number" min="0" max="24"> <input name="N0" type="number" min="0" max="59">
|
||||
> <input name="T0" type="number" min="0" max="16"><br>
|
||||
<input name="H1" type="number" min="0" max="24"> <input name="N1" type="number" min="0" max="59">
|
||||
> <input name="T1" type="number" min="0" max="16"><br>
|
||||
<input name="H2" type="number" min="0" max="24"> <input name="N2" type="number" min="0" max="59">
|
||||
> <input name="T2" type="number" min="0" max="16"><br>
|
||||
<input name="H3" type="number" min="0" max="24"> <input name="N3" type="number" min="0" max="59">
|
||||
> <input name="T3" type="number" min="0" max="16"><br>
|
||||
<input name="H4" type="number" min="0" max="24"> <input name="N4" type="number" min="0" max="59">
|
||||
> <input name="T4" type="number" min="0" max="16"><br>
|
||||
<input name="H5" type="number" min="0" max="24"> <input name="N5" type="number" min="0" max="59">
|
||||
> <input name="T5" type="number" min="0" max="16"><br>
|
||||
<input name="H6" type="number" min="0" max="24"> <input name="N6" type="number" min="0" max="59">
|
||||
> <input name="T6" type="number" min="0" max="16"><br>
|
||||
<input name="H7" type="number" min="0" max="24"> <input name="N7" type="number" min="0" max="59">
|
||||
> <input name="T7" type="number" min="0" max="16"><hr>
|
||||
Time-Controlled Macros:<br>
|
||||
<div style="display: inline-block">
|
||||
<table id="TMT">
|
||||
</table></div><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
||||
|
||||
|
||||
//security settings and about
|
||||
const char PAGE_settings_sec0[] PROGMEM = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
const char PAGE_settings_sec0[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<title>Misc Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings");}function B(){window.open("/settings","_self");}function U(){window.open("/update","_self");}function GetV(){var d = document;
|
||||
)=====";
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings");}function B(){window.open("/settings","_self");}function U(){window.open("/update","_self");}function GetV(){var d = document;)=====";
|
||||
|
||||
const char PAGE_settings_sec1[] PROGMEM = R"=====(
|
||||
</head>
|
||||
const char PAGE_settings_sec1[] PROGMEM = R"=====(</head>
|
||||
<body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
@@ -411,27 +397,13 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
|
||||
<button type="button" onclick="U()">Manual OTA Update</button><br>
|
||||
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
|
||||
<h3>About</h3>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.8.0<br><br>
|
||||
<b>Contributors:</b><br>
|
||||
StormPie <i>(Mobile HTML UI)</i><br><br>
|
||||
Thank you so much!<br><br>
|
||||
(c) 2016-2018 Christian Schwinne <br>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.8.3<br><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br>
|
||||
A huge thank you to everyone who helped me create WLED!<br><br>
|
||||
(c) 2016-2019 Christian Schwinne <br>
|
||||
<i>Licensed under the MIT license</i><br><br>
|
||||
<b>Uses libraries:</b><br>
|
||||
<i>ESP8266/ESP32 Arduino Core</i><br>
|
||||
<i><a href="https://github.com/svenihoney/NeoPixelBus" target="_blank">NeoPixelBus</a> by Makuna (svenihoney fork)</i><br>
|
||||
<i><a href="https://github.com/FastLED/FastLED/" target="_blank">FastLED</a> library</i><br>
|
||||
<i>(ESP32) <a href="https://github.com/bbx10/WebServer_tng" target="_blank">WebServer_tng</a> by bbx10</i><br>
|
||||
<i><a href="https://github.com/kitesurfer1404/WS2812FX" target="_blank">WS2812FX</a> by kitesurfer1404 (modified)</i><br>
|
||||
<i><a href="https://github.com/JChristensen/Timezone" target="_blank">Timezone</a> library by JChristensen</i><br>
|
||||
<i><a href="https://github.com/blynkkk/blynk-library" target="_blank">Blynk</a> library (compacted)</i><br>
|
||||
<i><a href="https://github.com/forkineye/E131" target="_blank">E1.31</a> library by forkineye (modified)</i><br>
|
||||
<i><a href="https://github.com/knolleary/pubsubclient" target="_blank">PubSubClient</a> by knolleary (modified)</i><br>
|
||||
<i><a href="https://github.com/Aircoookie/Espalexa" target="_blank">Espalexa</a> by Aircoookie (modified)</i><br><br>
|
||||
<i>UI icons by <a href="https://linearicons.com" target="_blank">Linearicons</a> created by <a href="https://perxis.com" target="_blank">Perxis</a>! (CC-BY-SA 4.0)</i> <br><br>
|
||||
Server message: <span class="msg"> Response error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
</html>)=====";
|
157
wled00/htmls00.h
157
wled00/htmls00.h
File diff suppressed because one or more lines are too long
95
wled00/ir_codes.h
Normal file
95
wled00/ir_codes.h
Normal file
@@ -0,0 +1,95 @@
|
||||
//Infrared codes
|
||||
|
||||
//Add your custom codes here
|
||||
#define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example)
|
||||
#define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for
|
||||
|
||||
//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/
|
||||
#define IR24_BRIGHTER 0xF700FF
|
||||
#define IR24_DARKER 0xF7807F
|
||||
#define IR24_OFF 0xF740BF
|
||||
#define IR24_ON 0xF7C03F
|
||||
#define IR24_RED 0xF720DF
|
||||
#define IR24_REDDISH 0xF710EF
|
||||
#define IR24_ORANGE 0xF730CF
|
||||
#define IR24_YELLOWISH 0xF708F7
|
||||
#define IR24_YELLOW 0xF728D7
|
||||
#define IR24_GREEN 0xF7A05F
|
||||
#define IR24_GREENISH 0xF7906F
|
||||
#define IR24_TURQUOISE 0xF7B04F
|
||||
#define IR24_CYAN 0xF78877
|
||||
#define IR24_AQUA 0xF7A857
|
||||
#define IR24_BLUE 0xF7609F
|
||||
#define IR24_DEEPBLUE 0xF750AF
|
||||
#define IR24_PURPLE 0xF7708F
|
||||
#define IR24_MAGENTA 0xF748B7
|
||||
#define IR24_PINK 0xF76897
|
||||
#define IR24_WHITE 0xF7E01F
|
||||
#define IR24_FLASH 0xF7D02F
|
||||
#define IR24_STROBE 0xF7F00F
|
||||
#define IR24_FADE 0xF7C837
|
||||
#define IR24_SMOOTH 0xF7E817
|
||||
|
||||
/* 44-key defs, to be done later
|
||||
#define IR44_BPlus 0xFF3AC5 //
|
||||
#define IR44_BMinus 0xFFBA45 //
|
||||
#define IR44_ON 0xFF827D //
|
||||
#define IR44_OFF 0xFF02FD //
|
||||
#define IR44_R 0xFF1AE5 //
|
||||
#define IR44_G 0xFF9A65 //
|
||||
#define IR44_B 0xFFA25D //
|
||||
#define IR44_W 0xFF22DD //
|
||||
#define IR44_B1 0xFF2AD5 //
|
||||
#define IR44_B2 0xFFAA55 //
|
||||
#define IR44_B3 0xFF926D //
|
||||
#define IR44_B4 0xFF12ED //
|
||||
#define IR44_B5 0xFF0AF5 //
|
||||
#define IR44_B6 0xFF8A75 //
|
||||
#define IR44_B7 0xFFB24D //
|
||||
#define IR44_B8 0xFF32CD //
|
||||
#define IR44_B9 0xFF38C7 //
|
||||
#define IR44_B10 0xFFB847 //
|
||||
#define IR44_B11 0xFF7887 //
|
||||
#define IR44_B12 0xFFF807 //
|
||||
#define IR44_B13 0xFF18E7 //
|
||||
#define IR44_B14 0xFF9867 //
|
||||
#define IR44_B15 0xFF58A7 //
|
||||
#define IR44_B16 0xFFD827 //
|
||||
#define IR44_UPR 0xFF28D7 //
|
||||
#define IR44_UPG 0xFFA857 //
|
||||
#define IR44_UPB 0xFF6897 //
|
||||
#define IR44_QUICK 0xFFE817 //
|
||||
#define IR44_DOWNR 0xFF08F7 //
|
||||
#define IR44_DOWNG 0xFF8877 //
|
||||
#define IR44_DOWNB 0xFF48B7 //
|
||||
#define IR44_SLOW 0xFFC837 //
|
||||
#define IR44_DIY1 0xFF30CF //
|
||||
#define IR44_DIY2 0xFFB04F //
|
||||
#define IR44_DIY3 0xFF708F //
|
||||
#define IR44_AUTO 0xFFF00F //
|
||||
#define IR44_DIY4 0xFF10EF //
|
||||
#define IR44_DIY5 0xFF906F //
|
||||
#define IR44_DIY6 0xFF50AF //
|
||||
#define IR44_FLASH 0xFFD02F //
|
||||
#define IR44_JUMP3 0xFF20DF //
|
||||
#define IR44_JUMP7 0xFFA05F //
|
||||
#define IR44_FADE3 0xFF609F //
|
||||
#define IR44_FADE7 0xFFE01F //
|
||||
*/
|
||||
|
||||
#define COLOR_RED 0xFF0000
|
||||
#define COLOR_REDDISH 0xFF7800
|
||||
#define COLOR_ORANGE 0xFFA000
|
||||
#define COLOR_YELLOWISH 0xFFC800
|
||||
#define COLOR_YELLOW 0xFFFF00
|
||||
#define COLOR_GREEN 0x00FF00
|
||||
#define COLOR_GREENISH 0x00FF78
|
||||
#define COLOR_TURQUOISE 0x00FFA0
|
||||
#define COLOR_CYAN 0x00FFDC
|
||||
#define COLOR_AQUA 0x00C8FF
|
||||
#define COLOR_BLUE 0x00A0FF
|
||||
#define COLOR_DEEPBLUE 0x0000FF
|
||||
#define COLOR_PURPLE 0xAA00FF
|
||||
#define COLOR_MAGENTA 0xFF00DC
|
||||
#define COLOR_PINK 0xFF00A0
|
||||
#define COLOR_WHITE 0xFFFFDC
|
@@ -500,6 +500,42 @@ DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
|
||||
200, 255, 72, 0,
|
||||
255, 255, 72, 0};
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
|
||||
0, 1, 2, 14, //gc
|
||||
33, 2, 5, 35, //gc from 47, 61,126
|
||||
100, 13,135, 92, //gc from 88,242,247
|
||||
120, 43,255,193, //gc from 135,255,253
|
||||
140, 247, 7,249, //gc from 252, 69,253
|
||||
160, 193, 17,208, //gc from 231, 96,237
|
||||
180, 39,255,154, //gc from 130, 77,213
|
||||
200, 4,213,236, //gc from 57,122,248
|
||||
220, 39,252,135, //gc from 177,254,255
|
||||
240, 193,213,253, //gc from 203,239,253
|
||||
255, 255,249,255};
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
|
||||
0, 1, 5, 45, //deep blue
|
||||
10, 1, 5, 45,
|
||||
25, 5,169,175, //light blue
|
||||
40, 1, 5, 45,
|
||||
61, 1, 5, 45,
|
||||
76, 45,175, 31, //green
|
||||
91, 1, 5, 45,
|
||||
112, 1, 5, 45,
|
||||
127, 249,150, 5, //yellow
|
||||
143, 1, 5, 45,
|
||||
162, 1, 5, 45,
|
||||
178, 255,92, 0, //pastel orange
|
||||
193, 1, 5, 45,
|
||||
214, 1, 5, 45,
|
||||
229, 223, 45, 72, //pink
|
||||
244, 1, 5, 45,
|
||||
255, 1, 5, 45};
|
||||
|
||||
|
||||
// Single array of defined cpt-city color palettes.
|
||||
// This will let us programmatically choose one based on
|
||||
@@ -543,8 +579,10 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
|
||||
BlacK_Magenta_Red_gp, //41-28 Magred
|
||||
BlacK_Red_Magenta_Yellow_gp, //42-29 Yelmag
|
||||
Blue_Cyan_Yellow_gp, //43-30 Yelblu
|
||||
Orange_Teal_gp //44-31 Orange & Teal
|
||||
};
|
||||
Orange_Teal_gp, //44-31 Orange & Teal
|
||||
Tiamat_gp, //45-32 Tiamat
|
||||
April_Night_gp //46-33 April Night
|
||||
};
|
||||
|
||||
|
||||
// Count of how many cpt-city gradients are defined:
|
||||
@@ -552,4 +590,3 @@ const uint8_t gGradientPaletteCount =
|
||||
sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );
|
||||
|
||||
#endif
|
||||
|
||||
|
487
wled00/src/dependencies/espalexa/Espalexa.h
Normal file
487
wled00/src/dependencies/espalexa/Espalexa.h
Normal file
@@ -0,0 +1,487 @@
|
||||
#ifndef Espalexa_h
|
||||
#define Espalexa_h
|
||||
|
||||
/*
|
||||
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
|
||||
*
|
||||
* This was put together from these two excellent projects:
|
||||
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
|
||||
* https://github.com/probonopd/ESP8266HueEmulator
|
||||
*/
|
||||
/*
|
||||
* @title Espalexa library
|
||||
* @version 2.3.3
|
||||
* @author Christian Schwinne
|
||||
* @license MIT
|
||||
* @contributors d-999
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
//you can use these defines for library config in your sketch. Just use them before #include <Espalexa.h>
|
||||
//#define ESPALEXA_ASYNC
|
||||
|
||||
#ifndef ESPALEXA_MAXDEVICES
|
||||
#define ESPALEXA_MAXDEVICES 10 //this limit only has memory reasons, set it higher should you need to
|
||||
#endif
|
||||
|
||||
//#define ESPALEXA_DEBUG
|
||||
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include <AsyncTCP.h>
|
||||
#else
|
||||
#include <ESPAsyncTCP.h>
|
||||
#endif
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#else
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include <WiFi.h>
|
||||
#include "../webserver/WebServer.h" //if you get an error here please update to ESP32 arduino core 1.0.0
|
||||
#else
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifdef ESPALEXA_DEBUG
|
||||
#pragma message "Espalexa 2.3.3 debug mode"
|
||||
#define EA_DEBUG(x) Serial.print (x)
|
||||
#define EA_DEBUGLN(x) Serial.println (x)
|
||||
#else
|
||||
#define EA_DEBUG(x)
|
||||
#define EA_DEBUGLN(x)
|
||||
#endif
|
||||
|
||||
#include "EspalexaDevice.h"
|
||||
|
||||
class Espalexa {
|
||||
private:
|
||||
//private member vars
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
AsyncWebServer* serverAsync;
|
||||
AsyncWebServerRequest* server; //this saves many #defines
|
||||
String body = "";
|
||||
#elif defined ARDUINO_ARCH_ESP32
|
||||
WebServer* server;
|
||||
#else
|
||||
ESP8266WebServer* server;
|
||||
#endif
|
||||
uint8_t currentDeviceCount = 0;
|
||||
|
||||
EspalexaDevice* devices[ESPALEXA_MAXDEVICES] = {};
|
||||
//Keep in mind that Device IDs go from 1 to DEVICES, cpp arrays from 0 to DEVICES-1!!
|
||||
|
||||
WiFiUDP espalexaUdp;
|
||||
IPAddress ipMulti;
|
||||
bool udpConnected = false;
|
||||
char packetBuffer[255]; //buffer to hold incoming udp packet
|
||||
String escapedMac=""; //lowercase mac address
|
||||
|
||||
//private member functions
|
||||
String deviceJsonString(uint8_t deviceId)
|
||||
{
|
||||
if (deviceId < 1 || deviceId > currentDeviceCount) return "{}"; //error
|
||||
EspalexaDevice* dev = devices[deviceId-1];
|
||||
String json = "{\"type\":\"";
|
||||
json += dev->isColorDevice() ? "Extended color light" : "Dimmable light";
|
||||
json += "\",\"manufacturername\":\"OpenSource\",\"swversion\":\"0.1\",\"name\":\"";
|
||||
json += dev->getName();
|
||||
json += "\",\"uniqueid\":\""+ WiFi.macAddress() +"-"+ (deviceId+1) ;
|
||||
json += "\",\"modelid\":\"LST001\",\"state\":{\"on\":";
|
||||
json += boolString(dev->getValue()) +",\"bri\":"+ (String)(dev->getLastValue()-1) ;
|
||||
if (dev->isColorDevice())
|
||||
{
|
||||
json += ",\"xy\":[0.00000,0.00000],\"colormode\":\"";
|
||||
json += (dev->isColorTemperatureMode()) ? "ct":"hs";
|
||||
json += "\",\"effect\":\"none\",\"ct\":" + (String)(dev->getCt()) + ",\"hue\":" + (String)(dev->getHue()) + ",\"sat\":" + (String)(dev->getSat());
|
||||
}
|
||||
json +=",\"alert\":\"none\",\"reachable\":true}}";
|
||||
return json;
|
||||
}
|
||||
|
||||
//Espalexa status page /espalexa
|
||||
void servePage()
|
||||
{
|
||||
EA_DEBUGLN("HTTP Req espalexa ...\n");
|
||||
String res = "Hello from Espalexa!\r\n\r\n";
|
||||
for (int i=0; i<currentDeviceCount; i++)
|
||||
{
|
||||
res += "Value of device " + String(i+1) + " (" + devices[i]->getName() + "): " + String(devices[i]->getValue()) + "\r\n";
|
||||
}
|
||||
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
|
||||
res += "\r\nUptime: " + (String)millis();
|
||||
res += "\r\n\r\nEspalexa library v2.3.3 by Christian Schwinne 2019";
|
||||
server->send(200, "text/plain", res);
|
||||
}
|
||||
|
||||
//not found URI (only if internal webserver is used)
|
||||
void serveNotFound()
|
||||
{
|
||||
EA_DEBUGLN("Not-Found HTTP call:");
|
||||
#ifndef ESPALEXA_ASYNC
|
||||
EA_DEBUGLN("URI: " + server->uri());
|
||||
EA_DEBUGLN("Body: " + server->arg(0));
|
||||
if(!handleAlexaApiCall(server->uri(), server->arg(0)))
|
||||
#else
|
||||
EA_DEBUGLN("URI: " + server->url());
|
||||
EA_DEBUGLN("Body: " + body);
|
||||
if(!handleAlexaApiCall(server))
|
||||
#endif
|
||||
server->send(404, "text/plain", "Not Found (espalexa-internal)");
|
||||
}
|
||||
|
||||
//send description.xml device property page
|
||||
void serveDescription()
|
||||
{
|
||||
EA_DEBUGLN("# Responding to description.xml ... #\n");
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
|
||||
String setup_xml = "<?xml version=\"1.0\" ?>"
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
||||
"<URLBase>http://"+ String(s) +":80/</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
||||
"<friendlyName>Philips hue ("+ String(s) +")</friendlyName>"
|
||||
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
||||
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
||||
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
||||
"<modelName>Philips hue bridge 2012</modelName>"
|
||||
"<modelNumber>929000226503</modelNumber>"
|
||||
"<modelURL>http://www.meethue.com</modelURL>"
|
||||
"<serialNumber>"+ escapedMac +"</serialNumber>"
|
||||
"<UDN>uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"</UDN>"
|
||||
"<presentationURL>index.html</presentationURL>"
|
||||
"<iconList>"
|
||||
" <icon>"
|
||||
" <mimetype>image/png</mimetype>"
|
||||
" <height>48</height>"
|
||||
" <width>48</width>"
|
||||
" <depth>24</depth>"
|
||||
" <url>hue_logo_0.png</url>"
|
||||
" </icon>"
|
||||
" <icon>"
|
||||
" <mimetype>image/png</mimetype>"
|
||||
" <height>120</height>"
|
||||
" <width>120</width>"
|
||||
" <depth>24</depth>"
|
||||
" <url>hue_logo_3.png</url>"
|
||||
" </icon>"
|
||||
"</iconList>"
|
||||
"</device>"
|
||||
"</root>";
|
||||
|
||||
server->send(200, "text/xml", setup_xml.c_str());
|
||||
|
||||
EA_DEBUG("Sending :");
|
||||
EA_DEBUGLN(setup_xml);
|
||||
}
|
||||
|
||||
//init the server
|
||||
void startHttpServer()
|
||||
{
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
if (serverAsync == nullptr) {
|
||||
serverAsync = new AsyncWebServer(80);
|
||||
serverAsync->onNotFound([=](AsyncWebServerRequest *request){server = request; serveNotFound();});
|
||||
}
|
||||
|
||||
serverAsync->onRequestBody([=](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
|
||||
char b[len +1];
|
||||
b[len] = 0;
|
||||
memcpy(b, data, len);
|
||||
body = b; //save the body so we can use it for the API call
|
||||
EA_DEBUG("Received body: ");
|
||||
EA_DEBUGLN(body);
|
||||
});
|
||||
serverAsync->on("/espalexa", HTTP_GET, [=](AsyncWebServerRequest *request){server = request; servePage();});
|
||||
serverAsync->on("/description.xml", HTTP_GET, [=](AsyncWebServerRequest *request){server = request; serveDescription();});
|
||||
serverAsync->begin();
|
||||
|
||||
#else
|
||||
if (server == nullptr) {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
server = new WebServer(80);
|
||||
#else
|
||||
server = new ESP8266WebServer(80);
|
||||
#endif
|
||||
server->onNotFound([=](){serveNotFound();});
|
||||
}
|
||||
|
||||
server->on("/espalexa", HTTP_GET, [=](){servePage();});
|
||||
server->on("/description.xml", HTTP_GET, [=](){serveDescription();});
|
||||
server->begin();
|
||||
#endif
|
||||
}
|
||||
|
||||
//called when Alexa sends ON command
|
||||
void alexaOn(uint8_t deviceId)
|
||||
{
|
||||
devices[deviceId-1]->setValue(devices[deviceId-1]->getLastValue());
|
||||
devices[deviceId-1]->setPropertyChanged(1);
|
||||
devices[deviceId-1]->doCallback();
|
||||
}
|
||||
|
||||
//called when Alexa sends OFF command
|
||||
void alexaOff(uint8_t deviceId)
|
||||
{
|
||||
devices[deviceId-1]->setValue(0);
|
||||
devices[deviceId-1]->setPropertyChanged(2);
|
||||
devices[deviceId-1]->doCallback();
|
||||
}
|
||||
|
||||
//called when Alexa sends BRI command
|
||||
void alexaDim(uint8_t deviceId, uint8_t briL)
|
||||
{
|
||||
if (briL == 255)
|
||||
{
|
||||
devices[deviceId-1]->setValue(255);
|
||||
} else {
|
||||
devices[deviceId-1]->setValue(briL+1);
|
||||
}
|
||||
devices[deviceId-1]->setPropertyChanged(3);
|
||||
devices[deviceId-1]->doCallback();
|
||||
}
|
||||
|
||||
//called when Alexa sends HUE command
|
||||
void alexaCol(uint8_t deviceId, uint16_t hue, uint8_t sat)
|
||||
{
|
||||
devices[deviceId-1]->setColor(hue, sat);
|
||||
devices[deviceId-1]->setPropertyChanged(4);
|
||||
devices[deviceId-1]->doCallback();
|
||||
}
|
||||
|
||||
//called when Alexa sends CT command (color temperature)
|
||||
void alexaCt(uint8_t deviceId, uint16_t ct)
|
||||
{
|
||||
devices[deviceId-1]->setColor(ct);
|
||||
devices[deviceId-1]->setPropertyChanged(5);
|
||||
devices[deviceId-1]->doCallback();
|
||||
}
|
||||
|
||||
//respond to UDP SSDP M-SEARCH
|
||||
void respondToSearch()
|
||||
{
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
|
||||
String response =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"EXT:\r\n"
|
||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||
"LOCATION: http://"+ String(s) +":80/description.xml\r\n"
|
||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
||||
"hue-bridgeid: "+ escapedMac +"\r\n"
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::upnp:rootdevice\r\n" // _uuid::_deviceType
|
||||
"\r\n";
|
||||
|
||||
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
espalexaUdp.write((uint8_t*)response.c_str(), response.length());
|
||||
#else
|
||||
espalexaUdp.write(response.c_str());
|
||||
#endif
|
||||
espalexaUdp.endPacket();
|
||||
}
|
||||
|
||||
String boolString(bool st)
|
||||
{
|
||||
return(st)?"true":"false";
|
||||
}
|
||||
|
||||
public:
|
||||
Espalexa(){}
|
||||
|
||||
//initialize interfaces
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
bool begin(AsyncWebServer* externalServer = nullptr)
|
||||
#elif defined ARDUINO_ARCH_ESP32
|
||||
bool begin(WebServer* externalServer = nullptr)
|
||||
#else
|
||||
bool begin(ESP8266WebServer* externalServer = nullptr)
|
||||
#endif
|
||||
{
|
||||
EA_DEBUGLN("Espalexa Begin...");
|
||||
EA_DEBUG("MAXDEVICES ");
|
||||
EA_DEBUGLN(ESPALEXA_MAXDEVICES);
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
serverAsync = externalServer;
|
||||
#else
|
||||
server = externalServer;
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
udpConnected = espalexaUdp.beginMulticast(IPAddress(239, 255, 255, 250), 1900);
|
||||
#else
|
||||
udpConnected = espalexaUdp.beginMulticast(WiFi.localIP(), IPAddress(239, 255, 255, 250), 1900);
|
||||
#endif
|
||||
|
||||
if (udpConnected){
|
||||
|
||||
startHttpServer();
|
||||
EA_DEBUGLN("Done");
|
||||
return true;
|
||||
}
|
||||
EA_DEBUGLN("Failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
//service loop
|
||||
void loop() {
|
||||
#ifndef ESPALEXA_ASYNC
|
||||
if (server == nullptr) return; //only if begin() was not called
|
||||
server->handleClient();
|
||||
#endif
|
||||
|
||||
if (!udpConnected) return;
|
||||
int packetSize = espalexaUdp.parsePacket();
|
||||
if (!packetSize) return; //no new udp packet
|
||||
|
||||
EA_DEBUGLN("Got UDP!");
|
||||
int len = espalexaUdp.read(packetBuffer, 254);
|
||||
if (len > 0) {
|
||||
packetBuffer[len] = 0;
|
||||
}
|
||||
espalexaUdp.flush();
|
||||
|
||||
String request = packetBuffer;
|
||||
EA_DEBUGLN(request);
|
||||
if(request.indexOf("M-SEARCH") >= 0) {
|
||||
if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0) {
|
||||
EA_DEBUGLN("Responding search req...");
|
||||
respondToSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool addDevice(EspalexaDevice* d)
|
||||
{
|
||||
EA_DEBUG("Adding device ");
|
||||
EA_DEBUGLN((currentDeviceCount+1));
|
||||
if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false;
|
||||
devices[currentDeviceCount] = d;
|
||||
currentDeviceCount++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addDevice(String deviceName, CallbackBriFunction callback, uint8_t initialValue = 0)
|
||||
{
|
||||
EA_DEBUG("Constructing device ");
|
||||
EA_DEBUGLN((currentDeviceCount+1));
|
||||
if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false;
|
||||
EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue);
|
||||
return addDevice(d);
|
||||
}
|
||||
|
||||
bool addDevice(String deviceName, CallbackColFunction callback, uint8_t initialValue = 0)
|
||||
{
|
||||
EA_DEBUG("Constructing device ");
|
||||
EA_DEBUGLN((currentDeviceCount+1));
|
||||
if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false;
|
||||
EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue);
|
||||
return addDevice(d);
|
||||
}
|
||||
|
||||
//basic implementation of Philips hue api functions needed for basic Alexa control
|
||||
#ifdef ESPALEXA_ASYNC
|
||||
bool handleAlexaApiCall(AsyncWebServerRequest* request)
|
||||
{
|
||||
server = request; //copy request reference
|
||||
String req = request->url(); //body from global variable
|
||||
EA_DEBUGLN(request->contentType());
|
||||
if (request->hasParam("body", true)) // This is necessary, otherwise ESP crashes if there is no body
|
||||
{
|
||||
EA_DEBUG("BodyMethod2");
|
||||
body = request->getParam("body", true)->value();
|
||||
}
|
||||
EA_DEBUG("FinalBody: ");
|
||||
EA_DEBUGLN(body);
|
||||
#else
|
||||
bool handleAlexaApiCall(String req, String body)
|
||||
{
|
||||
#endif
|
||||
EA_DEBUGLN("AlexaApiCall");
|
||||
if (req.indexOf("api") <0) return false; //return if not an API call
|
||||
EA_DEBUGLN("ok");
|
||||
|
||||
if (body.indexOf("devicetype") > 0) //client wants a hue api username, we dont care and give static
|
||||
{
|
||||
EA_DEBUGLN("devType");
|
||||
body = "";
|
||||
server->send(200, "application/json", "[{\"success\":{\"username\": \"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (req.indexOf("state") > 0) //client wants to control light
|
||||
{
|
||||
server->send(200, "application/json", "[{\"success\":true}]"); //short valid response
|
||||
|
||||
int tempDeviceId = req.substring(req.indexOf("lights")+7).toInt();
|
||||
EA_DEBUG("ls"); EA_DEBUGLN(tempDeviceId);
|
||||
if (body.indexOf("false")>0) {alexaOff(tempDeviceId); return true;}
|
||||
if (body.indexOf("bri")>0 ) {alexaDim(tempDeviceId, body.substring(body.indexOf("bri") +5).toInt()); return true;}
|
||||
if (body.indexOf("hue")>0 ) {alexaCol(tempDeviceId, body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt()); return true;}
|
||||
if (body.indexOf("ct") >0 ) {alexaCt (tempDeviceId, body.substring(body.indexOf("ct") +4).toInt()); return true;}
|
||||
alexaOn(tempDeviceId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int pos = req.indexOf("lights");
|
||||
if (pos > 0) //client wants light info
|
||||
{
|
||||
int tempDeviceId = req.substring(pos+7).toInt();
|
||||
EA_DEBUG("l"); EA_DEBUGLN(tempDeviceId);
|
||||
|
||||
if (tempDeviceId == 0) //client wants all lights
|
||||
{
|
||||
EA_DEBUGLN("lAll");
|
||||
String jsonTemp = "{";
|
||||
for (int i = 0; i<currentDeviceCount; i++)
|
||||
{
|
||||
jsonTemp += "\"" + String(i+1) + "\":";
|
||||
jsonTemp += deviceJsonString(i+1);
|
||||
if (i < currentDeviceCount-1) jsonTemp += ",";
|
||||
}
|
||||
jsonTemp += "}";
|
||||
server->send(200, "application/json", jsonTemp);
|
||||
} else //client wants one light (tempDeviceId)
|
||||
{
|
||||
server->send(200, "application/json", deviceJsonString(tempDeviceId));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//we dont care about other api commands at this time and send empty JSON
|
||||
server->send(200, "application/json", "{}");
|
||||
return true;
|
||||
}
|
||||
|
||||
//is an unique device ID
|
||||
String getEscapedMac()
|
||||
{
|
||||
return escapedMac;
|
||||
}
|
||||
|
||||
//convert brightness (0-255) to percentage
|
||||
uint8_t toPercent(uint8_t bri)
|
||||
{
|
||||
uint16_t perc = bri * 100;
|
||||
return perc / 255;
|
||||
}
|
||||
|
||||
~Espalexa(){delete devices;} //note: Espalexa is NOT meant to be destructed
|
||||
};
|
||||
|
||||
#endif
|
||||
|
176
wled00/src/dependencies/espalexa/EspalexaDevice.cpp
Normal file
176
wled00/src/dependencies/espalexa/EspalexaDevice.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
//EspalexaDevice Class
|
||||
|
||||
#include "EspalexaDevice.h"
|
||||
|
||||
EspalexaDevice::EspalexaDevice(){}
|
||||
|
||||
EspalexaDevice::EspalexaDevice(String deviceName, CallbackBriFunction gnCallback, uint8_t initialValue) { //constructor
|
||||
|
||||
_deviceName = deviceName;
|
||||
_callback = gnCallback;
|
||||
_val = initialValue;
|
||||
_val_last = _val;
|
||||
}
|
||||
|
||||
EspalexaDevice::EspalexaDevice(String deviceName, CallbackColFunction gnCallback, uint8_t initialValue) { //constructor for color device
|
||||
|
||||
_deviceName = deviceName;
|
||||
_callbackCol = gnCallback;
|
||||
_callback = nullptr;
|
||||
_val = initialValue;
|
||||
_val_last = _val;
|
||||
}
|
||||
|
||||
EspalexaDevice::~EspalexaDevice(){/*nothing to destruct*/}
|
||||
|
||||
bool EspalexaDevice::isColorDevice()
|
||||
{
|
||||
//if brightness-only callback is null, we have color device
|
||||
return (_callback == nullptr);
|
||||
}
|
||||
|
||||
bool EspalexaDevice::isColorTemperatureMode()
|
||||
{
|
||||
return _ct;
|
||||
}
|
||||
|
||||
String EspalexaDevice::getName()
|
||||
{
|
||||
return _deviceName;
|
||||
}
|
||||
|
||||
uint8_t EspalexaDevice::getLastChangedProperty()
|
||||
{
|
||||
return _changed;
|
||||
}
|
||||
|
||||
uint8_t EspalexaDevice::getValue()
|
||||
{
|
||||
return _val;
|
||||
}
|
||||
|
||||
uint16_t EspalexaDevice::getHue()
|
||||
{
|
||||
return _hue;
|
||||
}
|
||||
|
||||
uint8_t EspalexaDevice::getSat()
|
||||
{
|
||||
return _sat;
|
||||
}
|
||||
|
||||
uint16_t EspalexaDevice::getCt()
|
||||
{
|
||||
if (_ct == 0) return 500;
|
||||
return _ct;
|
||||
}
|
||||
|
||||
uint32_t EspalexaDevice::getColorRGB()
|
||||
{
|
||||
uint8_t rgb[3];
|
||||
|
||||
if (isColorTemperatureMode())
|
||||
{
|
||||
//TODO tweak a bit to match hue lamp characteristics
|
||||
//based on https://gist.github.com/paulkaplan/5184275
|
||||
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
|
||||
float r, g, b;
|
||||
|
||||
if( temp <= 66 ){
|
||||
r = 255;
|
||||
g = temp;
|
||||
g = 99.470802 * log(g) - 161.119568;
|
||||
if( temp <= 19){
|
||||
b = 0;
|
||||
} else {
|
||||
b = temp-10;
|
||||
b = 138.517731 * log(b) - 305.044793;
|
||||
}
|
||||
} else {
|
||||
r = temp - 60;
|
||||
r = 329.698727 * pow(r, -0.13320476);
|
||||
g = temp - 60;
|
||||
g = 288.12217 * pow(g, -0.07551485 );
|
||||
b = 255;
|
||||
}
|
||||
|
||||
rgb[0] = (byte)constrain(r,0.1,255.1);
|
||||
rgb[1] = (byte)constrain(g,0.1,255.1);
|
||||
rgb[2] = (byte)constrain(b,0.1,255.1);
|
||||
}
|
||||
else
|
||||
{ //hue + sat mode
|
||||
float h = ((float)_hue)/65535.0;
|
||||
float s = ((float)_sat)/255.0;
|
||||
byte i = floor(h*6);
|
||||
float f = h * 6-i;
|
||||
float p = 255 * (1-s);
|
||||
float q = 255 * (1-f*s);
|
||||
float t = 255 * (1-(1-f)*s);
|
||||
switch (i%6) {
|
||||
case 0: rgb[0]=255,rgb[1]=t,rgb[2]=p;break;
|
||||
case 1: rgb[0]=q,rgb[1]=255,rgb[2]=p;break;
|
||||
case 2: rgb[0]=p,rgb[1]=255,rgb[2]=t;break;
|
||||
case 3: rgb[0]=p,rgb[1]=q,rgb[2]=255;break;
|
||||
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
|
||||
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
|
||||
}
|
||||
}
|
||||
return ((rgb[0] << 16) | (rgb[1] << 8) | (rgb[2]));
|
||||
}
|
||||
|
||||
uint8_t EspalexaDevice::getLastValue()
|
||||
{
|
||||
if (_val_last == 0) return 255;
|
||||
return _val_last;
|
||||
}
|
||||
|
||||
void EspalexaDevice::setPropertyChanged(uint8_t p)
|
||||
{
|
||||
//0: initial 1: on 2: off 3: bri 4: col 5: ct
|
||||
_changed = p;
|
||||
}
|
||||
|
||||
//you need to re-discover the device for the Alexa name to change
|
||||
void EspalexaDevice::setName(String name)
|
||||
{
|
||||
_deviceName = name;
|
||||
}
|
||||
|
||||
void EspalexaDevice::setValue(uint8_t val)
|
||||
{
|
||||
if (_val != 0)
|
||||
{
|
||||
_val_last = _val;
|
||||
}
|
||||
if (val != 0)
|
||||
{
|
||||
_val_last = val;
|
||||
}
|
||||
_val = val;
|
||||
}
|
||||
|
||||
void EspalexaDevice::setPercent(uint8_t perc)
|
||||
{
|
||||
uint16_t val = perc * 255;
|
||||
val /= 100;
|
||||
if (val > 255) val = 255;
|
||||
setValue(val);
|
||||
}
|
||||
|
||||
void EspalexaDevice::setColor(uint16_t hue, uint8_t sat)
|
||||
{
|
||||
_hue = hue;
|
||||
_sat = sat;
|
||||
_ct = 0;
|
||||
}
|
||||
|
||||
void EspalexaDevice::setColor(uint16_t ct)
|
||||
{
|
||||
_ct = ct;
|
||||
}
|
||||
|
||||
void EspalexaDevice::doCallback()
|
||||
{
|
||||
(_callback != nullptr) ? _callback(_val) : _callbackCol(_val, getColorRGB());
|
||||
}
|
46
wled00/src/dependencies/espalexa/EspalexaDevice.h
Normal file
46
wled00/src/dependencies/espalexa/EspalexaDevice.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef EspalexaDevice_h
|
||||
#define EspalexaDevice_h
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
typedef void (*CallbackBriFunction) (uint8_t br);
|
||||
typedef void (*CallbackColFunction) (uint8_t br, uint32_t col);
|
||||
|
||||
class EspalexaDevice {
|
||||
private:
|
||||
String _deviceName;
|
||||
CallbackBriFunction _callback;
|
||||
CallbackColFunction _callbackCol;
|
||||
uint8_t _val, _val_last, _sat = 0;
|
||||
uint16_t _hue = 0, _ct = 0;
|
||||
uint8_t _changed = 0;
|
||||
|
||||
public:
|
||||
EspalexaDevice();
|
||||
~EspalexaDevice();
|
||||
EspalexaDevice(String deviceName, CallbackBriFunction gnCallback, uint8_t initialValue =0);
|
||||
EspalexaDevice(String deviceName, CallbackColFunction gnCallback, uint8_t initialValue =0);
|
||||
|
||||
bool isColorDevice();
|
||||
bool isColorTemperatureMode();
|
||||
String getName();
|
||||
uint8_t getLastChangedProperty();
|
||||
uint8_t getValue();
|
||||
uint16_t getHue();
|
||||
uint8_t getSat();
|
||||
uint16_t getCt();
|
||||
uint32_t getColorRGB();
|
||||
|
||||
void setPropertyChanged(uint8_t p);
|
||||
void setValue(uint8_t bri);
|
||||
void setPercent(uint8_t perc);
|
||||
void setName(String name);
|
||||
void setColor(uint16_t hue, uint8_t sat);
|
||||
void setColor(uint16_t ct);
|
||||
|
||||
void doCallback();
|
||||
|
||||
uint8_t getLastValue(); //last value that was not off (1-255)
|
||||
};
|
||||
|
||||
#endif
|
21
wled00/src/dependencies/espalexa/LICENSE
Normal file
21
wled00/src/dependencies/espalexa/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Christian Schwinne
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@@ -16,7 +16,8 @@
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#include <Time.h> //http://www.arduino.cc/playground/Code/Time
|
||||
|
||||
#include "../time/Time.h" //http://www.arduino.cc/playground/Code/Time
|
||||
|
||||
//convenient constants for dstRules
|
||||
enum week_t {Last, First, Second, Third, Fourth};
|
||||
|
@@ -3,50 +3,83 @@
|
||||
*/
|
||||
/*
|
||||
* @title WLED project sketch
|
||||
* @version 0.8.0
|
||||
* @version 0.8.3
|
||||
* @author Christian Schwinne
|
||||
*/
|
||||
|
||||
//ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS).
|
||||
//Uncomment the following line to disable some features (currently Mobile UI, welcome page and single digit + cronixie overlays) to compile for ESP8266-01
|
||||
//#define WLED_FLASH_512K_MODE
|
||||
//CURRENTLY NOT WORKING
|
||||
|
||||
//ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS).
|
||||
|
||||
//ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS).
|
||||
//Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
|
||||
|
||||
//You are required to disable over-the-air updates:
|
||||
//#define WLED_DISABLE_OTA
|
||||
|
||||
//You need to choose 1-2 of these features to disable:
|
||||
//#define WLED_DISABLE_ALEXA
|
||||
//#define WLED_DISABLE_BLYNK
|
||||
//#define WLED_DISABLE_CRONIXIE
|
||||
//#define WLED_DISABLE_HUESYNC
|
||||
//#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01
|
||||
//#define WLED_DISABLE_MOBILE_UI
|
||||
|
||||
//to toggle usb serial debug (un)comment following line(s)
|
||||
//#define WLED_DEBUG
|
||||
|
||||
|
||||
//library inclusions
|
||||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "src/dependencies/webserver/WebServer.h"
|
||||
#include <HTTPClient.h>
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include "src/dependencies/webserver/WebServer.h"
|
||||
#include <HTTPClient.h>
|
||||
/*#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremote.h>
|
||||
#endif*/ //there are issues with ESP32 infrared, so it is disabled for now
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <EEPROM.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <WiFiUDP.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h"
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h"
|
||||
#endif
|
||||
#include "src/dependencies/time/Time.h"
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
#define ESPALEXA_MAXDEVICES 1
|
||||
#include "src/dependencies/espalexa/Espalexa.h"
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||
#endif
|
||||
#include "src/dependencies/e131/E131.h"
|
||||
#include "src/dependencies/pubsubclient/PubSubClient.h"
|
||||
#include "htmls00.h"
|
||||
#include "htmls01.h"
|
||||
#include "htmls02.h"
|
||||
#include "html_classic.h"
|
||||
#include "html_mobile.h"
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
#include "WS2812FX.h"
|
||||
#include "ir_codes.h"
|
||||
|
||||
|
||||
//version code in format yymmddb (b = daily build)
|
||||
#define VERSION 1810151
|
||||
char versionString[] = "0.8.0";
|
||||
#define VERSION 1902122
|
||||
char versionString[] = "0.8.3";
|
||||
|
||||
|
||||
//AP and OTA default passwords (for maximum change them!)
|
||||
@@ -54,18 +87,13 @@ char apPass[65] = "wled1234";
|
||||
char otaPass[33] = "wledota";
|
||||
|
||||
|
||||
//to toggle usb serial debug (un)comment following line(s)
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
//spiffs FS only useful for debug (only ESP8266)
|
||||
//#define USEFS
|
||||
|
||||
|
||||
//Hardware CONFIG (only changeble HERE, not at runtime)
|
||||
//LED strip pin changeable in NpbWrapper.h. Only change for ESP32
|
||||
byte buttonPin = 0; //needs pull-up
|
||||
byte auxPin = 15; //debug feature, use e.g. for external relay with API call AX=
|
||||
//LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
|
||||
|
||||
byte auxDefaultState = 0; //0: input 1: high 2: low
|
||||
byte auxTriggeredState = 0; //0: input 1: high 2: low
|
||||
char ntpServerName[] = "0.wled.pool.ntp.org"; //NTP server to use
|
||||
@@ -74,7 +102,7 @@ char ntpServerName[] = "0.wled.pool.ntp.org"; //NTP server to use
|
||||
//WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
||||
char clientSSID[33] = "Your_Network";
|
||||
char clientPass[65] = "";
|
||||
char cmDNS[33] = "led"; //mDNS address (x.local), only for Apple and Windows, if Bonjour installed
|
||||
char cmDNS[33] = "x"; //mDNS address (placeholder, will be replaced by wledXXXXXXXXXXXX.local)
|
||||
char apSSID[65] = ""; //AP off by default (unless setup)
|
||||
byte apChannel = 1; //2.4GHz WiFi AP channel (1-13)
|
||||
byte apHide = 0; //hidden AP SSID
|
||||
@@ -87,16 +115,15 @@ IPAddress staticDNS(8, 8, 8, 8); //only for NTP, google DNS server
|
||||
|
||||
|
||||
//LED CONFIG
|
||||
uint16_t ledCount = 10; //lowered to prevent accidental overcurrent
|
||||
uint16_t ledCount = 30; //overcurrent prevented by ABL
|
||||
bool useRGBW = false; //SK6812 strips can contain an extra White channel
|
||||
bool autoRGBtoRGBW = false; //if RGBW enabled, calculate White channel from RGB
|
||||
#define ABL_MILLIAMPS_DEFAULT 850; //auto lower brightness to stay close to milliampere limit
|
||||
bool turnOnAtBoot = true; //turn on LEDs at power-up
|
||||
byte bootPreset = 0; //save preset to load after power-up
|
||||
|
||||
byte colS[]{255, 159, 0}; //default RGB color
|
||||
byte colSecS[]{0, 0, 0}; //default RGB secondary color
|
||||
byte whiteS = 0; //default White channel
|
||||
byte whiteSecS = 0; //default secondary White channel
|
||||
byte colS[]{255, 159, 0, 0}; //default RGB(W) color
|
||||
byte colSecS[]{0, 0, 0, 0}; //default RGB(W) secondary color
|
||||
byte briS = 127; //default brightness
|
||||
byte effectDefault = 0;
|
||||
byte effectSpeedDefault = 75;
|
||||
@@ -114,7 +141,6 @@ bool enableSecTransition = true; //also enable transition for secon
|
||||
uint16_t transitionDelay = 900; //default crossfade duration in ms
|
||||
|
||||
bool reverseMode = false; //flip entire LED strip (reverses all effect directions)
|
||||
bool initLedsLast = false; //turn on LEDs only after WiFi connected/AP open
|
||||
bool skipFirstLed = false; //ignore first LED in strip (useful if you need the LED as signal repeater)
|
||||
byte briMultiplier = 100; //% of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
|
||||
|
||||
@@ -130,7 +156,8 @@ bool useHSBDefault = useHSB;
|
||||
|
||||
|
||||
//Sync CONFIG
|
||||
bool buttonEnabled = true;
|
||||
bool buttonEnabled = true;
|
||||
bool irEnabled = false; //Infrared receiver
|
||||
|
||||
uint16_t udpPort = 21324; //WLED notifier default port
|
||||
uint16_t udpRgbPort = 19446; //Hyperion port
|
||||
@@ -139,7 +166,7 @@ bool receiveNotificationBrightness = true; //apply brightness from incoming n
|
||||
bool receiveNotificationColor = true; //apply color
|
||||
bool receiveNotificationEffects = true; //apply effects setup
|
||||
bool notifyDirect = true; //send notification if change via UI or HTTP API
|
||||
bool notifyButton = true;
|
||||
bool notifyButton = true; //send if updated by button or infrared remote
|
||||
bool notifyAlexa = false; //send notification if updated via Alexa
|
||||
bool notifyMacro = false; //send notification for macro
|
||||
bool notifyHue = true; //send notification if Hue light changes
|
||||
@@ -216,16 +243,14 @@ uint16_t userVar0 = 0, userVar1 = 0;
|
||||
|
||||
//internal global variable declarations
|
||||
//color
|
||||
byte col[]{255, 159, 0}; //target RGB color
|
||||
byte colOld[]{0, 0, 0}; //color before transition
|
||||
byte colT[]{0, 0, 0}; //current color
|
||||
byte colIT[]{0, 0, 0}; //color that was last sent to LEDs
|
||||
byte colSec[]{0, 0, 0};
|
||||
byte colSecT[]{0, 0, 0};
|
||||
byte colSecOld[]{0, 0, 0};
|
||||
byte colSecIT[]{0, 0, 0};
|
||||
byte white = whiteS, whiteOld, whiteT, whiteIT;
|
||||
byte whiteSec = whiteSecS, whiteSecOld, whiteSecT, whiteSecIT;
|
||||
byte col[]{255, 159, 0, 0}; //target RGB(W) color
|
||||
byte colOld[]{0, 0, 0, 0}; //color before transition
|
||||
byte colT[]{0, 0, 0, 0}; //current color
|
||||
byte colIT[]{0, 0, 0, 0}; //color that was last sent to LEDs
|
||||
byte colSec[]{0, 0, 0, 0};
|
||||
byte colSecT[]{0, 0, 0, 0};
|
||||
byte colSecOld[]{0, 0, 0, 0};
|
||||
byte colSecIT[]{0, 0, 0, 0};
|
||||
|
||||
byte lastRandomIndex = 0; //used to save last random color so the new one is not the same
|
||||
|
||||
@@ -240,10 +265,13 @@ float tperLast = 0; //crossfade transition progress, 0
|
||||
bool nightlightActive = false;
|
||||
bool nightlightActiveOld = false;
|
||||
uint32_t nightlightDelayMs = 10;
|
||||
uint8_t nightlightDelayMinsDefault = nightlightDelayMins;
|
||||
unsigned long nightlightStartTime;
|
||||
byte briNlT = 0; //current nightlight brightness
|
||||
|
||||
//brightness
|
||||
bool offMode = false;
|
||||
unsigned long lastOnTime = 0;
|
||||
byte bri = briS;
|
||||
byte briOld = 0;
|
||||
byte briT = 0;
|
||||
@@ -273,7 +301,6 @@ bool udpConnected = false, udpRgbConnected = false;
|
||||
|
||||
//ui style
|
||||
char cssCol[6][9]={"","","","","",""};
|
||||
String cssColorString="";
|
||||
bool showWelcomePage = false;
|
||||
|
||||
//hue
|
||||
@@ -311,7 +338,7 @@ byte timerHours[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMinutes[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMacro[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerWeekday[] = {255,255,255,255,255,255,255,255}; //weekdays to activate on
|
||||
//bit pattern of arr elem: 0b11111111: sat,fri,thu,wed,tue,mon,sun,validity
|
||||
//bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
|
||||
|
||||
//blynk
|
||||
bool blynkEnabled = false;
|
||||
@@ -321,7 +348,7 @@ bool presetCyclingEnabled = false;
|
||||
byte presetCycleMin = 1, presetCycleMax = 5;
|
||||
uint16_t presetCycleTime = 1250;
|
||||
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
|
||||
bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true;
|
||||
bool presetApplyBri = false, presetApplyCol = true, presetApplyFx = true;
|
||||
bool saveCurrPresetCycConf = false;
|
||||
|
||||
//realtime
|
||||
@@ -342,10 +369,11 @@ unsigned long auxStartTime = 0;
|
||||
bool auxActive = false, auxActiveBefore = false;
|
||||
|
||||
//alexa udp
|
||||
WiFiUDP alexaUDP;
|
||||
IPAddress ipMulti(239, 255, 255, 250);
|
||||
unsigned int portMulti = 1900;
|
||||
String escapedMac;
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
Espalexa espalexa;
|
||||
EspalexaDevice* espalexaDevice;
|
||||
#endif
|
||||
|
||||
//dns server
|
||||
DNSServer dnsServer;
|
||||
@@ -361,21 +389,23 @@ unsigned int ntpLocalPort = 2390;
|
||||
#define NTP_PACKET_SIZE 48
|
||||
|
||||
//string temp buffer
|
||||
#define OMAX 1750
|
||||
#define OMAX 2000
|
||||
char obuf[OMAX];
|
||||
uint16_t olen = 0;
|
||||
|
||||
//server library objects
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WebServer server(80);
|
||||
WebServer server(80);
|
||||
#else
|
||||
ESP8266WebServer server(80);
|
||||
ESP8266WebServer server(80);
|
||||
#endif
|
||||
HTTPClient* hueClient = NULL;
|
||||
WiFiClient* mqttTCPClient = NULL;
|
||||
PubSubClient* mqtt = NULL;
|
||||
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
#endif
|
||||
|
||||
//udp interface objects
|
||||
WiFiUDP notifierUdp, rgbUdp;
|
||||
@@ -386,7 +416,7 @@ E131* e131;
|
||||
WS2812FX strip = WS2812FX();
|
||||
|
||||
//debug macros
|
||||
#ifdef DEBUG
|
||||
#ifdef WLED_DEBUG
|
||||
#define DEBUG_PRINT(x) Serial.print (x)
|
||||
#define DEBUG_PRINTLN(x) Serial.println (x)
|
||||
#define DEBUG_PRINTF(x) Serial.printf (x)
|
||||
@@ -401,8 +431,8 @@ WS2812FX strip = WS2812FX();
|
||||
|
||||
//filesystem
|
||||
#ifdef USEFS
|
||||
#include <FS.h>;
|
||||
File fsUploadFile;
|
||||
#include <FS.h>;
|
||||
File fsUploadFile;
|
||||
#endif
|
||||
|
||||
//gamma 2.4 lookup table used for color correction
|
||||
@@ -434,6 +464,7 @@ void serveMessage(int,String,String,int=255);
|
||||
void reset()
|
||||
{
|
||||
briT = 0;
|
||||
delay(250); //enough time to send response to client
|
||||
setAllLeds();
|
||||
DEBUG_PRINTLN("MODULE RESET");
|
||||
ESP.restart();
|
||||
@@ -462,64 +493,76 @@ bool oappendi(int i)
|
||||
|
||||
//boot starts here
|
||||
void setup() {
|
||||
wledInit();
|
||||
wledInit();
|
||||
}
|
||||
|
||||
|
||||
//main program loop
|
||||
void loop() {
|
||||
server.handleClient();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleButton();
|
||||
handleNetworkTime();
|
||||
if (!onlyAP)
|
||||
{
|
||||
handleAlexa();
|
||||
handleMQTT();
|
||||
}
|
||||
|
||||
handleOverlays();
|
||||
server.handleClient();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleButton();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
if (!onlyAP)
|
||||
{
|
||||
handleAlexa();
|
||||
handleMQTT();
|
||||
}
|
||||
|
||||
handleOverlays();
|
||||
|
||||
yield();
|
||||
|
||||
|
||||
if (!realtimeActive) //block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (dnsActive) dnsServer.processNextRequest();
|
||||
if (aOtaEnabled) ArduinoOTA.handle();
|
||||
handleNightlight();
|
||||
if (!onlyAP) {
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
}
|
||||
if (briT) strip.service(); //do not update strip if off, prevents flicker on ESP32
|
||||
}
|
||||
|
||||
//DEBUG serial logging
|
||||
#ifdef DEBUG
|
||||
if (millis() - debugTime > 5000)
|
||||
{
|
||||
DEBUG_PRINTLN("---MODULE DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("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(WiFi.localIP());
|
||||
debugTime = millis();
|
||||
}
|
||||
yield();
|
||||
|
||||
if (!realtimeActive) //block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (dnsActive) dnsServer.processNextRequest();
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) ArduinoOTA.handle();
|
||||
#endif
|
||||
handleNightlight();
|
||||
if (!onlyAP) {
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
}
|
||||
if (briT) lastOnTime = millis();
|
||||
if (millis() - lastOnTime < 600)
|
||||
{
|
||||
offMode = false;
|
||||
strip.service();
|
||||
} else if (!offMode)
|
||||
{
|
||||
/*#if LEDPIN == 2 //turn off onboard LED
|
||||
pinMode(2, OUTPUT);
|
||||
digitalWrite(2, HIGH);
|
||||
#endif*/
|
||||
offMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
//DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 5000)
|
||||
{
|
||||
DEBUG_PRINTLN("---MODULE DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("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(WiFi.localIP());
|
||||
debugTime = millis();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#define EEPSIZE 3072
|
||||
|
||||
//eeprom Version code, enables default settings instead of 0 init on update
|
||||
#define EEPVER 9
|
||||
#define EEPVER 10
|
||||
//0 -> old version, default
|
||||
//1 -> 0.4p 1711272 and up
|
||||
//2 -> 0.4p 1711302 and up
|
||||
@@ -17,6 +17,8 @@
|
||||
//7 -> 0.7.1 and up
|
||||
//8 -> 0.8.0-a and up
|
||||
//9 -> 0.8.0
|
||||
//10-> 0.8.2
|
||||
|
||||
|
||||
/*
|
||||
* Erase all configuration data
|
||||
@@ -30,6 +32,7 @@ void clearEEPROM()
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
|
||||
void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i)
|
||||
@@ -39,6 +42,7 @@ void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i)
|
||||
@@ -49,6 +53,7 @@ void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||
str[len] = 0; //make sure every string is properly terminated. str must be at least len +1 big.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write configuration to flash
|
||||
*/
|
||||
@@ -66,12 +71,12 @@ void saveSettingsToEEPROM()
|
||||
writeStringToEEPROM(128, apSSID, 32);
|
||||
writeStringToEEPROM(160, apPass, 64);
|
||||
|
||||
EEPROM.write(224, nightlightDelayMins);
|
||||
EEPROM.write(224, nightlightDelayMinsDefault);
|
||||
EEPROM.write(225, nightlightFade);
|
||||
EEPROM.write(226, notifyDirectDefault);
|
||||
EEPROM.write(227, apChannel);
|
||||
EEPROM.write(228, apHide);
|
||||
EEPROM.write(229, (ledCount >> 0) & 0xFF);
|
||||
EEPROM.write(229, ledCount & 0xFF);
|
||||
EEPROM.write(230, notifyButton);
|
||||
EEPROM.write(231, notifyTwice);
|
||||
EEPROM.write(232, buttonEnabled);
|
||||
@@ -92,7 +97,7 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(250, receiveNotificationBrightness);
|
||||
EEPROM.write(251, fadeTransition);
|
||||
EEPROM.write(252, reverseMode);
|
||||
EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF);
|
||||
EEPROM.write(253, transitionDelayDefault & 0xFF);
|
||||
EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF);
|
||||
EEPROM.write(255, briMultiplier);
|
||||
|
||||
@@ -101,7 +106,7 @@ void saveSettingsToEEPROM()
|
||||
|
||||
EEPROM.write(288, nightlightTargetBri);
|
||||
EEPROM.write(289, otaLock);
|
||||
EEPROM.write(290, (udpPort >> 0) & 0xFF);
|
||||
EEPROM.write(290, udpPort & 0xFF);
|
||||
EEPROM.write(291, (udpPort >> 8) & 0xFF);
|
||||
writeStringToEEPROM(292, serverDescription, 32);
|
||||
|
||||
@@ -124,7 +129,7 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(368, abs(arlsOffset));
|
||||
EEPROM.write(369, turnOnAtBoot);
|
||||
EEPROM.write(370, useHSBDefault);
|
||||
EEPROM.write(371, whiteS);
|
||||
EEPROM.write(371, colS[3]); //white default
|
||||
EEPROM.write(372, useRGBW);
|
||||
EEPROM.write(373, effectPaletteDefault);
|
||||
EEPROM.write(374, strip.paletteFade);
|
||||
@@ -136,19 +141,24 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(378, colSecS[0]);
|
||||
EEPROM.write(379, colSecS[1]);
|
||||
EEPROM.write(380, colSecS[2]);
|
||||
EEPROM.write(381, whiteSecS);
|
||||
EEPROM.write(381, colSecS[3]);
|
||||
EEPROM.write(382, strip.paletteBlend);
|
||||
|
||||
EEPROM.write(383, strip.colorOrder);
|
||||
|
||||
EEPROM.write(385, irEnabled);
|
||||
|
||||
EEPROM.write(387, strip.ablMilliampsMax & 0xFF);
|
||||
EEPROM.write(388, (strip.ablMilliampsMax >> 8) & 0xFF);
|
||||
EEPROM.write(389, bootPreset);
|
||||
EEPROM.write(390, aOtaEnabled);
|
||||
EEPROM.write(391, receiveNotificationColor);
|
||||
EEPROM.write(392, receiveNotificationEffects);
|
||||
EEPROM.write(393, wifiLock);
|
||||
|
||||
EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF);
|
||||
EEPROM.write(394, abs(utcOffsetSecs) & 0xFF);
|
||||
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
|
||||
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
|
||||
EEPROM.write(397, initLedsLast);
|
||||
//397 was initLedsLast
|
||||
EEPROM.write(398, (ledCount >> 8) & 0xFF);
|
||||
EEPROM.write(399, !enableSecTransition);
|
||||
|
||||
@@ -170,7 +180,7 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(i, hueIP[i-2050]);
|
||||
}
|
||||
writeStringToEEPROM(2054, hueApiKey, 46);
|
||||
EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF);
|
||||
EEPROM.write(2100, huePollIntervalMs & 0xFF);
|
||||
EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF);
|
||||
EEPROM.write(2102, notifyHue);
|
||||
EEPROM.write(2103, hueApplyOnOff);
|
||||
@@ -205,10 +215,10 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(2180, macroCountdown);
|
||||
EEPROM.write(2181, macroNl);
|
||||
|
||||
EEPROM.write(2190, (e131Universe >> 0) & 0xFF);
|
||||
EEPROM.write(2190, e131Universe & 0xFF);
|
||||
EEPROM.write(2191, (e131Universe >> 8) & 0xFF);
|
||||
EEPROM.write(2192, e131Multicast);
|
||||
EEPROM.write(2193, (realtimeTimeoutMs >> 0) & 0xFF);
|
||||
EEPROM.write(2193, realtimeTimeoutMs & 0xFF);
|
||||
EEPROM.write(2194, (realtimeTimeoutMs >> 8) & 0xFF);
|
||||
EEPROM.write(2195, arlsForceMaxBri);
|
||||
EEPROM.write(2196, arlsDisableGammaCorrection);
|
||||
@@ -222,7 +232,7 @@ void saveSettingsToEEPROM()
|
||||
if (saveCurrPresetCycConf)
|
||||
{
|
||||
EEPROM.write(2205, presetCyclingEnabled);
|
||||
EEPROM.write(2206, (presetCycleTime >> 0) & 0xFF);
|
||||
EEPROM.write(2206, presetCycleTime & 0xFF);
|
||||
EEPROM.write(2207, (presetCycleTime >> 8) & 0xFF);
|
||||
EEPROM.write(2208, presetCycleMin);
|
||||
EEPROM.write(2209, presetCycleMax);
|
||||
@@ -246,9 +256,10 @@ void saveSettingsToEEPROM()
|
||||
writeStringToEEPROM(2333, mqttDeviceTopic, 32);
|
||||
writeStringToEEPROM(2366, mqttGroupTopic, 32);
|
||||
|
||||
EEPROM.commit();
|
||||
commit();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read all configuration from flash
|
||||
*/
|
||||
@@ -256,7 +267,9 @@ void loadSettingsFromEEPROM(bool first)
|
||||
{
|
||||
if (EEPROM.read(233) != 233) //first boot/reset to default
|
||||
{
|
||||
DEBUG_PRINT("Settings invalid, restoring defaults...");
|
||||
saveSettingsToEEPROM();
|
||||
DEBUG_PRINTLN("done");
|
||||
return;
|
||||
}
|
||||
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
|
||||
@@ -268,7 +281,8 @@ void loadSettingsFromEEPROM(bool first)
|
||||
readStringFromEEPROM(128, apSSID, 32);
|
||||
readStringFromEEPROM(160, apPass, 64);
|
||||
|
||||
nightlightDelayMins = EEPROM.read(224);
|
||||
nightlightDelayMinsDefault = EEPROM.read(224);
|
||||
nightlightDelayMins = nightlightDelayMinsDefault;
|
||||
nightlightFade = EEPROM.read(225);
|
||||
notifyDirectDefault = EEPROM.read(226);
|
||||
notifyDirect = notifyDirectDefault;
|
||||
@@ -277,7 +291,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
if (apChannel > 13 || apChannel < 1) apChannel = 1;
|
||||
apHide = EEPROM.read(228);
|
||||
if (apHide > 1) apHide = 1;
|
||||
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
|
||||
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 30;
|
||||
|
||||
notifyButton = EEPROM.read(230);
|
||||
notifyTwice = EEPROM.read(231);
|
||||
@@ -307,7 +321,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
receiveNotificationBrightness = EEPROM.read(250);
|
||||
fadeTransition = EEPROM.read(251);
|
||||
reverseMode = EEPROM.read(252);
|
||||
transitionDelayDefault = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
|
||||
transitionDelayDefault = EEPROM.read(253) + ((EEPROM.read(254) << 8) & 0xFF00);
|
||||
transitionDelay = transitionDelayDefault;
|
||||
briMultiplier = EEPROM.read(255);
|
||||
|
||||
@@ -315,7 +329,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
|
||||
nightlightTargetBri = EEPROM.read(288);
|
||||
otaLock = EEPROM.read(289);
|
||||
udpPort = ((EEPROM.read(290) << 0) & 0xFF) + ((EEPROM.read(291) << 8) & 0xFF00);
|
||||
udpPort = EEPROM.read(290) + ((EEPROM.read(291) << 8) & 0xFF00);
|
||||
|
||||
readStringFromEEPROM(292, serverDescription, 32);
|
||||
|
||||
@@ -338,7 +352,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
if (!EEPROM.read(367)) arlsOffset = -arlsOffset;
|
||||
turnOnAtBoot = EEPROM.read(369);
|
||||
useHSBDefault = EEPROM.read(370);
|
||||
whiteS = EEPROM.read(371); white = whiteS;
|
||||
colS[3] = EEPROM.read(371); col[3] = colS[3];
|
||||
useRGBW = EEPROM.read(372);
|
||||
effectPaletteDefault = EEPROM.read(373); effectPalette = effectPaletteDefault;
|
||||
//374 - strip.paletteFade
|
||||
@@ -349,10 +363,10 @@ void loadSettingsFromEEPROM(bool first)
|
||||
}
|
||||
//377 = lastEEPROMversion
|
||||
if (lastEEPROMversion > 1) {
|
||||
colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0];
|
||||
colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1];
|
||||
colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2];
|
||||
whiteSecS = EEPROM.read(381); whiteSec = whiteSecS;
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colSecS[i] = EEPROM.read(378+i); colSec[i] = colSecS[i];
|
||||
}
|
||||
}
|
||||
if (lastEEPROMversion > 3) {
|
||||
effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault;
|
||||
@@ -377,7 +391,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
|
||||
readStringFromEEPROM(2054, hueApiKey, 46);
|
||||
|
||||
huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00);
|
||||
huePollIntervalMs = EEPROM.read(2100) + ((EEPROM.read(2101) << 8) & 0xFF00);
|
||||
notifyHue = EEPROM.read(2102);
|
||||
hueApplyOnOff = EEPROM.read(2103);
|
||||
hueApplyBri = EEPROM.read(2104);
|
||||
@@ -413,9 +427,9 @@ void loadSettingsFromEEPROM(bool first)
|
||||
|
||||
if (lastEEPROMversion > 6)
|
||||
{
|
||||
e131Universe = ((EEPROM.read(2190) << 0) & 0xFF) + ((EEPROM.read(2191) << 8) & 0xFF00);
|
||||
e131Universe = EEPROM.read(2190) + ((EEPROM.read(2191) << 8) & 0xFF00);
|
||||
e131Multicast = EEPROM.read(2192);
|
||||
realtimeTimeoutMs = ((EEPROM.read(2193) << 0) & 0xFF) + ((EEPROM.read(2194) << 8) & 0xFF00);
|
||||
realtimeTimeoutMs = EEPROM.read(2193) + ((EEPROM.read(2194) << 8) & 0xFF00);
|
||||
arlsForceMaxBri = EEPROM.read(2195);
|
||||
arlsDisableGammaCorrection = EEPROM.read(2196);
|
||||
}
|
||||
@@ -430,8 +444,8 @@ void loadSettingsFromEEPROM(bool first)
|
||||
timerHours[i] = EEPROM.read(2260 + i);
|
||||
timerMinutes[i] = EEPROM.read(2270 + i);
|
||||
timerWeekday[i] = EEPROM.read(2280 + i);
|
||||
timerMacro[i] = EEPROM.read(2290 + i);
|
||||
if (timerWeekday[i] == 0) timerWeekday[i] = 255;
|
||||
timerMacro[i] = EEPROM.read(2290 + i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,12 +455,24 @@ void loadSettingsFromEEPROM(bool first)
|
||||
readStringFromEEPROM(2333, mqttDeviceTopic, 32);
|
||||
readStringFromEEPROM(2366, mqttGroupTopic, 32);
|
||||
}
|
||||
|
||||
if (lastEEPROMversion > 9)
|
||||
{
|
||||
strip.colorOrder = 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
|
||||
{
|
||||
strip.ablMilliampsMax = 65000;
|
||||
} else {
|
||||
strip.ablMilliampsMax = ABL_MILLIAMPS_DEFAULT;
|
||||
}
|
||||
|
||||
receiveDirect = !EEPROM.read(2200);
|
||||
enableRealtimeUI = EEPROM.read(2201);
|
||||
uiConfiguration = EEPROM.read(2202);
|
||||
|
||||
#ifdef WLED_FLASH_512K_MODE
|
||||
#ifdef WLED_DISABLE_MOBILE_UI
|
||||
uiConfiguration = 1;
|
||||
//force default UI since mobile is unavailable
|
||||
#endif
|
||||
@@ -457,7 +483,7 @@ void loadSettingsFromEEPROM(bool first)
|
||||
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
|
||||
{
|
||||
presetCyclingEnabled = EEPROM.read(2205);
|
||||
presetCycleTime = ((EEPROM.read(2206) << 0) & 0xFF) + ((EEPROM.read(2207) << 8) & 0xFF00);
|
||||
presetCycleTime = EEPROM.read(2206) + ((EEPROM.read(2207) << 8) & 0xFF00);
|
||||
presetCycleMin = EEPROM.read(2208);
|
||||
presetCycleMax = EEPROM.read(2209);
|
||||
presetApplyBri = EEPROM.read(2210);
|
||||
@@ -467,9 +493,8 @@ void loadSettingsFromEEPROM(bool first)
|
||||
|
||||
bootPreset = EEPROM.read(389);
|
||||
wifiLock = EEPROM.read(393);
|
||||
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
|
||||
utcOffsetSecs = EEPROM.read(394) + ((EEPROM.read(395) << 8) & 0xFF00);
|
||||
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
|
||||
initLedsLast = EEPROM.read(397);
|
||||
enableSecTransition = !EEPROM.read(399);
|
||||
|
||||
//favorite setting (preset) memory (25 slots/ each 20byte)
|
||||
@@ -491,47 +516,41 @@ void loadSettingsFromEEPROM(bool first)
|
||||
|
||||
useHSB = useHSBDefault;
|
||||
|
||||
strip.setMode(effectCurrent);
|
||||
strip.setSpeed(effectSpeed);
|
||||
strip.setIntensity(effectIntensity);
|
||||
strip.setPalette(effectPalette);
|
||||
overlayCurrent = overlayDefault;
|
||||
}
|
||||
|
||||
|
||||
//PRESET PROTOCOL 20 bytes
|
||||
//0: preset purpose byte 0:invalid 1:valid preset 1.0
|
||||
//1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17: fp 18-19:Zeros
|
||||
|
||||
void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
|
||||
bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool loadFX = true)
|
||||
{
|
||||
if (index == 255 || index == 0) loadSettingsFromEEPROM(false);//load boot defaults
|
||||
if (index > 25 || index < 1) return;
|
||||
if (index == 255 || index == 0)
|
||||
{
|
||||
loadSettingsFromEEPROM(false);//load boot defaults
|
||||
return true;
|
||||
}
|
||||
if (index > 25 || index < 1) return false;
|
||||
uint16_t i = 380 + index*20;
|
||||
if (EEPROM.read(i) == 0) return;
|
||||
if (EEPROM.read(i) == 0) return false;
|
||||
if (loadBri) bri = EEPROM.read(i+1);
|
||||
if (loadCol)
|
||||
{
|
||||
col[0] = EEPROM.read(i+2);
|
||||
col[1] = EEPROM.read(i+3);
|
||||
col[2] = EEPROM.read(i+4);
|
||||
white = EEPROM.read(i+5);
|
||||
colSec[0] = EEPROM.read(i+6);
|
||||
colSec[1] = EEPROM.read(i+7);
|
||||
colSec[2] = EEPROM.read(i+8);
|
||||
whiteSec = EEPROM.read(i+9);
|
||||
for (byte j=0; j<4; j++)
|
||||
{
|
||||
col[j] = EEPROM.read(i+j+2);
|
||||
colSec[j] = EEPROM.read(i+j+6);
|
||||
}
|
||||
}
|
||||
if (loadFX)
|
||||
{
|
||||
byte lastfx = effectCurrent;
|
||||
effectCurrent = EEPROM.read(i+10);
|
||||
effectSpeed = EEPROM.read(i+11);
|
||||
effectIntensity = EEPROM.read(i+16);
|
||||
effectPalette = EEPROM.read(i+17);
|
||||
if (lastfx != effectCurrent) strip.setMode(effectCurrent);
|
||||
strip.setSpeed(effectSpeed);
|
||||
strip.setIntensity(effectIntensity);
|
||||
strip.setPalette(effectPalette);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void savePreset(byte index)
|
||||
@@ -541,22 +560,20 @@ void savePreset(byte index)
|
||||
uint16_t i = 380 + index*20;//min400
|
||||
EEPROM.write(i, 1);
|
||||
EEPROM.write(i+1, bri);
|
||||
EEPROM.write(i+2, col[0]);
|
||||
EEPROM.write(i+3, col[1]);
|
||||
EEPROM.write(i+4, col[2]);
|
||||
EEPROM.write(i+5, white);
|
||||
EEPROM.write(i+6, colSec[0]);
|
||||
EEPROM.write(i+7, colSec[1]);
|
||||
EEPROM.write(i+8, colSec[2]);
|
||||
EEPROM.write(i+9, whiteSec);
|
||||
for (uint16_t j=0; j<4; j++)
|
||||
{
|
||||
EEPROM.write(i+j+2, col[j]);
|
||||
EEPROM.write(i+j+6, colSec[j]);
|
||||
}
|
||||
EEPROM.write(i+10, effectCurrent);
|
||||
EEPROM.write(i+11, effectSpeed);
|
||||
|
||||
EEPROM.write(i+16, effectIntensity);
|
||||
EEPROM.write(i+17, effectPalette);
|
||||
EEPROM.commit();
|
||||
commit();
|
||||
}
|
||||
|
||||
|
||||
String loadMacro(byte index)
|
||||
{
|
||||
index-=1;
|
||||
@@ -567,10 +584,10 @@ String loadMacro(byte index)
|
||||
if (EEPROM.read(i) == 0) break;
|
||||
m += char(EEPROM.read(i));
|
||||
}
|
||||
if (m.charAt(0) < 65 || m.charAt(0) > 90) return ""; //do simple check if macro is valid (capital first letter)
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
void applyMacro(byte index)
|
||||
{
|
||||
index-=1;
|
||||
@@ -589,6 +606,7 @@ void applyMacro(byte index)
|
||||
handleSet(mc);
|
||||
}
|
||||
|
||||
|
||||
void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings
|
||||
{
|
||||
index-=1;
|
||||
@@ -598,6 +616,23 @@ void saveMacro(byte index, String mc, bool sing=true) //only commit on single sa
|
||||
{
|
||||
EEPROM.write(i, mc.charAt(i-s));
|
||||
}
|
||||
if (sing) EEPROM.commit();
|
||||
if (sing) commit();
|
||||
}
|
||||
|
||||
|
||||
void commit()
|
||||
{
|
||||
DEBUG_PRINT("s");
|
||||
//this is to support IR on ESP32, needs work
|
||||
/*#ifdef ARDUINO_ARCH_ESP32
|
||||
portMUX_TYPE mMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL(&mMux);
|
||||
#endif*/
|
||||
|
||||
EEPROM.commit();
|
||||
|
||||
/*#ifdef ARDUINO_ARCH_ESP32
|
||||
portEXIT_CRITICAL(&mMux);
|
||||
#endif*/
|
||||
DEBUG_PRINT(".");
|
||||
}
|
||||
|
@@ -2,60 +2,88 @@
|
||||
* Sending XML status files to client
|
||||
*/
|
||||
|
||||
void XML_response(bool isHTTP)
|
||||
//build XML response to HTTP /win API request
|
||||
void XML_response(bool isHTTP, bool includeTheme)
|
||||
{
|
||||
olen = 0;
|
||||
oappend("<?xml version = \"1.0\" ?><vs><ac>");
|
||||
if (nightlightActive && nightlightFade)
|
||||
{
|
||||
oappendi(briT);
|
||||
} else
|
||||
{
|
||||
oappendi(bri);
|
||||
}
|
||||
oappend("</ac>");
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
oappend("<cl>");
|
||||
oappendi(col[i]);
|
||||
oappend("</cl>");
|
||||
}
|
||||
oappend("<ns>");
|
||||
oappendi(notifyDirect);
|
||||
oappend("</ns><nr>");
|
||||
oappendi(receiveNotifications);
|
||||
oappend("</nr><nl>");
|
||||
oappendi(nightlightActive);
|
||||
oappend("</nl><nf>");
|
||||
oappendi(nightlightFade);
|
||||
oappend("</nf><nd>");
|
||||
oappendi(nightlightDelayMins);
|
||||
oappend("</nd><nt>");
|
||||
oappendi(nightlightTargetBri);
|
||||
oappend("</nt><fx>");
|
||||
oappendi(effectCurrent);
|
||||
oappend("</fx><sx>");
|
||||
oappendi(effectSpeed);
|
||||
oappend("</sx><ix>");
|
||||
oappendi(effectIntensity);
|
||||
oappend("</ix><fp>");
|
||||
oappendi(effectPalette);
|
||||
oappend("</fp><wv>");
|
||||
if (useRGBW && !autoRGBtoRGBW) {
|
||||
oappendi(white);
|
||||
} else {
|
||||
oappend("-1");
|
||||
}
|
||||
oappend("</wv><md>");
|
||||
oappendi(useHSB);
|
||||
oappend("</md><ds>");
|
||||
oappend(serverDescription);
|
||||
oappend("</ds></vs>");
|
||||
if (isHTTP) server.send(200, "text/xml", obuf);
|
||||
olen = 0;
|
||||
oappend("<?xml version = \"1.0\" ?><vs><ac>");
|
||||
oappendi((nightlightActive && nightlightFade) ? briT : bri);
|
||||
oappend("</ac>");
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
oappend("<cl>");
|
||||
oappendi(col[i]);
|
||||
oappend("</cl>");
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
oappend("<cs>");
|
||||
oappendi(colSec[i]);
|
||||
oappend("</cs>");
|
||||
}
|
||||
|
||||
oappend("<ns>");
|
||||
oappendi(notifyDirect);
|
||||
oappend("</ns><nr>");
|
||||
oappendi(receiveNotifications);
|
||||
oappend("</nr><nl>");
|
||||
oappendi(nightlightActive);
|
||||
oappend("</nl><nf>");
|
||||
oappendi(nightlightFade);
|
||||
oappend("</nf><nd>");
|
||||
oappendi(nightlightDelayMins);
|
||||
oappend("</nd><nt>");
|
||||
oappendi(nightlightTargetBri);
|
||||
oappend("</nt><fx>");
|
||||
oappendi(effectCurrent);
|
||||
oappend("</fx><sx>");
|
||||
oappendi(effectSpeed);
|
||||
oappend("</sx><ix>");
|
||||
oappendi(effectIntensity);
|
||||
oappend("</ix><fp>");
|
||||
oappendi(effectPalette);
|
||||
oappend("</fp><wv>");
|
||||
if (useRGBW && !autoRGBtoRGBW) {
|
||||
oappendi(col[3]);
|
||||
} else {
|
||||
oappend("-1");
|
||||
}
|
||||
oappend("</wv><ws>");
|
||||
oappendi(colSec[3]);
|
||||
oappend("</ws><md>");
|
||||
oappendi(useHSB);
|
||||
oappend("</md><cy>");
|
||||
oappendi(presetCyclingEnabled);
|
||||
oappend("</cy><ds>");
|
||||
oappend(serverDescription);
|
||||
oappend("</ds>");
|
||||
if (includeTheme)
|
||||
{
|
||||
char cs[6][9];
|
||||
getThemeColors(cs);
|
||||
oappend("<th><ca>#");
|
||||
oappend(cs[0]);
|
||||
oappend("</ca><cb>#");
|
||||
oappend(cs[1]);
|
||||
oappend("</cb><cc>#");
|
||||
oappend(cs[2]);
|
||||
oappend("</cc><cd>#");
|
||||
oappend(cs[3]);
|
||||
oappend("</cd><cu>#");
|
||||
oappend(cs[4]);
|
||||
oappend("</cu><ct>#");
|
||||
oappend(cs[5]);
|
||||
oappend("</ct><cf>");
|
||||
oappend(cssFont);
|
||||
oappend("</cf></th>");
|
||||
}
|
||||
oappend("</vs>");
|
||||
if (isHTTP) server.send(200, "text/xml", obuf);
|
||||
}
|
||||
|
||||
void sappend(char stype, char* key, int val) //append a setting to string buffer
|
||||
//append a numeric setting to string buffer
|
||||
void sappend(char stype, char* key, int val)
|
||||
{
|
||||
char ds[] = "d.Sf.";
|
||||
|
||||
@@ -85,28 +113,30 @@ void sappend(char stype, char* key, int val) //append a setting to string buffer
|
||||
}
|
||||
}
|
||||
|
||||
void sappends(char stype, char* key, char* val) //append a string setting
|
||||
//append a string setting to buffer
|
||||
void sappends(char stype, char* key, char* val)
|
||||
{
|
||||
switch(stype)
|
||||
{
|
||||
case 's': //string (we can interpret val as char*)
|
||||
oappend("d.Sf.");
|
||||
oappend(key);
|
||||
oappend(".value=\"");
|
||||
oappend(val);
|
||||
oappend("\";");
|
||||
break;
|
||||
oappend("d.Sf.");
|
||||
oappend(key);
|
||||
oappend(".value=\"");
|
||||
oappend(val);
|
||||
oappend("\";");
|
||||
break;
|
||||
case 'm': //message
|
||||
oappend("d.getElementsByClassName");
|
||||
oappend(key);
|
||||
oappend(".innerHTML=\"");
|
||||
oappend(val);
|
||||
oappend("\";");
|
||||
break;
|
||||
oappend("d.getElementsByClassName");
|
||||
oappend(key);
|
||||
oappend(".innerHTML=\"");
|
||||
oappend(val);
|
||||
oappend("\";");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
//get values for settings form in javascript
|
||||
void getSettingsJS(byte subPage)
|
||||
{
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
|
||||
DEBUG_PRINT("settings resp");
|
||||
@@ -171,17 +201,26 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
|
||||
if (subPage == 2) {
|
||||
sappend('v',"LC",ledCount);
|
||||
sappend('v',"MA",strip.ablMilliampsMax);
|
||||
if (strip.currentMilliamps)
|
||||
{
|
||||
sappends('m',"(\"pow\")[0]","");
|
||||
olen -= 2; //delete ";
|
||||
oappendi(strip.currentMilliamps);
|
||||
oappend("mA\";");
|
||||
}
|
||||
sappend('v',"CR",colS[0]);
|
||||
sappend('v',"CG",colS[1]);
|
||||
sappend('v',"CB",colS[2]);
|
||||
sappend('v',"CA",briS);
|
||||
sappend('c',"EW",useRGBW);
|
||||
sappend('i',"CO",strip.colorOrder);
|
||||
sappend('c',"AW",autoRGBtoRGBW);
|
||||
sappend('v',"CW",whiteS);
|
||||
sappend('v',"CW",colS[3]);
|
||||
sappend('v',"SR",colSecS[0]);
|
||||
sappend('v',"SG",colSecS[1]);
|
||||
sappend('v',"SB",colSecS[2]);
|
||||
sappend('v',"SW",whiteSecS);
|
||||
sappend('v',"SW",colSecS[3]);
|
||||
sappend('c',"BO",turnOnAtBoot);
|
||||
sappend('v',"BP",bootPreset);
|
||||
sappend('v',"FX",effectDefault);
|
||||
@@ -196,11 +235,10 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
sappend('c',"T2",enableSecTransition);
|
||||
sappend('v',"BF",briMultiplier);
|
||||
sappend('v',"TB",nightlightTargetBri);
|
||||
sappend('v',"TL",nightlightDelayMins);
|
||||
sappend('v',"TL",nightlightDelayMinsDefault);
|
||||
sappend('c',"TW",nightlightFade);
|
||||
sappend('i',"PB",strip.paletteBlend);
|
||||
sappend('c',"RV",reverseMode);
|
||||
sappend('c',"EI",initLedsLast);
|
||||
sappend('c',"SL",skipFirstLed);
|
||||
}
|
||||
|
||||
@@ -222,6 +260,7 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
if (subPage == 4)
|
||||
{
|
||||
sappend('c',"BT",buttonEnabled);
|
||||
sappend('c',"IR",irEnabled);
|
||||
sappend('v',"UP",udpPort);
|
||||
sappend('c',"RB",receiveNotificationBrightness);
|
||||
sappend('c',"RC",receiveNotificationColor);
|
||||
@@ -303,6 +342,7 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
k[0] = 'H'; sappend('v',k,timerHours[i]);
|
||||
k[0] = 'N'; sappend('v',k,timerMinutes[i]);
|
||||
k[0] = 'T'; sappend('v',k,timerMacro[i]);
|
||||
k[0] = 'W'; sappend('v',k,timerWeekday[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,3 +361,29 @@ void getSettingsJS(byte subPage) //get values for settings form in javascript
|
||||
}
|
||||
oappend("}</script>");
|
||||
}
|
||||
|
||||
|
||||
//get colors from current theme as c strings
|
||||
void getThemeColors(char o[][9])
|
||||
{
|
||||
switch (currentTheme)
|
||||
{
|
||||
// accent color (aCol) background (bCol) panel (cCol) controls (dCol) shadows (sCol) text (tCol)
|
||||
default: strcpy(o[0], "D9B310"); strcpy(o[1], "0B3C5D"); strcpy(o[2], "1D2731"); strcpy(o[3], "328CC1"); strcpy(o[4], "000"); strcpy(o[5], "328CC1"); break; //night
|
||||
case 1: strcpy(o[0], "eee"); strcpy(o[1], "ddd"); strcpy(o[2], "b9b9b9"); strcpy(o[3], "049"); strcpy(o[4], "777"); strcpy(o[5], "049"); break; //modern
|
||||
case 2: strcpy(o[0], "abb"); strcpy(o[1], "fff"); strcpy(o[2], "ddd"); strcpy(o[3], "000"); strcpy(o[4], "0004"); strcpy(o[5], "000"); break; //bright
|
||||
case 3: strcpy(o[0], "c09f80"); strcpy(o[1], "d7cec7"); strcpy(o[2], "76323f"); strcpy(o[3], "888"); strcpy(o[4], "3334"); strcpy(o[5], "888"); break; //wine
|
||||
case 4: strcpy(o[0], "3cc47c"); strcpy(o[1], "828081"); strcpy(o[2], "d9a803"); strcpy(o[3], "1e392a"); strcpy(o[4], "000a"); strcpy(o[5], "1e392a"); break; //electric
|
||||
case 5: strcpy(o[0], "57bc90"); strcpy(o[1], "a5a5af"); strcpy(o[2], "015249"); strcpy(o[3], "88c9d4"); strcpy(o[4], "0004"); strcpy(o[5], "88c9d4"); break; //mint
|
||||
case 6: strcpy(o[0], "f7c331"); strcpy(o[1], "dca"); strcpy(o[2], "6b7a8f"); strcpy(o[3], "f7882f"); strcpy(o[4], "0007"); strcpy(o[5], "f7882f"); break; //amber
|
||||
case 7: strcpy(o[0], "fff"); strcpy(o[1], "333"); strcpy(o[2], "222"); strcpy(o[3], "666"); strcpy(o[4], ""); strcpy(o[5], "fff"); break; //dark
|
||||
case 8: strcpy(o[0], "0ac"); strcpy(o[1], "124"); strcpy(o[2], "224"); strcpy(o[3], "003eff"); strcpy(o[4], "003eff"); strcpy(o[5], "003eff"); break; //air
|
||||
case 9: strcpy(o[0], "f70"); strcpy(o[1], "421"); strcpy(o[2], "221"); strcpy(o[3], "a50"); strcpy(o[4], "f70"); strcpy(o[5], "f70"); break; //nixie
|
||||
case 10: strcpy(o[0], "2d2"); strcpy(o[1], "010"); strcpy(o[2], "121"); strcpy(o[3], "060"); strcpy(o[4], "040"); strcpy(o[5], "3f3"); break; //terminal
|
||||
case 11: strcpy(o[0], "867ADE"); strcpy(o[1], "4033A3"); strcpy(o[2], "483AAA"); strcpy(o[3], "483AAA"); strcpy(o[4], ""); strcpy(o[5], "867ADE"); break; //c64
|
||||
case 12: strcpy(o[0], "fbe8a6"); strcpy(o[1], "d2fdff"); strcpy(o[2], "b4dfe5"); strcpy(o[3], "f4976c"); strcpy(o[4], ""); strcpy(o[5], "303c6c"); break; //easter
|
||||
case 13: strcpy(o[0], "d4af37"); strcpy(o[1], "173305"); strcpy(o[2], "308505"); strcpy(o[3], "f21313"); strcpy(o[4], "f002"); strcpy(o[5], "d4af37"); break; //christmas
|
||||
case 14: strcpy(o[0], "fc7"); strcpy(o[1], "49274a"); strcpy(o[2], "94618e"); strcpy(o[3], "f4decb"); strcpy(o[4], "0008"); strcpy(o[5], "f4decb"); break; //end
|
||||
case 15: for (int i=0;i<6;i++) strcpy(o[i], cssCol[i]); //custom
|
||||
}
|
||||
}
|
||||
|
@@ -59,18 +59,19 @@ void handleSettingsSet(byte subPage)
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (ledCount > 600) ledCount = 600;
|
||||
#endif
|
||||
strip.ablMilliampsMax = server.arg("MA").toInt();
|
||||
useRGBW = server.hasArg("EW");
|
||||
strip.colorOrder = server.arg("CO").toInt();
|
||||
autoRGBtoRGBW = server.hasArg("AW");
|
||||
if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default
|
||||
|
||||
//ignore settings and save current brightness, colors and fx as default
|
||||
if (server.hasArg("IS"))
|
||||
{
|
||||
colS[0] = col[0];
|
||||
colS[1] = col[1];
|
||||
colS[2] = col[2];
|
||||
colSecS[0] = colSec[0];
|
||||
colSecS[1] = colSec[1];
|
||||
colSecS[2] = colSec[2];
|
||||
whiteS = white;
|
||||
whiteSecS = whiteSec;
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colS[i] = col[i];
|
||||
colSecS[i] = colSec[i];
|
||||
}
|
||||
briS = bri;
|
||||
effectDefault = effectCurrent;
|
||||
effectSpeedDefault = effectSpeed;
|
||||
@@ -83,8 +84,8 @@ void handleSettingsSet(byte subPage)
|
||||
colSecS[0] = server.arg("SR").toInt();
|
||||
colSecS[1] = server.arg("SG").toInt();
|
||||
colSecS[2] = server.arg("SB").toInt();
|
||||
whiteS = server.arg("CW").toInt();
|
||||
whiteSecS = server.arg("SW").toInt();
|
||||
colS[3] = server.arg("CW").toInt();
|
||||
colSecS[3] = server.arg("SW").toInt();
|
||||
briS = server.arg("CA").toInt();
|
||||
effectDefault = server.arg("FX").toInt();
|
||||
effectSpeedDefault = server.arg("SX").toInt();
|
||||
@@ -107,12 +108,11 @@ void handleSettingsSet(byte subPage)
|
||||
|
||||
nightlightTargetBri = server.arg("TB").toInt();
|
||||
t = server.arg("TL").toInt();
|
||||
if (t > 0) nightlightDelayMins = t;
|
||||
if (t > 0) nightlightDelayMinsDefault = t;
|
||||
nightlightFade = server.hasArg("TW");
|
||||
|
||||
t = server.arg("PB").toInt();
|
||||
if (t >= 0 && t < 4) strip.paletteBlend = t;
|
||||
initLedsLast = server.hasArg("EI");
|
||||
reverseMode = server.hasArg("RV");
|
||||
strip.setReverseMode(reverseMode);
|
||||
skipFirstLed = server.hasArg("SL");
|
||||
@@ -136,13 +136,13 @@ void handleSettingsSet(byte subPage)
|
||||
strcpy(cssCol[i],server.arg(k).c_str());
|
||||
}
|
||||
strcpy(cssFont,server.arg("CF").c_str());
|
||||
buildCssColorString();
|
||||
}
|
||||
|
||||
//SYNC
|
||||
if (subPage == 4)
|
||||
{
|
||||
buttonEnabled = server.hasArg("BT");
|
||||
irEnabled = server.hasArg("IR");
|
||||
int t = server.arg("UP").toInt();
|
||||
if (t > 0) udpPort = t;
|
||||
receiveNotificationBrightness = server.hasArg("RB");
|
||||
@@ -170,7 +170,9 @@ void handleSettingsSet(byte subPage)
|
||||
strcpy(alexaInvocationName, server.arg("AI").c_str());
|
||||
notifyAlexa = server.hasArg("SA");
|
||||
|
||||
if (server.hasArg("BK") && !server.arg("BK").equals("Hidden")) {strcpy(blynkApiKey,server.arg("BK").c_str()); initBlynk(blynkApiKey);}
|
||||
if (server.hasArg("BK") && !server.arg("BK").equals("Hidden")) {
|
||||
strcpy(blynkApiKey,server.arg("BK").c_str()); initBlynk(blynkApiKey);
|
||||
}
|
||||
|
||||
strcpy(mqttServer, server.arg("MS").c_str());
|
||||
strcpy(mqttDeviceTopic, server.arg("MD").c_str());
|
||||
@@ -209,10 +211,13 @@ void handleSettingsSet(byte subPage)
|
||||
useAMPM = !server.hasArg("CF");
|
||||
currentTimezone = server.arg("TZ").toInt();
|
||||
utcOffsetSecs = server.arg("UO").toInt();
|
||||
if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected
|
||||
|
||||
//start ntp if not already connected
|
||||
if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
if (server.hasArg("OL")){
|
||||
overlayDefault = server.arg("OL").toInt();
|
||||
if (overlayCurrent != overlayDefault) strip.unlockAll();
|
||||
overlayCurrent = overlayDefault;
|
||||
}
|
||||
|
||||
@@ -264,6 +269,9 @@ void handleSettingsSet(byte subPage)
|
||||
|
||||
k[0] = 'T'; //macros
|
||||
timerMacro[i] = server.arg(k).toInt();
|
||||
|
||||
k[0] = 'W'; //weekdays
|
||||
timerWeekday[i] = server.arg(k).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +281,7 @@ void handleSettingsSet(byte subPage)
|
||||
if (server.hasArg("RS")) //complete factory reset
|
||||
{
|
||||
clearEEPROM();
|
||||
serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again...",255);
|
||||
serveMessage(200, "All Settings erased.", "Connect to WLED-AP to setup again",255);
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -300,455 +308,426 @@ void handleSettingsSet(byte subPage)
|
||||
}
|
||||
saveSettingsToEEPROM();
|
||||
if (subPage == 2) strip.init(useRGBW,ledCount,skipFirstLed);
|
||||
if (subPage == 4) alexaInit();
|
||||
}
|
||||
|
||||
|
||||
//helper to get int value at a position in string
|
||||
int getNumVal(String* req, uint16_t pos)
|
||||
{
|
||||
return req->substring(pos + 3).toInt();
|
||||
}
|
||||
|
||||
|
||||
//HTTP API request parser
|
||||
bool handleSet(String req)
|
||||
{
|
||||
bool effectUpdated = false;
|
||||
if (!(req.indexOf("win") >= 0)) return false;
|
||||
if (!(req.indexOf("win") >= 0)) return false;
|
||||
|
||||
int pos = 0;
|
||||
DEBUG_PRINT("API req: ");
|
||||
DEBUG_PRINTLN(req);
|
||||
int pos = 0;
|
||||
DEBUG_PRINT("API req: ");
|
||||
DEBUG_PRINTLN(req);
|
||||
|
||||
//save macro, requires &MS=<slot>(<macro>) format
|
||||
pos = req.indexOf("&MS=");
|
||||
if (pos > 0) {
|
||||
int i = req.substring(pos + 4).toInt();
|
||||
pos = req.indexOf('(') +1;
|
||||
if (pos > 0) {
|
||||
int en = req.indexOf(')');
|
||||
String mc = req.substring(pos);
|
||||
if (en > 0) mc = req.substring(pos, en);
|
||||
saveMacro(i, mc);
|
||||
}
|
||||
|
||||
pos = req.indexOf("IN");
|
||||
if (pos < 1) XML_response(true, false);
|
||||
return true;
|
||||
//if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise
|
||||
}
|
||||
|
||||
//save macro, requires &MS=<slot>(<macro>) format
|
||||
pos = req.indexOf("&MS=");
|
||||
if (pos > 0) {
|
||||
int i = req.substring(pos + 4).toInt();
|
||||
pos = req.indexOf('(') +1;
|
||||
if (pos > 0) {
|
||||
int en = req.indexOf(')');
|
||||
String mc = req.substring(pos);
|
||||
if (en > 0) mc = req.substring(pos, en);
|
||||
saveMacro(i, mc);
|
||||
}
|
||||
|
||||
pos = req.indexOf("IN");
|
||||
if (pos < 1) XML_response(true);
|
||||
return true;
|
||||
//if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise
|
||||
}
|
||||
|
||||
//set brigthness
|
||||
pos = req.indexOf("&A=");
|
||||
if (pos > 0) {
|
||||
bri = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set brigthness
|
||||
pos = req.indexOf("&A=");
|
||||
if (pos > 0) {
|
||||
bri = getNumVal(&req, pos);
|
||||
}
|
||||
|
||||
//set hue
|
||||
pos = req.indexOf("HU=");
|
||||
if (pos > 0) {
|
||||
uint16_t temphue = req.substring(pos + 3).toInt();
|
||||
byte tempsat = 255;
|
||||
pos = req.indexOf("SA=");
|
||||
if (pos > 0) {
|
||||
tempsat = req.substring(pos + 3).toInt();
|
||||
}
|
||||
colorHStoRGB(temphue,tempsat,(req.indexOf("H2")>0)? colSec:col);
|
||||
}
|
||||
//set hue
|
||||
pos = req.indexOf("HU=");
|
||||
if (pos > 0) {
|
||||
uint16_t temphue = getNumVal(&req, pos);
|
||||
byte tempsat = 255;
|
||||
pos = req.indexOf("SA=");
|
||||
if (pos > 0) {
|
||||
tempsat = getNumVal(&req, pos);
|
||||
}
|
||||
colorHStoRGB(temphue,tempsat,(req.indexOf("H2")>0)? colSec:col);
|
||||
}
|
||||
|
||||
//set red value
|
||||
pos = req.indexOf("&R=");
|
||||
if (pos > 0) {
|
||||
col[0] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set green value
|
||||
pos = req.indexOf("&G=");
|
||||
if (pos > 0) {
|
||||
col[1] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set blue value
|
||||
pos = req.indexOf("&B=");
|
||||
if (pos > 0) {
|
||||
col[2] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set white value
|
||||
pos = req.indexOf("&W=");
|
||||
if (pos > 0) {
|
||||
white = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set red value
|
||||
pos = req.indexOf("&R=");
|
||||
if (pos > 0) {
|
||||
col[0] = getNumVal(&req, pos);
|
||||
}
|
||||
//set green value
|
||||
pos = req.indexOf("&G=");
|
||||
if (pos > 0) {
|
||||
col[1] = getNumVal(&req, pos);
|
||||
}
|
||||
//set blue value
|
||||
pos = req.indexOf("&B=");
|
||||
if (pos > 0) {
|
||||
col[2] = getNumVal(&req, pos);
|
||||
}
|
||||
//set white value
|
||||
pos = req.indexOf("&W=");
|
||||
if (pos > 0) {
|
||||
col[3] = getNumVal(&req, pos);
|
||||
}
|
||||
|
||||
//set 2nd red value
|
||||
pos = req.indexOf("R2=");
|
||||
if (pos > 0) {
|
||||
colSec[0] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set 2nd green value
|
||||
pos = req.indexOf("G2=");
|
||||
if (pos > 0) {
|
||||
colSec[1] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set 2nd blue value
|
||||
pos = req.indexOf("B2=");
|
||||
if (pos > 0) {
|
||||
colSec[2] = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set 2nd white value
|
||||
pos = req.indexOf("W2=");
|
||||
if (pos > 0) {
|
||||
whiteSec = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set 2nd red value
|
||||
pos = req.indexOf("R2=");
|
||||
if (pos > 0) {
|
||||
colSec[0] = getNumVal(&req, pos);
|
||||
}
|
||||
//set 2nd green value
|
||||
pos = req.indexOf("G2=");
|
||||
if (pos > 0) {
|
||||
colSec[1] = getNumVal(&req, pos);
|
||||
}
|
||||
//set 2nd blue value
|
||||
pos = req.indexOf("B2=");
|
||||
if (pos > 0) {
|
||||
colSec[2] = getNumVal(&req, pos);
|
||||
}
|
||||
//set 2nd white value
|
||||
pos = req.indexOf("W2=");
|
||||
if (pos > 0) {
|
||||
colSec[3] = getNumVal(&req, pos);
|
||||
}
|
||||
|
||||
//set color from HEX or 32bit DEC
|
||||
pos = req.indexOf("CL=");
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(col, &white, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
pos = req.indexOf("C2=");
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(colSec, &whiteSec, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
//set color from HEX or 32bit DEC
|
||||
pos = req.indexOf("CL=");
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(col, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
pos = req.indexOf("C2=");
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
|
||||
//set 2nd to white
|
||||
pos = req.indexOf("SW");
|
||||
if (pos > 0) {
|
||||
if(useRGBW) {
|
||||
whiteSec = 255;
|
||||
colSec[0] = 0;
|
||||
colSec[1] = 0;
|
||||
colSec[2] = 0;
|
||||
} else {
|
||||
colSec[0] = 255;
|
||||
colSec[1] = 255;
|
||||
colSec[2] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
//set 2nd to black
|
||||
pos = req.indexOf("SB");
|
||||
if (pos > 0) {
|
||||
whiteSec = 0;
|
||||
//set 2nd to white
|
||||
pos = req.indexOf("SW");
|
||||
if (pos > 0) {
|
||||
if(useRGBW) {
|
||||
colSec[3] = 255;
|
||||
colSec[0] = 0;
|
||||
colSec[1] = 0;
|
||||
colSec[2] = 0;
|
||||
}
|
||||
} else {
|
||||
colSec[0] = 255;
|
||||
colSec[1] = 255;
|
||||
colSec[2] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
//set to random hue SR=0->1st SR=1->2nd
|
||||
pos = req.indexOf("SR");
|
||||
if (pos > 0) {
|
||||
_setRandomColor(req.substring(pos + 3).toInt());
|
||||
}
|
||||
//set 2nd to 1st
|
||||
pos = req.indexOf("SP");
|
||||
if (pos > 0) {
|
||||
colSec[0] = col[0];
|
||||
colSec[1] = col[1];
|
||||
colSec[2] = col[2];
|
||||
whiteSec = white;
|
||||
}
|
||||
//swap 2nd & 1st
|
||||
pos = req.indexOf("SC");
|
||||
if (pos > 0) {
|
||||
byte _temp[4];
|
||||
for (int i = 0; i<3; i++)
|
||||
{
|
||||
_temp[i] = col[i];
|
||||
col[i] = colSec[i];
|
||||
colSec[i] = _temp[i];
|
||||
}
|
||||
_temp[3] = white;
|
||||
white = whiteSec;
|
||||
whiteSec = _temp[3];
|
||||
}
|
||||
//set 2nd to black
|
||||
pos = req.indexOf("SB");
|
||||
if (pos > 0) {
|
||||
colSec[3] = 0;
|
||||
colSec[0] = 0;
|
||||
colSec[1] = 0;
|
||||
colSec[2] = 0;
|
||||
}
|
||||
|
||||
//set current effect index
|
||||
pos = req.indexOf("FX=");
|
||||
if (pos > 0) {
|
||||
if (effectCurrent != req.substring(pos + 3).toInt())
|
||||
{
|
||||
effectCurrent = req.substring(pos + 3).toInt();
|
||||
strip.setMode(effectCurrent);
|
||||
effectUpdated = true;
|
||||
}
|
||||
}
|
||||
//set effect speed
|
||||
pos = req.indexOf("SX=");
|
||||
if (pos > 0) {
|
||||
if (effectSpeed != req.substring(pos + 3).toInt())
|
||||
{
|
||||
effectSpeed = req.substring(pos + 3).toInt();
|
||||
strip.setSpeed(effectSpeed);
|
||||
effectUpdated = true;
|
||||
}
|
||||
}
|
||||
//set effect intensity
|
||||
pos = req.indexOf("IX=");
|
||||
if (pos > 0) {
|
||||
if (effectIntensity != req.substring(pos + 3).toInt())
|
||||
{
|
||||
effectIntensity = req.substring(pos + 3).toInt();
|
||||
strip.setIntensity(effectIntensity);
|
||||
effectUpdated = true;
|
||||
}
|
||||
}
|
||||
//set effect palette (only for FastLED effects)
|
||||
pos = req.indexOf("FP=");
|
||||
if (pos > 0) {
|
||||
if (effectPalette != req.substring(pos + 3).toInt())
|
||||
{
|
||||
effectPalette = req.substring(pos + 3).toInt();
|
||||
strip.setPalette(effectPalette);
|
||||
effectUpdated = true;
|
||||
}
|
||||
}
|
||||
//set to random hue SR=0->1st SR=1->2nd
|
||||
pos = req.indexOf("SR");
|
||||
if (pos > 0) {
|
||||
_setRandomColor(getNumVal(&req, pos));
|
||||
}
|
||||
//set 2nd to 1st
|
||||
pos = req.indexOf("SP");
|
||||
if (pos > 0) {
|
||||
colSec[0] = col[0];
|
||||
colSec[1] = col[1];
|
||||
colSec[2] = col[2];
|
||||
colSec[3] = col[3];
|
||||
}
|
||||
//swap 2nd & 1st
|
||||
pos = req.indexOf("SC");
|
||||
if (pos > 0) {
|
||||
byte temp;
|
||||
for (uint8_t i=0; i<4; i++)
|
||||
{
|
||||
temp = col[i];
|
||||
col[i] = colSec[i];
|
||||
colSec[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
//set current effect index
|
||||
pos = req.indexOf("FX=");
|
||||
if (pos > 0) {
|
||||
effectCurrent = getNumVal(&req, pos);
|
||||
presetCyclingEnabled = false;
|
||||
}
|
||||
//set effect speed
|
||||
pos = req.indexOf("SX=");
|
||||
if (pos > 0) {
|
||||
effectSpeed = getNumVal(&req, pos);
|
||||
}
|
||||
//set effect intensity
|
||||
pos = req.indexOf("IX=");
|
||||
if (pos > 0) {
|
||||
effectIntensity = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set effect palette (only for FastLED effects)
|
||||
pos = req.indexOf("FP=");
|
||||
if (pos > 0) {
|
||||
effectPalette = req.substring(pos + 3).toInt();
|
||||
}
|
||||
|
||||
//set hue polling light: 0 -off
|
||||
pos = req.indexOf("HP=");
|
||||
if (pos > 0) {
|
||||
int id = req.substring(pos + 3).toInt();
|
||||
if (id > 0)
|
||||
{
|
||||
if (id < 100) huePollLightId = id;
|
||||
setupHue();
|
||||
} else {
|
||||
huePollingEnabled = false;
|
||||
}
|
||||
}
|
||||
//set hue polling light: 0 -off
|
||||
pos = req.indexOf("HP=");
|
||||
if (pos > 0) {
|
||||
int id = getNumVal(&req, pos);
|
||||
if (id > 0)
|
||||
{
|
||||
if (id < 100) huePollLightId = id;
|
||||
setupHue();
|
||||
} else {
|
||||
huePollingEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
//set default control mode (0 - RGB, 1 - HSB)
|
||||
pos = req.indexOf("MD=");
|
||||
if (pos > 0) {
|
||||
useHSB = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//set advanced overlay
|
||||
pos = req.indexOf("OL=");
|
||||
if (pos > 0) {
|
||||
overlayCurrent = req.substring(pos + 3).toInt();
|
||||
strip.unlockAll();
|
||||
}
|
||||
//(un)lock pixel (ranges)
|
||||
pos = req.indexOf("&L=");
|
||||
if (pos > 0){
|
||||
int index = req.substring(pos + 3).toInt();
|
||||
pos = req.indexOf("L2=");
|
||||
if (pos > 0){
|
||||
int index2 = req.substring(pos + 3).toInt();
|
||||
if (req.indexOf("UL") > 0)
|
||||
{
|
||||
strip.unlockRange(index, index2);
|
||||
} else
|
||||
{
|
||||
strip.lockRange(index, index2);
|
||||
}
|
||||
//set default control mode (0 - RGB, 1 - HSB)
|
||||
pos = req.indexOf("MD=");
|
||||
if (pos > 0) {
|
||||
useHSB = getNumVal(&req, pos);
|
||||
}
|
||||
//set advanced overlay
|
||||
pos = req.indexOf("OL=");
|
||||
if (pos > 0) {
|
||||
overlayCurrent = getNumVal(&req, pos);
|
||||
strip.unlockAll();
|
||||
}
|
||||
//(un)lock pixel (ranges)
|
||||
pos = req.indexOf("&L=");
|
||||
if (pos > 0){
|
||||
int index = getNumVal(&req, pos);
|
||||
pos = req.indexOf("L2=");
|
||||
if (pos > 0){
|
||||
int index2 = getNumVal(&req, pos);
|
||||
if (req.indexOf("UL") > 0)
|
||||
{
|
||||
strip.unlockRange(index, index2);
|
||||
} else
|
||||
{
|
||||
if (req.indexOf("UL") > 0)
|
||||
{
|
||||
strip.unlock(index);
|
||||
} else
|
||||
{
|
||||
strip.lock(index);
|
||||
}
|
||||
strip.lockRange(index, index2);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (req.indexOf("UL") > 0)
|
||||
{
|
||||
strip.unlock(index);
|
||||
} else
|
||||
{
|
||||
strip.lock(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply macro
|
||||
pos = req.indexOf("&M=");
|
||||
if (pos > 0) {
|
||||
applyMacro(req.substring(pos + 3).toInt());
|
||||
}
|
||||
//toggle send UDP direct notifications
|
||||
if (req.indexOf("SN=") > 0)
|
||||
{
|
||||
notifyDirect = true;
|
||||
if (req.indexOf("SN=0") > 0)
|
||||
{
|
||||
notifyDirect = false;
|
||||
}
|
||||
}
|
||||
//apply macro
|
||||
pos = req.indexOf("&M=");
|
||||
if (pos > 0) {
|
||||
applyMacro(getNumVal(&req, pos));
|
||||
}
|
||||
//toggle send UDP direct notifications
|
||||
if (req.indexOf("SN=") > 0)
|
||||
{
|
||||
notifyDirect = true;
|
||||
if (req.indexOf("SN=0") > 0)
|
||||
{
|
||||
notifyDirect = false;
|
||||
}
|
||||
}
|
||||
|
||||
//toggle receive UDP direct notifications
|
||||
if (req.indexOf("RN=") > 0)
|
||||
{
|
||||
receiveNotifications = true;
|
||||
if (req.indexOf("RN=0") > 0)
|
||||
{
|
||||
receiveNotifications = false;
|
||||
}
|
||||
}
|
||||
//toggle receive UDP direct notifications
|
||||
if (req.indexOf("RN=") > 0)
|
||||
{
|
||||
receiveNotifications = true;
|
||||
if (req.indexOf("RN=0") > 0)
|
||||
{
|
||||
receiveNotifications = false;
|
||||
}
|
||||
}
|
||||
|
||||
//toggle nightlight mode
|
||||
bool aNlDef = false;
|
||||
if (req.indexOf("&ND") > 0) aNlDef = true;
|
||||
pos = req.indexOf("NL=");
|
||||
if (pos > 0)
|
||||
{
|
||||
if (req.indexOf("NL=0") > 0)
|
||||
{
|
||||
nightlightActive = false;
|
||||
bri = briT;
|
||||
} else {
|
||||
nightlightActive = true;
|
||||
if (!aNlDef) nightlightDelayMins = req.substring(pos + 3).toInt();
|
||||
nightlightStartTime = millis();
|
||||
}
|
||||
} else if (aNlDef)
|
||||
{
|
||||
//toggle nightlight mode
|
||||
bool aNlDef = false;
|
||||
if (req.indexOf("&ND") > 0) aNlDef = true;
|
||||
pos = req.indexOf("NL=");
|
||||
if (pos > 0)
|
||||
{
|
||||
if (req.indexOf("NL=0") > 0)
|
||||
{
|
||||
nightlightActive = false;
|
||||
bri = briT;
|
||||
} else {
|
||||
nightlightActive = true;
|
||||
if (!aNlDef) nightlightDelayMins = getNumVal(&req, pos);
|
||||
nightlightStartTime = millis();
|
||||
}
|
||||
}
|
||||
} else if (aNlDef)
|
||||
{
|
||||
nightlightActive = true;
|
||||
nightlightStartTime = millis();
|
||||
}
|
||||
|
||||
//set nightlight target brightness
|
||||
pos = req.indexOf("NT=");
|
||||
if (pos > 0) {
|
||||
nightlightTargetBri = req.substring(pos + 3).toInt();
|
||||
nightlightActiveOld = false; //re-init
|
||||
}
|
||||
//set nightlight target brightness
|
||||
pos = req.indexOf("NT=");
|
||||
if (pos > 0) {
|
||||
nightlightTargetBri = getNumVal(&req, pos);
|
||||
nightlightActiveOld = false; //re-init
|
||||
}
|
||||
|
||||
//toggle nightlight fade
|
||||
if (req.indexOf("NF=") > 0)
|
||||
{
|
||||
if (req.indexOf("NF=0") > 0)
|
||||
{
|
||||
nightlightFade = false;
|
||||
} else {
|
||||
nightlightFade = true;
|
||||
}
|
||||
nightlightActiveOld = false; //re-init
|
||||
}
|
||||
//toggle nightlight fade
|
||||
if (req.indexOf("NF=") > 0)
|
||||
{
|
||||
if (req.indexOf("NF=0") > 0)
|
||||
{
|
||||
nightlightFade = false;
|
||||
} else {
|
||||
nightlightFade = true;
|
||||
}
|
||||
nightlightActiveOld = false; //re-init
|
||||
}
|
||||
|
||||
//toggle general purpose output
|
||||
pos = req.indexOf("AX=");
|
||||
if (pos > 0) {
|
||||
auxTime = req.substring(pos + 3).toInt();
|
||||
auxActive = true;
|
||||
if (auxTime == 0) auxActive = false;
|
||||
}
|
||||
pos = req.indexOf("TT=");
|
||||
if (pos > 0) {
|
||||
transitionDelay = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//toggle general purpose output
|
||||
pos = req.indexOf("AX=");
|
||||
if (pos > 0) {
|
||||
auxTime = getNumVal(&req, pos);
|
||||
auxActive = true;
|
||||
if (auxTime == 0) auxActive = false;
|
||||
}
|
||||
pos = req.indexOf("TT=");
|
||||
if (pos > 0) {
|
||||
transitionDelay = getNumVal(&req, pos);
|
||||
}
|
||||
|
||||
//main toggle on/off
|
||||
pos = req.indexOf("&T=");
|
||||
if (pos > 0) {
|
||||
nightlightActive = false; //always disable nightlight when toggling
|
||||
switch (req.substring(pos + 3).toInt())
|
||||
{
|
||||
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off
|
||||
case 1: bri = briLast; break; //on
|
||||
default: if (bri == 0) //toggle
|
||||
{
|
||||
bri = briLast;
|
||||
} else
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//main toggle on/off
|
||||
pos = req.indexOf("&T=");
|
||||
if (pos > 0) {
|
||||
nightlightActive = false; //always disable nightlight when toggling
|
||||
switch (getNumVal(&req, pos))
|
||||
{
|
||||
case 0: if (bri != 0){briLast = bri; bri = 0;} break; //off
|
||||
case 1: bri = briLast; break; //on
|
||||
default: toggleOnOff(); //toggle
|
||||
}
|
||||
}
|
||||
|
||||
//deactivate nightlight if target brightness is reached
|
||||
if (bri == nightlightTargetBri) nightlightActive = false;
|
||||
//set time (unix timestamp)
|
||||
pos = req.indexOf("ST=");
|
||||
if (pos > 0) {
|
||||
setTime(req.substring(pos+3).toInt());
|
||||
}
|
||||
//deactivate nightlight if target brightness is reached
|
||||
if (bri == nightlightTargetBri) nightlightActive = false;
|
||||
//set time (unix timestamp)
|
||||
pos = req.indexOf("ST=");
|
||||
if (pos > 0) {
|
||||
setTime(getNumVal(&req, pos));
|
||||
}
|
||||
|
||||
//set countdown goal (unix timestamp)
|
||||
pos = req.indexOf("CT=");
|
||||
if (pos > 0) {
|
||||
countdownTime = req.substring(pos+3).toInt();
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
}
|
||||
//set countdown goal (unix timestamp)
|
||||
pos = req.indexOf("CT=");
|
||||
if (pos > 0) {
|
||||
countdownTime = getNumVal(&req, pos);
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
}
|
||||
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt();
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt();
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
||||
|
||||
if (req.indexOf("CY=") > 0) //preset cycle
|
||||
{
|
||||
presetCyclingEnabled = true;
|
||||
if (req.indexOf("CY=0") > 0)
|
||||
{
|
||||
presetCyclingEnabled = false;
|
||||
}
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = req.substring(pos + 3).toInt();
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
if (req.indexOf("PA=") > 0) //apply brightness from preset
|
||||
{
|
||||
presetApplyBri = true;
|
||||
if (req.indexOf("PA=0") > 0) presetApplyBri = false;
|
||||
}
|
||||
if (req.indexOf("PC=") > 0) //apply color from preset
|
||||
{
|
||||
presetApplyCol = true;
|
||||
if (req.indexOf("PC=0") > 0) presetApplyCol = false;
|
||||
}
|
||||
if (req.indexOf("PX=") > 0) //apply effects from preset
|
||||
{
|
||||
presetApplyFx = true;
|
||||
if (req.indexOf("PX=0") > 0) presetApplyFx = false;
|
||||
}
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) {
|
||||
savePreset(req.substring(pos + 3).toInt());
|
||||
}
|
||||
pos = req.indexOf("PL="); //applies entire preset
|
||||
if (pos > 0) {
|
||||
applyPreset(req.substring(pos + 3).toInt(), presetApplyBri, presetApplyCol, presetApplyFx);
|
||||
if (presetApplyFx) effectUpdated = true;
|
||||
}
|
||||
|
||||
//cronixie
|
||||
pos = req.indexOf("NX="); //sets digits to code
|
||||
if (pos > 0) {
|
||||
strcpy(cronixieDisplay,req.substring(pos + 3, pos + 9).c_str());
|
||||
setCronixie();
|
||||
}
|
||||
pos = req.indexOf("NM="); //mode, 1 countdown
|
||||
if (pos > 0) {
|
||||
countdownMode = true;
|
||||
if (req.indexOf("NM=0") > 0)
|
||||
{
|
||||
countdownMode = false;
|
||||
}
|
||||
}
|
||||
if (req.indexOf("NB=") > 0) //sets backlight
|
||||
{
|
||||
cronixieBacklight = true;
|
||||
if (req.indexOf("NB=0") > 0)
|
||||
{
|
||||
cronixieBacklight = false;
|
||||
}
|
||||
if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
pos = req.indexOf("U0="); //user var 0
|
||||
if (pos > 0) {
|
||||
userVar0 = req.substring(pos + 3).toInt();
|
||||
}
|
||||
pos = req.indexOf("U1="); //user var 1
|
||||
if (pos > 0) {
|
||||
userVar1 = req.substring(pos + 3).toInt();
|
||||
}
|
||||
//you can add more if you need
|
||||
if (req.indexOf("CY=") > 0) //preset cycle
|
||||
{
|
||||
presetCyclingEnabled = true;
|
||||
if (req.indexOf("CY=0") > 0)
|
||||
{
|
||||
presetCyclingEnabled = false;
|
||||
}
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
if (req.indexOf("PA=") > 0) //apply brightness from preset
|
||||
{
|
||||
presetApplyBri = true;
|
||||
if (req.indexOf("PA=0") > 0) presetApplyBri = false;
|
||||
}
|
||||
if (req.indexOf("PC=") > 0) //apply color from preset
|
||||
{
|
||||
presetApplyCol = true;
|
||||
if (req.indexOf("PC=0") > 0) presetApplyCol = false;
|
||||
}
|
||||
if (req.indexOf("PX=") > 0) //apply effects from preset
|
||||
{
|
||||
presetApplyFx = true;
|
||||
if (req.indexOf("PX=0") > 0) presetApplyFx = false;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) {
|
||||
savePreset(getNumVal(&req, pos));
|
||||
}
|
||||
pos = req.indexOf("PL="); //applies entire preset
|
||||
if (pos > 0) {
|
||||
applyPreset(getNumVal(&req, pos), presetApplyBri, presetApplyCol, presetApplyFx);
|
||||
}
|
||||
|
||||
//cronixie
|
||||
pos = req.indexOf("NX="); //sets digits to code
|
||||
if (pos > 0) {
|
||||
strcpy(cronixieDisplay,req.substring(pos + 3, pos + 9).c_str());
|
||||
setCronixie();
|
||||
}
|
||||
pos = req.indexOf("NM="); //mode, 1 countdown
|
||||
if (pos > 0) {
|
||||
countdownMode = true;
|
||||
if (req.indexOf("NM=0") > 0)
|
||||
{
|
||||
countdownMode = false;
|
||||
}
|
||||
}
|
||||
if (req.indexOf("NB=") > 0) //sets backlight
|
||||
{
|
||||
cronixieBacklight = true;
|
||||
if (req.indexOf("NB=0") > 0)
|
||||
{
|
||||
cronixieBacklight = false;
|
||||
}
|
||||
if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
|
||||
pos = req.indexOf("U0="); //user var 0
|
||||
if (pos > 0) {
|
||||
userVar0 = getNumVal(&req, pos);
|
||||
}
|
||||
pos = req.indexOf("U1="); //user var 1
|
||||
if (pos > 0) {
|
||||
userVar1 = getNumVal(&req, pos);
|
||||
}
|
||||
//you can add more if you need
|
||||
|
||||
//internal call, does not send XML response
|
||||
pos = req.indexOf("IN");
|
||||
if (pos < 1) XML_response(true);
|
||||
//do not send UDP notifications this time
|
||||
pos = req.indexOf("NN");
|
||||
if (pos > 0)
|
||||
{
|
||||
colorUpdated(5);
|
||||
return true;
|
||||
}
|
||||
if (effectUpdated)
|
||||
{
|
||||
colorUpdated(6);
|
||||
} else
|
||||
{
|
||||
colorUpdated(1);
|
||||
}
|
||||
return true;
|
||||
//internal call, does not send XML response
|
||||
pos = req.indexOf("IN");
|
||||
if (pos < 1) XML_response(true, (req.indexOf("IT") > 0)); //include theme if firstload
|
||||
|
||||
pos = req.indexOf("NN"); //do not send UDP notifications this time
|
||||
colorUpdated((pos > 0) ? 5:1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -3,36 +3,37 @@
|
||||
*/
|
||||
void handleSerial()
|
||||
{
|
||||
if (Serial.available() > 0) //support for Adalight protocol to high-speed control LEDs over serial (gamma correction done by PC)
|
||||
if (Serial.available() > 0) //support for Adalight protocol to high-speed control LEDs over serial
|
||||
{
|
||||
if (Serial.find("Ada"))
|
||||
if (!Serial.find("Ada")) return;
|
||||
|
||||
if (!realtimeActive && bri == 0) strip.setBrightness(briLast);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
|
||||
delay(1);
|
||||
byte hi = Serial.read();
|
||||
byte ledc = Serial.read();
|
||||
byte chk = Serial.read();
|
||||
if(chk != (hi ^ ledc ^ 0x55)) return;
|
||||
if (ledCount < ledc) ledc = ledCount;
|
||||
|
||||
byte sc[3]; int t =-1; int to = 0;
|
||||
for (int i=0; i < ledc; i++)
|
||||
{
|
||||
if (!realtimeActive && bri == 0) strip.setBrightness(briLast);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
delay(1);
|
||||
byte hi = Serial.read();
|
||||
byte ledc = Serial.read();
|
||||
byte chk = Serial.read();
|
||||
if(chk != (hi ^ ledc ^ 0x55)) return;
|
||||
if (ledCount < ledc) ledc = ledCount;
|
||||
byte sc[3]; int t =-1; int to = 0;
|
||||
for (int i=0; i < ledc; i++)
|
||||
for (byte j=0; j<3; j++)
|
||||
{
|
||||
for (byte j=0; j<3; j++)
|
||||
while (Serial.peek()<0) //no data yet available
|
||||
{
|
||||
while (Serial.peek()<0) //no data yet available
|
||||
{
|
||||
delay(1);
|
||||
to++;
|
||||
if (to>5) {strip.show(); return;} //unexpected end of transmission
|
||||
}
|
||||
to = 0;
|
||||
sc[j] = Serial.read();
|
||||
delay(1);
|
||||
to++;
|
||||
if (to>5) {strip.show(); return;} //unexpected end of transmission
|
||||
}
|
||||
setRealtimePixel(i,sc[0],sc[1],sc[2],0);
|
||||
to = 0;
|
||||
sc[j] = Serial.read();
|
||||
}
|
||||
strip.show();
|
||||
setRealtimePixel(i,sc[0],sc[1],sc[2],0);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,29 +5,29 @@
|
||||
void wledInit()
|
||||
{
|
||||
EEPROM.begin(EEPSIZE);
|
||||
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
|
||||
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
|
||||
if (ledCount > 1200 || ledCount == 0) ledCount = 30;
|
||||
//RMT eats up too much RAM
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (ledCount > 600) ledCount = 600;
|
||||
if (ledCount > 600) ledCount = 600;
|
||||
#endif
|
||||
if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204)); //quick init
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
|
||||
strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204)); //init LEDs quickly
|
||||
|
||||
#ifdef USEFS
|
||||
SPIFFS.begin();
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN("Load EEPROM");
|
||||
loadSettingsFromEEPROM(true);
|
||||
if (!initLedsLast) initStrip();
|
||||
beginStrip();
|
||||
DEBUG_PRINT("CSSID: ");
|
||||
DEBUG_PRINT(clientSSID);
|
||||
buildCssColorString();
|
||||
userBeginPreConnection();
|
||||
if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true;
|
||||
|
||||
WiFi.persistent(false);
|
||||
initCon();
|
||||
|
||||
DEBUG_PRINTLN("");
|
||||
@@ -58,6 +58,11 @@ void wledInit()
|
||||
}
|
||||
|
||||
prepareIds(); //UUID from MAC (for Alexa and MQTT)
|
||||
if (strcmp(cmDNS,"x") == 0) //fill in unique mdns default
|
||||
{
|
||||
strcpy(cmDNS, "wled-");
|
||||
strcat(cmDNS, escapedMac.c_str());
|
||||
}
|
||||
if (mqttDeviceTopic[0] == 0)
|
||||
{
|
||||
strcpy(mqttDeviceTopic, "wled/");
|
||||
@@ -72,12 +77,12 @@ void wledInit()
|
||||
mqttInit = initMQTT();
|
||||
}
|
||||
|
||||
if (!initLedsLast) strip.service();
|
||||
strip.service();
|
||||
|
||||
//HTTP server page init
|
||||
initServer();
|
||||
|
||||
if (!initLedsLast) strip.service();
|
||||
strip.service();
|
||||
//init Alexa hue emulation
|
||||
if (alexaEnabled && !onlyAP) alexaInit();
|
||||
|
||||
@@ -86,6 +91,7 @@ void wledInit()
|
||||
|
||||
//init ArduinoOTA
|
||||
if (!onlyAP) {
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled)
|
||||
{
|
||||
ArduinoOTA.onStart([]() {
|
||||
@@ -97,8 +103,9 @@ void wledInit()
|
||||
if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS);
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!initLedsLast) strip.service();
|
||||
strip.service();
|
||||
// Set up mDNS responder:
|
||||
if (strlen(cmDNS) > 0 && !onlyAP)
|
||||
{
|
||||
@@ -106,8 +113,9 @@ void wledInit()
|
||||
DEBUG_PRINTLN("mDNS responder started");
|
||||
// Add service to MDNS
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("wled", "tcp", 80);
|
||||
}
|
||||
if (!initLedsLast) strip.service();
|
||||
strip.service();
|
||||
|
||||
initBlynk(blynkApiKey);
|
||||
initE131();
|
||||
@@ -117,29 +125,30 @@ void wledInit()
|
||||
e131Enabled = false;
|
||||
}
|
||||
|
||||
if (initLedsLast) initStrip();
|
||||
userBegin();
|
||||
|
||||
if (macroBoot>0) applyMacro(macroBoot);
|
||||
Serial.println("Ada");
|
||||
}
|
||||
|
||||
void initStrip()
|
||||
|
||||
void beginStrip()
|
||||
{
|
||||
// Initialize NeoPixel Strip and button
|
||||
if (initLedsLast) strip.init(useRGBW,ledCount,skipFirstLed);
|
||||
strip.setReverseMode(reverseMode);
|
||||
strip.setColor(0);
|
||||
strip.setBrightness(255);
|
||||
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
pinMode(4,OUTPUT); //this is only needed in special cases
|
||||
digitalWrite(4,LOW);
|
||||
pinMode(BTNPIN, INPUT_PULLUP);
|
||||
|
||||
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
|
||||
colorUpdated(0);
|
||||
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
|
||||
|
||||
//disable button if it is "pressed" unintentionally
|
||||
if(digitalRead(BTNPIN) == LOW) buttonEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
void initAP(){
|
||||
bool set = apSSID[0];
|
||||
if (!set) strcpy(apSSID,"WLED-AP");
|
||||
@@ -147,6 +156,7 @@ void initAP(){
|
||||
if (!set) apSSID[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
void initCon()
|
||||
{
|
||||
WiFi.disconnect(); //close old connections
|
||||
@@ -170,26 +180,24 @@ void initCon()
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
int fail_count = 0;
|
||||
if (strlen(clientSSID) <1 || strcmp(clientSSID,"Your_Network") == 0) fail_count = apWaitTimeSecs*2; //instantly go to ap mode
|
||||
if (strlen(clientSSID) <1 || strcmp(clientSSID,"Your_Network") == 0)
|
||||
fail_count = apWaitTimeSecs*2; //instantly go to ap mode
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
WiFi.hostname(serverDescription);
|
||||
WiFi.hostname(serverDescription);
|
||||
#endif
|
||||
WiFi.begin(clientSSID, clientPass);
|
||||
WiFi.begin(clientSSID, clientPass);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setHostname(serverDescription);
|
||||
WiFi.setHostname(serverDescription);
|
||||
#endif
|
||||
unsigned long lastTry = 0;
|
||||
bool con = false;
|
||||
while(!con)
|
||||
{
|
||||
yield();
|
||||
if (!initLedsLast)
|
||||
{
|
||||
handleTransitions();
|
||||
handleButton();
|
||||
handleOverlays();
|
||||
if (briT) strip.service();
|
||||
}
|
||||
handleTransitions();
|
||||
handleButton();
|
||||
handleOverlays();
|
||||
if (briT) strip.service();
|
||||
if (millis()-lastTry > 499) {
|
||||
con = (WiFi.status() == WL_CONNECTED);
|
||||
lastTry = millis();
|
||||
@@ -208,9 +216,9 @@ void initCon()
|
||||
}
|
||||
|
||||
|
||||
//fill string buffer with build info
|
||||
void getBuildInfo()
|
||||
{
|
||||
//fill string buffer with build info
|
||||
olen = 0;
|
||||
oappend("hard-coded build info:\r\n\n");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
@@ -224,25 +232,46 @@ void getBuildInfo()
|
||||
oappendi(VERSION);
|
||||
oappend("\r\neepver: ");
|
||||
oappendi(EEPVER);
|
||||
oappend("\r\nesp-core: ");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
oappend((char*)ESP.getSdkVersion());
|
||||
#else
|
||||
oappend((char*)ESP.getCoreVersion().c_str());
|
||||
#endif
|
||||
oappend("\r\nopt: ");
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
oappend("alexa ");
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
oappend("blynk ");
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
oappend("cronixie ");
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
oappend("huesync ");
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_MOBILE_UI
|
||||
oappend("mobile-ui ");
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
oappend("ota");
|
||||
#endif
|
||||
#ifdef USEFS
|
||||
oappend("\r\nspiffs: true\r\n");
|
||||
#else
|
||||
oappend("\r\nspiffs: false\r\n");
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
#ifdef WLED_DEBUG
|
||||
oappend("debug: true\r\n");
|
||||
#else
|
||||
oappend("debug: false\r\n");
|
||||
#endif
|
||||
oappend("button-pin: gpio");
|
||||
oappendi(buttonPin);
|
||||
oappend("\r\n");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
oappend("strip-pin: gpio");
|
||||
oappendi(BTNPIN);
|
||||
oappend("\r\nstrip-pin: gpio");
|
||||
oappendi(LEDPIN);
|
||||
#else
|
||||
oappend("strip-pin: gpio2");
|
||||
#endif
|
||||
oappend("\r\nbrand: wled");
|
||||
oappend("\r\nbuild-type: src\r\n");
|
||||
}
|
||||
|
||||
@@ -255,6 +284,3 @@ bool checkClientIsMobile(String useragent)
|
||||
if (useragent.indexOf("iPod") >= 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -3,6 +3,8 @@
|
||||
*/
|
||||
|
||||
#define WLEDPACKETSIZE 24
|
||||
#define UDP_IN_MAXSIZE 1472
|
||||
|
||||
|
||||
void notify(byte callMode, bool followUp=false)
|
||||
{
|
||||
@@ -14,9 +16,10 @@ void notify(byte callMode, bool followUp=false)
|
||||
case 2: if (!notifyButton) return; break;
|
||||
case 4: if (!notifyDirect) return; break;
|
||||
case 6: if (!notifyDirect) return; break; //fx change
|
||||
case 7: if (!notifyHue) return; break;
|
||||
case 7: if (!notifyHue) return; break;
|
||||
case 8: if (!notifyDirect) return; break;
|
||||
case 9: if (!notifyDirect) return; break;
|
||||
case 10: if (!notifyAlexa) return; break;
|
||||
default: return;
|
||||
}
|
||||
byte udpOut[WLEDPACKETSIZE];
|
||||
@@ -30,19 +33,19 @@ void notify(byte callMode, bool followUp=false)
|
||||
udpOut[7] = nightlightDelayMins;
|
||||
udpOut[8] = effectCurrent;
|
||||
udpOut[9] = effectSpeed;
|
||||
udpOut[10] = white;
|
||||
udpOut[10] = col[3];
|
||||
udpOut[11] = 5; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
|
||||
udpOut[12] = colSec[0];
|
||||
udpOut[13] = colSec[1];
|
||||
udpOut[14] = colSec[2];
|
||||
udpOut[15] = whiteSec;
|
||||
udpOut[15] = colSec[3];
|
||||
udpOut[16] = effectIntensity;
|
||||
udpOut[17] = (transitionDelay >> 0) & 0xFF;
|
||||
udpOut[18] = (transitionDelay >> 8) & 0xFF;
|
||||
udpOut[19] = effectPalette;
|
||||
|
||||
IPAddress broadcastIp;
|
||||
broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP();
|
||||
broadcastIp = ~uint32_t(WiFi.subnetMask()) | uint32_t(WiFi.gatewayIP());
|
||||
|
||||
notifierUdp.beginPacket(broadcastIp, udpPort);
|
||||
notifierUdp.write(udpOut, WLEDPACKETSIZE);
|
||||
@@ -52,6 +55,7 @@ void notify(byte callMode, bool followUp=false)
|
||||
notificationTwoRequired = (followUp)? false:notifyTwice;
|
||||
}
|
||||
|
||||
|
||||
void arlsLock(uint32_t timeoutMs)
|
||||
{
|
||||
if (!realtimeActive){
|
||||
@@ -59,13 +63,14 @@ void arlsLock(uint32_t timeoutMs)
|
||||
{
|
||||
strip.setPixelColor(i,0,0,0,0);
|
||||
}
|
||||
strip.setMode(0);
|
||||
strip.unlockAll();
|
||||
}
|
||||
realtimeActive = true;
|
||||
realtimeTimeout = millis() + timeoutMs;
|
||||
if (arlsForceMaxBri) strip.setBrightness(255);
|
||||
}
|
||||
|
||||
|
||||
void initE131(){
|
||||
if (WiFi.status() == WL_CONNECTED && e131Enabled)
|
||||
{
|
||||
@@ -76,6 +81,29 @@ void initE131(){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleE131(){
|
||||
//E1.31 protocol support
|
||||
if(e131Enabled) {
|
||||
uint16_t len = e131->parsePacket();
|
||||
if (!len || e131->universe < e131Universe || e131->universe > e131Universe +4) return;
|
||||
len /= 3; //one LED is 3 DMX channels
|
||||
|
||||
uint16_t multipacketOffset = (e131->universe - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
||||
if (ledCount <= multipacketOffset) return;
|
||||
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
int j = i * 3;
|
||||
setRealtimePixel(i + multipacketOffset, e131->data[j], e131->data[j+1], e131->data[j+2], 0);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleNotifications()
|
||||
{
|
||||
//send second notification if enabled
|
||||
@@ -83,153 +111,147 @@ void handleNotifications()
|
||||
notify(notificationSentCallMode,true);
|
||||
}
|
||||
|
||||
//E1.31 protocol support
|
||||
if(e131Enabled) {
|
||||
uint16_t len = e131->parsePacket();
|
||||
if (len && e131->universe == e131Universe) {
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
if (len > ledCount) len = ledCount;
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
int j = i * 3;
|
||||
|
||||
setRealtimePixel(i, e131->data[j], e131->data[j+1], e131->data[j+2], 0);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
handleE131();
|
||||
|
||||
//unlock strip when realtime UDP times out
|
||||
if (realtimeActive && millis() > realtimeTimeout)
|
||||
{
|
||||
strip.unlockAll();
|
||||
//strip.unlockAll();
|
||||
strip.setBrightness(bri);
|
||||
realtimeActive = false;
|
||||
strip.setMode(effectCurrent);
|
||||
//strip.setMode(effectCurrent);
|
||||
realtimeIP[0] = 0;
|
||||
}
|
||||
|
||||
//receive UDP notifications
|
||||
if(udpConnected && (receiveNotifications || receiveDirect)){
|
||||
uint16_t packetSize = notifierUdp.parsePacket();
|
||||
|
||||
//hyperion / raw RGB
|
||||
if (!packetSize && udpRgbConnected) {
|
||||
packetSize = rgbUdp.parsePacket();
|
||||
if (!receiveDirect) return;
|
||||
if (packetSize > 1026 || packetSize < 3) return;
|
||||
realtimeIP = rgbUdp.remoteIP();
|
||||
DEBUG_PRINTLN(rgbUdp.remoteIP());
|
||||
byte udpIn[packetSize];
|
||||
rgbUdp.read(udpIn, packetSize);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
strip.show();
|
||||
return;
|
||||
}
|
||||
if (!udpConnected || !(receiveNotifications || receiveDirect)) return;
|
||||
|
||||
if (packetSize > 1026) return;
|
||||
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
|
||||
uint16_t packetSize = notifierUdp.parsePacket();
|
||||
|
||||
//hyperion / raw RGB
|
||||
if (!packetSize && udpRgbConnected) {
|
||||
packetSize = rgbUdp.parsePacket();
|
||||
if (!receiveDirect) return;
|
||||
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return;
|
||||
realtimeIP = rgbUdp.remoteIP();
|
||||
DEBUG_PRINTLN(rgbUdp.remoteIP());
|
||||
olen = 0;
|
||||
rgbUdp.read(obuf, packetSize);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
||||
{
|
||||
byte udpIn[packetSize];
|
||||
notifierUdp.read(udpIn, packetSize);
|
||||
if (udpIn[0] == 0 && !realtimeActive && receiveNotifications) //wled notifier, block if realtime packets active
|
||||
setRealtimePixel(id, obuf[i], obuf[i+1], obuf[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
strip.show();
|
||||
return;
|
||||
}
|
||||
|
||||
//notifier and UDP realtime
|
||||
if (packetSize > UDP_IN_MAXSIZE) return;
|
||||
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
|
||||
{
|
||||
olen = 0;
|
||||
notifierUdp.read(obuf, packetSize);
|
||||
char* udpIn = obuf;
|
||||
|
||||
//wled notifier, block if realtime packets active
|
||||
if (udpIn[0] == 0 && !realtimeActive && receiveNotifications)
|
||||
{
|
||||
//apply colors from notification
|
||||
if (receiveNotificationColor)
|
||||
{
|
||||
if (receiveNotificationColor)
|
||||
{
|
||||
col[0] = udpIn[3];
|
||||
col[1] = udpIn[4];
|
||||
col[2] = udpIn[5];
|
||||
}
|
||||
if (udpIn[11] > 0 && receiveNotificationColor) //check if sending modules white val is inteded
|
||||
if (udpIn[11] > 0) //check if sending modules white val is inteded
|
||||
{
|
||||
white = udpIn[10];
|
||||
if (udpIn[11] > 1 )
|
||||
col[3] = udpIn[10];
|
||||
if (udpIn[11] > 1)
|
||||
{
|
||||
colSec[0] = udpIn[12];
|
||||
colSec[1] = udpIn[13];
|
||||
colSec[2] = udpIn[14];
|
||||
whiteSec = udpIn[15];
|
||||
colSec[3] = udpIn[15];
|
||||
}
|
||||
}
|
||||
if (udpIn[8] != effectCurrent && receiveNotificationEffects)
|
||||
{
|
||||
effectCurrent = udpIn[8];
|
||||
strip.setMode(effectCurrent);
|
||||
}
|
||||
if (udpIn[9] != effectSpeed && receiveNotificationEffects)
|
||||
{
|
||||
effectSpeed = udpIn[9];
|
||||
strip.setSpeed(effectSpeed);
|
||||
}
|
||||
if (udpIn[11] > 2 && udpIn[16] != effectIntensity && receiveNotificationEffects)
|
||||
{
|
||||
effectIntensity = udpIn[16];
|
||||
strip.setIntensity(effectIntensity);
|
||||
}
|
||||
if (udpIn[11] > 3)
|
||||
{
|
||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||
}
|
||||
if (udpIn[11] > 4 && udpIn[19] != effectPalette && receiveNotificationEffects)
|
||||
{
|
||||
effectPalette = udpIn[19];
|
||||
strip.setPalette(effectPalette);
|
||||
}
|
||||
nightlightActive = udpIn[6];
|
||||
if (!nightlightActive)
|
||||
{
|
||||
if (receiveNotificationBrightness) bri = udpIn[2];
|
||||
colorUpdated(3);
|
||||
}
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize > 1) {
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeActive = false;
|
||||
} else {
|
||||
arlsLock(udpIn[1]*1000);
|
||||
}
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
}
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
//apply effects from notification
|
||||
if (receiveNotificationEffects)
|
||||
{
|
||||
effectCurrent = udpIn[8];
|
||||
effectSpeed = udpIn[9];
|
||||
if (udpIn[11] > 2) effectIntensity = udpIn[16];
|
||||
if (udpIn[11] > 4) effectPalette = udpIn[19];
|
||||
}
|
||||
|
||||
if (udpIn[11] > 3)
|
||||
{
|
||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||
}
|
||||
|
||||
nightlightActive = udpIn[6];
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness) bri = udpIn[2];
|
||||
colorUpdated(3);
|
||||
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize > 1) {
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeActive = false;
|
||||
return;
|
||||
} else {
|
||||
arlsLock(udpIn[1]*1000);
|
||||
}
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
uint16_t pix = i + arlsOffset;
|
||||
@@ -243,5 +265,3 @@ void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -2,6 +2,19 @@
|
||||
* LED methods
|
||||
*/
|
||||
|
||||
void toggleOnOff()
|
||||
{
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
} else
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setAllLeds() {
|
||||
if (!realtimeActive || !arlsForceMaxBri)
|
||||
{
|
||||
@@ -21,59 +34,63 @@ void setAllLeds() {
|
||||
{
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
whiteSecT = whiteSec;
|
||||
colSecT[3] = colSec[3];
|
||||
}
|
||||
if (autoRGBtoRGBW)
|
||||
if (useRGBW && autoRGBtoRGBW)
|
||||
{
|
||||
colorRGBtoRGBW(colT,&whiteT);
|
||||
colorRGBtoRGBW(colSecT,&whiteSecT);
|
||||
colorRGBtoRGBW(colT);
|
||||
colorRGBtoRGBW(colSecT);
|
||||
}
|
||||
if (useGammaCorrectionRGB)
|
||||
{
|
||||
strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]);
|
||||
strip.setSecondaryColor(gamma8[colSecT[0]], gamma8[colSecT[1]], gamma8[colSecT[2]], gamma8[whiteSecT]);
|
||||
strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[colT[3]]);
|
||||
strip.setSecondaryColor(gamma8[colSecT[0]], gamma8[colSecT[1]], gamma8[colSecT[2]], gamma8[colSecT[3]]);
|
||||
} else {
|
||||
strip.setColor(colT[0], colT[1], colT[2], whiteT);
|
||||
strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], whiteSecT);
|
||||
strip.setColor(colT[0], colT[1], colT[2], colT[3]);
|
||||
strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], colSecT[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setLedsStandard()
|
||||
{
|
||||
for (byte i = 0; i<3; i++)
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colOld[i] = col[i];
|
||||
colT[i] = col[i];
|
||||
colSecOld[i] = colSec[i];
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
whiteOld = white;
|
||||
briOld = bri;
|
||||
whiteSecOld = whiteSec;
|
||||
whiteT = white;
|
||||
briT = bri;
|
||||
whiteSecT = whiteSec;
|
||||
setAllLeds();
|
||||
}
|
||||
|
||||
|
||||
bool colorChanged()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
if (col[i] != colIT[i]) return true;
|
||||
if (colSec[i] != colSecIT[i]) return true;
|
||||
}
|
||||
if (white != whiteIT || whiteSec != whiteSecIT) return true;
|
||||
if (bri != briIT) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void colorUpdated(int callMode)
|
||||
{
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (NN)6: fx changed 7: hue 8: preset cycle 9: blynk
|
||||
//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
|
||||
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
|
||||
if (!colorChanged())
|
||||
{
|
||||
if (callMode == 6) notify(6);
|
||||
if (nightlightActive && !nightlightActiveOld && callMode != 3 && callMode != 5)
|
||||
{
|
||||
notify(4); return;
|
||||
}
|
||||
else if (fxChanged) notify(6);
|
||||
return; //no change
|
||||
}
|
||||
if (callMode != 5 && nightlightActive && nightlightFade)
|
||||
@@ -82,14 +99,11 @@ void colorUpdated(int callMode)
|
||||
nightlightDelayMs -= (millis() - nightlightStartTime);
|
||||
nightlightStartTime = millis();
|
||||
}
|
||||
colIT[0] = col[0];
|
||||
colIT[1] = col[1];
|
||||
colIT[2] = col[2];
|
||||
colSecIT[0] = colSec[0];
|
||||
colSecIT[1] = colSec[1];
|
||||
colSecIT[2] = colSec[2];
|
||||
whiteIT = white;
|
||||
whiteSecIT = whiteSec;
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colIT[i] = col[i];
|
||||
colSecIT[i] = colSec[i];
|
||||
}
|
||||
briIT = bri;
|
||||
if (bri > 0) briLast = bri;
|
||||
|
||||
@@ -103,14 +117,11 @@ void colorUpdated(int callMode)
|
||||
|
||||
if (transitionActive)
|
||||
{
|
||||
colOld[0] = colT[0];
|
||||
colOld[1] = colT[1];
|
||||
colOld[2] = colT[2];
|
||||
whiteOld = whiteT;
|
||||
colSecOld[0] = colSecT[0];
|
||||
colSecOld[1] = colSecT[1];
|
||||
colSecOld[2] = colSecT[2];
|
||||
whiteSecOld = whiteSecT;
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colOld[i] = colT[i];
|
||||
colSecOld[i] = colSecT[i];
|
||||
}
|
||||
briOld = briT;
|
||||
tperLast = 0;
|
||||
}
|
||||
@@ -124,6 +135,9 @@ void colorUpdated(int callMode)
|
||||
}
|
||||
|
||||
if (callMode == 8) return;
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
if (espalexaDevice != nullptr) espalexaDevice->setValue(bri);
|
||||
#endif
|
||||
//only update Blynk and mqtt every 2 seconds to reduce lag
|
||||
if (millis() - lastInterfaceUpdate <= 2000)
|
||||
{
|
||||
@@ -133,6 +147,7 @@ void colorUpdated(int callMode)
|
||||
updateInterfaces(callMode);
|
||||
}
|
||||
|
||||
|
||||
void updateInterfaces(uint8_t callMode)
|
||||
{
|
||||
if (callMode != 9 && callMode != 5) updateBlynk();
|
||||
@@ -140,6 +155,7 @@ void updateInterfaces(uint8_t callMode)
|
||||
lastInterfaceUpdate = millis();
|
||||
}
|
||||
|
||||
|
||||
void handleTransitions()
|
||||
{
|
||||
//handle still pending interface update
|
||||
@@ -160,26 +176,20 @@ void handleTransitions()
|
||||
setLedsStandard();
|
||||
return;
|
||||
}
|
||||
if (tper - tperLast < 0.004)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (tper - tperLast < 0.004) return;
|
||||
tperLast = tper;
|
||||
if (fadeTransition)
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
for (byte i = 0; i<3; i++)
|
||||
{
|
||||
colT[i] = colOld[i]+((col[i] - colOld[i])*tper);
|
||||
colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper);
|
||||
}
|
||||
whiteT = whiteOld +((white - whiteOld )*tper);
|
||||
whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper);
|
||||
briT = briOld +((bri - briOld )*tper);
|
||||
colT[i] = colOld[i]+((col[i] - colOld[i])*tper);
|
||||
colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper);
|
||||
}
|
||||
if (fadeTransition) setAllLeds();
|
||||
briT = briOld +((bri - briOld )*tper);
|
||||
|
||||
setAllLeds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleNightlight()
|
||||
{
|
||||
if (nightlightActive)
|
||||
@@ -187,7 +197,6 @@ void handleNightlight()
|
||||
if (!nightlightActiveOld) //init
|
||||
{
|
||||
nightlightStartTime = millis();
|
||||
notify(4);
|
||||
nightlightDelayMs = (int)(nightlightDelayMins*60000);
|
||||
nightlightActiveOld = true;
|
||||
briNlT = bri;
|
||||
@@ -195,7 +204,7 @@ void handleNightlight()
|
||||
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
|
||||
if (nightlightFade)
|
||||
{
|
||||
bri = briNlT+((nightlightTargetBri - briNlT)*nper);
|
||||
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
|
||||
colorUpdated(5);
|
||||
}
|
||||
if (nper >= 1)
|
||||
|
@@ -6,15 +6,15 @@ void handleButton()
|
||||
{
|
||||
if (buttonEnabled)
|
||||
{
|
||||
if (digitalRead(buttonPin) == LOW && !buttonPressedBefore)
|
||||
if (digitalRead(BTNPIN) == LOW && !buttonPressedBefore)
|
||||
{
|
||||
buttonPressedTime = millis();
|
||||
buttonPressedBefore = true;
|
||||
}
|
||||
else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore)
|
||||
else if (digitalRead(BTNPIN) == HIGH && buttonPressedBefore)
|
||||
{
|
||||
delay(15); //debounce
|
||||
if (digitalRead(buttonPin) == HIGH)
|
||||
if (digitalRead(BTNPIN) == HIGH)
|
||||
{
|
||||
if (millis() - buttonPressedTime > 7000) {initAP();}
|
||||
else if (millis() - buttonPressedTime > 700)
|
||||
@@ -25,14 +25,7 @@ void handleButton()
|
||||
else {
|
||||
if (macroButton == 0)
|
||||
{
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
} else
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
}
|
||||
toggleOnOff();
|
||||
colorUpdated(2);
|
||||
} else {
|
||||
applyMacro(macroButton);
|
||||
@@ -51,9 +44,9 @@ void handleButton()
|
||||
auxActiveBefore = true;
|
||||
switch (auxTriggeredState)
|
||||
{
|
||||
case 0: pinMode(auxPin, INPUT); break;
|
||||
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
|
||||
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
|
||||
case 0: pinMode(AUXPIN, INPUT); break;
|
||||
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
|
||||
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
|
||||
}
|
||||
auxStartTime = millis();
|
||||
}
|
||||
@@ -63,9 +56,9 @@ void handleButton()
|
||||
auxActiveBefore = false;
|
||||
switch (auxDefaultState)
|
||||
{
|
||||
case 0: pinMode(auxPin, INPUT); break;
|
||||
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
|
||||
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
|
||||
case 0: pinMode(AUXPIN, INPUT); break;
|
||||
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
|
||||
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -166,6 +166,13 @@ bool checkCountdown()
|
||||
return false;
|
||||
}
|
||||
|
||||
byte weekdayMondayFirst()
|
||||
{
|
||||
byte wd = weekday(local) -1;
|
||||
if (wd == 0) wd = 7;
|
||||
return wd;
|
||||
}
|
||||
|
||||
void checkTimers()
|
||||
{
|
||||
if (lastTimerMinute != minute(local)) //only check once a new minute begins
|
||||
@@ -176,11 +183,11 @@ void checkTimers()
|
||||
if (timerMacro[i] != 0
|
||||
&& (timerHours[i] == hour(local) || timerHours[i] == 24) //if hour is set to 24, activate every hour
|
||||
&& timerMinutes[i] == minute(local)
|
||||
&& timerWeekday[i] >> weekday(local) & 0x01) //timer should activate at current day of week
|
||||
&& (timerWeekday[i] & 0x01) //timer is enabled
|
||||
&& timerWeekday[i] >> weekdayMondayFirst() & 0x01) //timer should activate at current day of week
|
||||
{
|
||||
applyMacro(timerMacro[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,7 @@ void _nixieDisplay(int num[], uint16_t dur[], uint16_t pausedur[], byte cnt)
|
||||
strip.setRange(overlayMin, overlayMax, 0);
|
||||
if (num[nixieClockI] >= 0 && !nixiePause)
|
||||
{
|
||||
strip.setIndividual(num[nixieClockI],((uint32_t)white << 24)| ((uint32_t)colT[0] << 16) | ((uint32_t)colT[1] << 8) | colT[2]);
|
||||
strip.setIndividual(num[nixieClockI],((uint32_t)colT[3] << 24)| ((uint32_t)colT[0] << 16) | ((uint32_t)colT[1] << 8) | colT[2]);
|
||||
strip.unlock(num[nixieClockI]);
|
||||
}
|
||||
if (!nixiePause)
|
||||
@@ -171,9 +171,9 @@ void _overlayAnalogClock()
|
||||
int pix;
|
||||
for (int i = 0; i <= 12; i++)
|
||||
{
|
||||
pix = overlayMin + analogClock12pixel + (overlaySize/12)*i;
|
||||
if (pix > overlayMax) pix = pix - overlayMax;
|
||||
strip.setIndividual(pix,0x00FFAA);
|
||||
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
||||
if (pix > overlayMax) pix -= overlaySize;
|
||||
strip.setIndividual(pix, 0x00FFAA);
|
||||
}
|
||||
}
|
||||
if (!analogClockSecondsTrail) strip.setIndividual(secondPixel, 0xFF0000);
|
||||
@@ -184,7 +184,7 @@ void _overlayAnalogClock()
|
||||
|
||||
void _overlayNixieClock()
|
||||
{
|
||||
#ifdef WLED_FLASH_512K_MODE
|
||||
#ifdef WLED_DISABLE_CRONIXIE
|
||||
if (countdownMode) checkCountdown();
|
||||
#else
|
||||
|
||||
@@ -310,11 +310,11 @@ void _overlayAnalogCountdown()
|
||||
byte pixelCnt = perc*overlaySize;
|
||||
if (analogClock12pixel + pixelCnt > overlayMax)
|
||||
{
|
||||
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
} else
|
||||
{
|
||||
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)whiteSec << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
}
|
||||
}
|
||||
overlayRefreshMs = 998;
|
||||
|
@@ -5,286 +5,76 @@
|
||||
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
|
||||
* https://github.com/probonopd/ESP8266HueEmulator
|
||||
*/
|
||||
|
||||
void alexaInit()
|
||||
{
|
||||
if (alexaEnabled && WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
udpConnected = connectUDP();
|
||||
|
||||
if (udpConnected) alexaInitPages();
|
||||
}
|
||||
}
|
||||
|
||||
void handleAlexa()
|
||||
{
|
||||
if (alexaEnabled && WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
if(udpConnected){
|
||||
// if there’s data available, read a packet
|
||||
int packetSize = alexaUDP.parsePacket();
|
||||
if(packetSize>0) {
|
||||
IPAddress remote = alexaUDP.remoteIP();
|
||||
int len = alexaUDP.read(obuf, 254);
|
||||
if (len > 0) {
|
||||
obuf[len] = 0;
|
||||
}
|
||||
|
||||
if(strstr(obuf,"M-SEARCH") > 0) {
|
||||
if(strstr(obuf,"upnp:rootdevice") > 0 || strstr(obuf,"device:basic:1") > 0) {
|
||||
DEBUG_PRINTLN("Responding search req...");
|
||||
respondToSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void alexaOn()
|
||||
{
|
||||
if (macroAlexaOn == 0)
|
||||
{
|
||||
handleSet((notifyAlexa)?"win&T=1&IN":"win&T=1&NN&IN");
|
||||
} else
|
||||
{
|
||||
applyMacro(macroAlexaOn);
|
||||
}
|
||||
|
||||
server.send(200, "application/json", "[{\"success\":{\"/lights/1/state/on\":true}}]");
|
||||
}
|
||||
|
||||
void alexaOff()
|
||||
{
|
||||
if (macroAlexaOff == 0)
|
||||
{
|
||||
handleSet((notifyAlexa)?"win&T=0&IN":"win&T=0&NN&IN");
|
||||
} else
|
||||
{
|
||||
applyMacro(macroAlexaOff);
|
||||
}
|
||||
|
||||
server.send(200, "application/json", "[{\"success\":{\"/lights/1/state/on\":false}}]");
|
||||
}
|
||||
|
||||
void alexaDim(byte briL)
|
||||
{
|
||||
olen = 0;
|
||||
oappend("[{\"success\":{\"/lights/1/state/bri\":");
|
||||
oappendi(briL);
|
||||
oappend("}}]");
|
||||
|
||||
server.send(200, "application/json", obuf);
|
||||
|
||||
String ct = (notifyAlexa)?"win&IN&A=":"win&NN&IN&A=";
|
||||
if (briL < 255)
|
||||
{
|
||||
ct = ct + (briL+1);
|
||||
} else
|
||||
{
|
||||
ct = ct + (255);
|
||||
}
|
||||
handleSet(ct);
|
||||
}
|
||||
|
||||
void prepareIds() {
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
}
|
||||
|
||||
void respondToSearch() {
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINT("Send resp to ");
|
||||
DEBUG_PRINTLN(alexaUDP.remoteIP());
|
||||
DEBUG_PRINT("Port : ");
|
||||
DEBUG_PRINTLN(alexaUDP.remotePort());
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
void onAlexaChange(byte b, uint32_t color);
|
||||
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
|
||||
olen = 0;
|
||||
oappend(
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"EXT:\r\n"
|
||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||
"LOCATION: http://");
|
||||
oappend(s);
|
||||
oappend(":80/description.xml\r\n"
|
||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
||||
"hue-bridgeid: ");
|
||||
oappend((char*)escapedMac.c_str());
|
||||
oappend("\r\n"
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-");
|
||||
oappend((char*)escapedMac.c_str());
|
||||
oappend("::upnp:rootdevice\r\n" // _uuid::_deviceType
|
||||
"\r\n");
|
||||
|
||||
alexaUDP.beginPacket(alexaUDP.remoteIP(), alexaUDP.remotePort());
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
alexaUDP.write((byte*)obuf, olen);
|
||||
#else
|
||||
alexaUDP.write(obuf);
|
||||
#endif
|
||||
alexaUDP.endPacket();
|
||||
|
||||
DEBUG_PRINTLN("Response sent!");
|
||||
}
|
||||
|
||||
void alexaInitPages() {
|
||||
|
||||
server.on("/description.xml", HTTP_GET, [](){
|
||||
DEBUG_PRINTLN(" # Responding to description.xml ... #\n");
|
||||
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
|
||||
olen = 0;
|
||||
oappend("<?xml version=\"1.0\" ?>"
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
||||
"<URLBase>http://");
|
||||
oappend(s);
|
||||
oappend(":80/</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
||||
"<friendlyName>Philips hue (");
|
||||
oappend(s);
|
||||
oappend(")</friendlyName>"
|
||||
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
||||
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
||||
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
||||
"<modelName>Philips hue bridge 2012</modelName>"
|
||||
"<modelNumber>929000226503</modelNumber>"
|
||||
"<modelURL>http://www.meethue.com</modelURL>"
|
||||
"<serialNumber>");
|
||||
oappend((char*)escapedMac.c_str());
|
||||
oappend("</serialNumber>"
|
||||
"<UDN>uuid:2f402f80-da50-11e1-9b23-");
|
||||
oappend((char*)escapedMac.c_str());
|
||||
oappend("</UDN>"
|
||||
"<presentationURL>index.html</presentationURL>"
|
||||
"<iconList>"
|
||||
" <icon>"
|
||||
" <mimetype>image/png</mimetype>"
|
||||
" <height>48</height>"
|
||||
" <width>48</width>"
|
||||
" <depth>24</depth>"
|
||||
" <url>hue_logo_0.png</url>"
|
||||
" </icon>"
|
||||
" <icon>"
|
||||
" <mimetype>image/png</mimetype>"
|
||||
" <height>120</height>"
|
||||
" <width>120</width>"
|
||||
" <depth>24</depth>"
|
||||
" <url>hue_logo_3.png</url>"
|
||||
" </icon>"
|
||||
"</iconList>"
|
||||
"</device>"
|
||||
"</root>");
|
||||
|
||||
server.send(200, "text/xml", obuf);
|
||||
|
||||
DEBUG_PRINTLN("Sending setup_xml");
|
||||
});
|
||||
|
||||
// openHAB support
|
||||
server.on("/on.html", HTTP_GET, [](){
|
||||
DEBUG_PRINTLN("on req");
|
||||
server.send(200, "text/plain", "turned on");
|
||||
alexaOn();
|
||||
});
|
||||
|
||||
server.on("/off.html", HTTP_GET, [](){
|
||||
DEBUG_PRINTLN("off req");
|
||||
server.send(200, "text/plain", "turned off");
|
||||
alexaOff();
|
||||
});
|
||||
|
||||
server.on("/status.html", HTTP_GET, [](){
|
||||
DEBUG_PRINTLN("Got status request");
|
||||
|
||||
char statrespone[] = "0";
|
||||
if (bri > 0) {
|
||||
statrespone[0] = '1';
|
||||
}
|
||||
server.send(200, "text/plain", statrespone);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
String boolString(bool st)
|
||||
void alexaInit()
|
||||
{
|
||||
return (st)?"true":"false";
|
||||
if (alexaEnabled && WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
if (espalexaDevice == nullptr) //only init once
|
||||
{
|
||||
espalexaDevice = new EspalexaDevice(alexaInvocationName, onAlexaChange);
|
||||
espalexa.addDevice(espalexaDevice);
|
||||
espalexa.begin(&server);
|
||||
} else {
|
||||
espalexaDevice->setName(alexaInvocationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String briForHue(int realBri)
|
||||
void handleAlexa()
|
||||
{
|
||||
realBri--;
|
||||
if (realBri < 0) realBri = 0;
|
||||
return String(realBri);
|
||||
if (!alexaEnabled || WiFi.status() != WL_CONNECTED) return;
|
||||
espalexa.loop();
|
||||
}
|
||||
|
||||
bool handleAlexaApiCall(String req, String body) //basic implementation of Philips hue api functions needed for basic Alexa control
|
||||
void onAlexaChange(byte b, uint32_t color)
|
||||
{
|
||||
DEBUG_PRINTLN("AlexaApiCall");
|
||||
if (req.indexOf("api") <0) return false;
|
||||
DEBUG_PRINTLN("ok");
|
||||
if (body.indexOf("devicetype") > 0) //client wants a hue api username, we dont care and give static
|
||||
{
|
||||
DEBUG_PRINTLN("devType");
|
||||
server.send(200, "application/json", "[{\"success\":{\"username\": \"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]");
|
||||
return true;
|
||||
}
|
||||
if (req.indexOf("state") > 0) //client wants to control light
|
||||
{
|
||||
DEBUG_PRINTLN("ls");
|
||||
if (body.indexOf("bri")>0) {alexaDim(body.substring(body.indexOf("bri") +5).toInt()); return true;}
|
||||
if (body.indexOf("false")>0) {alexaOff(); return true;}
|
||||
alexaOn();
|
||||
|
||||
return true;
|
||||
}
|
||||
if (req.indexOf("lights/1") > 0) //client wants light info
|
||||
{
|
||||
DEBUG_PRINTLN("l1");
|
||||
server.send(200, "application/json", "{\"manufacturername\":\"OpenSource\",\"modelid\":\"LST001\",\"name\":\""+ String(alexaInvocationName) +"\",\"state\":{\"on\":"+ boolString(bri) +",\"hue\":0,\"bri\":"+ briForHue(bri) +",\"sat\":0,\"xy\":[0.00000,0.00000],\"ct\":500,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"swversion\":\"0.1\",\"type\":\"Extended color light\",\"uniqueid\":\"2\"}");
|
||||
|
||||
return true;
|
||||
}
|
||||
if (req.indexOf("lights") > 0) //client wants all lights
|
||||
{
|
||||
DEBUG_PRINTLN("lAll");
|
||||
server.send(200, "application/json", "{\"1\":{\"type\":\"Extended color light\",\"manufacturername\":\"OpenSource\",\"swversion\":\"0.1\",\"name\":\""+ String(alexaInvocationName) +"\",\"uniqueid\":\""+ WiFi.macAddress() +"-2\",\"modelid\":\"LST001\",\"state\":{\"on\":"+ boolString(bri) +",\"bri\":"+ briForHue(bri) +",\"xy\":[0.00000,0.00000],\"colormode\":\"hs\",\"effect\":\"none\",\"ct\":500,\"hue\":0,\"sat\":0,\"alert\":\"none\",\"reachable\":true}}}");
|
||||
return true;
|
||||
}
|
||||
|
||||
//we dont care about other api commands at this time and send empty JSON
|
||||
server.send(200, "application/json", "{}");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool connectUDP(){
|
||||
bool state = false;
|
||||
byte m = espalexaDevice->getLastChangedProperty();
|
||||
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINTLN("Con UDP");
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if(alexaUDP.beginMulticast(ipMulti, portMulti))
|
||||
#else
|
||||
if(alexaUDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti))
|
||||
#endif
|
||||
if (m == 1){ //ON
|
||||
if (!macroAlexaOn)
|
||||
{
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
colorUpdated(10);
|
||||
}
|
||||
} else applyMacro(macroAlexaOn);
|
||||
} else if (m == 2) //OFF
|
||||
{
|
||||
DEBUG_PRINTLN("Con success");
|
||||
state = true;
|
||||
if (!macroAlexaOff)
|
||||
{
|
||||
if (bri > 0)
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(10);
|
||||
}
|
||||
} else applyMacro(macroAlexaOff);
|
||||
} else if (m == 3) //brightness
|
||||
{
|
||||
bri = b;
|
||||
colorUpdated(10);
|
||||
} else //color
|
||||
{
|
||||
col[0] = ((color >> 16) & 0xFF);
|
||||
col[1] = ((color >> 8) & 0xFF);
|
||||
col[2] = (color & 0xFF);
|
||||
if (useRGBW) colorRGBtoRGBW(col);
|
||||
colorUpdated(10);
|
||||
}
|
||||
else{
|
||||
DEBUG_PRINTLN("Con failed");
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
void alexaInit(){}
|
||||
void handleAlexa(){}
|
||||
#endif
|
||||
|
@@ -19,7 +19,7 @@ byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
|
||||
|
||||
void setCronixie()
|
||||
{
|
||||
#ifndef WLED_FLASH_512K_MODE
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
/*
|
||||
* digit purpose index
|
||||
* 0-9 | 0-9 (incl. random)
|
||||
@@ -145,73 +145,72 @@ void setCronixie()
|
||||
|
||||
void _overlayCronixie()
|
||||
{
|
||||
if (countdownMode) checkCountdown();
|
||||
#ifndef WLED_FLASH_512K_MODE
|
||||
|
||||
byte h = hour(local);
|
||||
byte h0 = h;
|
||||
byte m = minute(local);
|
||||
byte s = second(local);
|
||||
byte d = day(local);
|
||||
byte mi = month(local);
|
||||
int y = year(local);
|
||||
//this has to be changed in time for 22nd century
|
||||
y -= 2000; if (y<0) y += 30; //makes countdown work
|
||||
if (countdownMode) checkCountdown();
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
|
||||
byte h = hour(local);
|
||||
byte h0 = h;
|
||||
byte m = minute(local);
|
||||
byte s = second(local);
|
||||
byte d = day(local);
|
||||
byte mi = month(local);
|
||||
int y = year(local);
|
||||
//this has to be changed in time for 22nd century
|
||||
y -= 2000; if (y<0) y += 30; //makes countdown work
|
||||
|
||||
if (useAMPM && !countdownMode)
|
||||
{
|
||||
if (h>12) h-=12;
|
||||
else if (h==0) h+=12;
|
||||
}
|
||||
byte _digitOut[]{10,10,10,10,10,10};
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (dP[i] < 12) _digitOut[i] = dP[i];
|
||||
else {
|
||||
if (dP[i] < 65)
|
||||
if (useAMPM && !countdownMode)
|
||||
{
|
||||
if (h>12) h-=12;
|
||||
else if (h==0) h+=12;
|
||||
}
|
||||
byte _digitOut[]{10,10,10,10,10,10};
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (dP[i] < 12) _digitOut[i] = dP[i];
|
||||
else {
|
||||
if (dP[i] < 65)
|
||||
{
|
||||
switch(dP[i])
|
||||
{
|
||||
switch(dP[i])
|
||||
{
|
||||
case 21: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; i++; break; //HH
|
||||
case 25: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; i++; break; //MM
|
||||
case 31: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; i++; break; //SS
|
||||
case 21: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; i++; break; //HH
|
||||
case 25: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; i++; break; //MM
|
||||
case 31: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; i++; break; //SS
|
||||
|
||||
case 20: _digitOut[i] = h- (h/10)*10; break; //H
|
||||
case 24: _digitOut[i] = m/10; break; //M
|
||||
case 30: _digitOut[i] = s/10; break; //S
|
||||
|
||||
case 43: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //D
|
||||
case 44: _digitOut[i] = d/10; _digitOut[i+1] = d- _digitOut[i]*10; i++; break; //DD
|
||||
case 40: _digitOut[i] = mi/10; _digitOut[i+1] = mi- _digitOut[i]*10; i++; break; //II
|
||||
case 37: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //YY
|
||||
case 39: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //YYYY
|
||||
|
||||
case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
|
||||
case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
|
||||
case 14: _digitOut[i] = (h0>11)?1:0; break; //B
|
||||
}
|
||||
} else
|
||||
case 20: _digitOut[i] = h- (h/10)*10; break; //H
|
||||
case 24: _digitOut[i] = m/10; break; //M
|
||||
case 30: _digitOut[i] = s/10; break; //S
|
||||
|
||||
case 43: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //D
|
||||
case 44: _digitOut[i] = d/10; _digitOut[i+1] = d- _digitOut[i]*10; i++; break; //DD
|
||||
case 40: _digitOut[i] = mi/10; _digitOut[i+1] = mi- _digitOut[i]*10; i++; break; //II
|
||||
case 37: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //YY
|
||||
case 39: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //YYYY
|
||||
|
||||
case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
|
||||
case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
|
||||
case 14: _digitOut[i] = (h0>11)?1:0; break; //B
|
||||
}
|
||||
} else
|
||||
{
|
||||
switch(dP[i])
|
||||
{
|
||||
switch(dP[i])
|
||||
{
|
||||
case 71: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //hh
|
||||
case 75: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //mm
|
||||
case 81: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ss
|
||||
case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
|
||||
case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
|
||||
case 64: _digitOut[i] = (h0>11)?1:10; break; //b
|
||||
case 71: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //hh
|
||||
case 75: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //mm
|
||||
case 81: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ss
|
||||
case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
|
||||
case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
|
||||
case 64: _digitOut[i] = (h0>11)?1:10; break; //b
|
||||
|
||||
case 93: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //d
|
||||
case 94: _digitOut[i] = d/10; _digitOut[i+1] = d- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //dd
|
||||
case 90: _digitOut[i] = mi/10; _digitOut[i+1] = mi- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ii
|
||||
case 87: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //yy
|
||||
case 89: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //yyyy
|
||||
}
|
||||
case 93: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //d
|
||||
case 94: _digitOut[i] = d/10; _digitOut[i+1] = d- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //dd
|
||||
case 90: _digitOut[i] = mi/10; _digitOut[i+1] = mi- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ii
|
||||
case 87: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //yy
|
||||
case 89: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //yyyy
|
||||
}
|
||||
}
|
||||
}
|
||||
strip.setCronixieDigits(_digitOut);
|
||||
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
|
||||
#endif
|
||||
}
|
||||
strip.setCronixieDigits(_digitOut);
|
||||
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -1,34 +1,13 @@
|
||||
/*
|
||||
* Color conversion methods
|
||||
*/
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
|
||||
|
||||
void colorFromUint32(uint32_t in)
|
||||
{
|
||||
//this is only an approximation using WS2812B with gamma correction enabled
|
||||
if (mired > 475)
|
||||
{
|
||||
rgb[0]=255;rgb[1]=199;rgb[2]=92;//500
|
||||
} else if (mired > 425)
|
||||
{
|
||||
rgb[0]=255;rgb[1]=213;rgb[2]=118;//450
|
||||
} else if (mired > 375)
|
||||
{
|
||||
rgb[0]=255;rgb[1]=216;rgb[2]=118;//400
|
||||
} else if (mired > 325)
|
||||
{
|
||||
rgb[0]=255;rgb[1]=234;rgb[2]=140;//350
|
||||
} else if (mired > 275)
|
||||
{
|
||||
rgb[0]=255;rgb[1]=243;rgb[2]=160;//300
|
||||
} else if (mired > 225)
|
||||
{
|
||||
rgb[0]=250;rgb[1]=255;rgb[2]=188;//250
|
||||
} else if (mired > 175)
|
||||
{
|
||||
rgb[0]=247;rgb[1]=255;rgb[2]=215;//200
|
||||
} else
|
||||
{
|
||||
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
|
||||
}
|
||||
col[3] = in >> 24 & 0xFF;
|
||||
col[0] = in >> 16 & 0xFF;
|
||||
col[1] = in >> 8 & 0xFF;
|
||||
col[2] = in & 0xFF;
|
||||
}
|
||||
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
|
||||
@@ -50,6 +29,29 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
|
||||
{
|
||||
//this is only an approximation using WS2812B with gamma correction enabled
|
||||
if (mired > 475) {
|
||||
rgb[0]=255;rgb[1]=199;rgb[2]=92;//500
|
||||
} else if (mired > 425) {
|
||||
rgb[0]=255;rgb[1]=213;rgb[2]=118;//450
|
||||
} else if (mired > 375) {
|
||||
rgb[0]=255;rgb[1]=216;rgb[2]=118;//400
|
||||
} else if (mired > 325) {
|
||||
rgb[0]=255;rgb[1]=234;rgb[2]=140;//350
|
||||
} else if (mired > 275) {
|
||||
rgb[0]=255;rgb[1]=243;rgb[2]=160;//300
|
||||
} else if (mired > 225) {
|
||||
rgb[0]=250;rgb[1]=255;rgb[2]=188;//250
|
||||
} else if (mired > 175) {
|
||||
rgb[0]=247;rgb[1]=255;rgb[2]=215;//200
|
||||
} else {
|
||||
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
|
||||
}
|
||||
}
|
||||
|
||||
void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
{
|
||||
float z = 1.0f - x - y;
|
||||
@@ -59,20 +61,20 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
|
||||
float g = (int)255*(-X * 0.707196f + 1.655397f + Z * 0.036152f);
|
||||
float b = (int)255*(X * 0.051713f - 0.121364f + Z * 1.011530f);
|
||||
if (r > b && r > g && r > 1.0f) {
|
||||
// red is too big
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0f;
|
||||
// red is too big
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0f;
|
||||
} else if (g > b && g > r && g > 1.0f) {
|
||||
// green is too big
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0f;
|
||||
// green is too big
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0f;
|
||||
} else if (b > r && b > g && b > 1.0f) {
|
||||
// blue is too big
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0f;
|
||||
// blue is too big
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0f;
|
||||
}
|
||||
// Apply gamma correction
|
||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
|
||||
@@ -80,33 +82,43 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
|
||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
|
||||
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
if (r > 1.0f) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0f;
|
||||
}
|
||||
// red is biggest
|
||||
if (r > 1.0f) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0f;
|
||||
}
|
||||
} else if (g > b && g > r) {
|
||||
// green is biggest
|
||||
if (g > 1.0f) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0f;
|
||||
}
|
||||
// green is biggest
|
||||
if (g > 1.0f) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0f;
|
||||
}
|
||||
} else if (b > r && b > g) {
|
||||
// blue is biggest
|
||||
if (b > 1.0f) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0f;
|
||||
}
|
||||
// blue is biggest
|
||||
if (b > 1.0f) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0f;
|
||||
}
|
||||
}
|
||||
rgb[0] = 255.0*r;
|
||||
rgb[1] = 255.0*g;
|
||||
rgb[2] = 255.0*b;
|
||||
}
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, byte* wht, char* in)
|
||||
void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
{
|
||||
float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f;
|
||||
float Y = rgb[0] * 0.283881f + rgb[1] * 0.668433f + rgb[2] * 0.047685f;
|
||||
float Z = rgb[0] * 0.000088f + rgb[1] * 0.072310f + rgb[2] * 0.986039f;
|
||||
xy[0] = X / (X + Y + Z);
|
||||
xy[1] = Y / (X + Y + Z);
|
||||
}
|
||||
#endif
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, char* in)
|
||||
{
|
||||
if (in[0] == 0) return;
|
||||
char first = in[0];
|
||||
@@ -120,21 +132,12 @@ void colorFromDecOrHexString(byte* rgb, byte* wht, char* in)
|
||||
c = strtoul(in, NULL, 10);
|
||||
}
|
||||
|
||||
*wht = (c >> 24) & 0xFF;
|
||||
rgb[3] = (c >> 24) & 0xFF;
|
||||
rgb[0] = (c >> 16) & 0xFF;
|
||||
rgb[1] = (c >> 8) & 0xFF;
|
||||
rgb[2] = c & 0xFF;
|
||||
}
|
||||
|
||||
void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
{
|
||||
float X = rgb[0] * 0.664511f + rgb[1] * 0.154324f + rgb[2] * 0.162028f;
|
||||
float Y = rgb[0] * 0.283881f + rgb[1] * 0.668433f + rgb[2] * 0.047685f;
|
||||
float Z = rgb[0] * 0.000088f + rgb[1] * 0.072310f + rgb[2] * 0.986039f;
|
||||
xy[0] = X / (X + Y + Z);
|
||||
xy[1] = Y / (X + Y + Z);
|
||||
}
|
||||
|
||||
float minf (float v, float w)
|
||||
{
|
||||
if (w > v) return v;
|
||||
@@ -147,12 +150,11 @@ float maxf (float v, float w)
|
||||
return v;
|
||||
}
|
||||
|
||||
void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw (http://codewelt.com/rgbw)
|
||||
void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw)
|
||||
{
|
||||
float low = minf(rgb[0],minf(rgb[1],rgb[2]));
|
||||
float high = maxf(rgb[0],maxf(rgb[1],rgb[2]));
|
||||
if (high < 0.1f) return;
|
||||
float sat = 255.0f * ((high - low) / high);
|
||||
*wht = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Sync to Philips hue lights
|
||||
*/
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
void handleHue()
|
||||
{
|
||||
if (huePollingEnabled && WiFi.status() == WL_CONNECTED && hueClient != NULL)
|
||||
@@ -206,4 +206,7 @@ String getJsonValue(String* req, String key)
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#else
|
||||
void handleHue(){}
|
||||
bool setupHue(){return false;}
|
||||
#endif
|
||||
|
@@ -7,19 +7,24 @@ byte blSat = 255;
|
||||
|
||||
void initBlynk(const char* auth)
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (WiFi.status() != WL_CONNECTED) return;
|
||||
blynkEnabled = (auth[0] != 0);
|
||||
if (blynkEnabled) Blynk.config(auth);
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleBlynk()
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (WiFi.status() == WL_CONNECTED && blynkEnabled)
|
||||
Blynk.run();
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateBlynk()
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (onlyAP) return;
|
||||
Blynk.virtualWrite(V0, bri);
|
||||
//we need a RGB -> HSB convert here
|
||||
@@ -29,26 +34,28 @@ void updateBlynk()
|
||||
Blynk.virtualWrite(V6, effectIntensity);
|
||||
Blynk.virtualWrite(V7, nightlightActive);
|
||||
Blynk.virtualWrite(V8, notifyDirect);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
BLYNK_WRITE(V0)
|
||||
{
|
||||
bri = param.asInt();//bri
|
||||
colorUpdated(9);
|
||||
bri = param.asInt();//bri
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V1)
|
||||
{
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V2)
|
||||
{
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V3)
|
||||
@@ -58,23 +65,20 @@ BLYNK_WRITE(V3)
|
||||
|
||||
BLYNK_WRITE(V4)
|
||||
{
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
strip.setMode(effectCurrent);
|
||||
colorUpdated(6);
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V5)
|
||||
{
|
||||
effectSpeed = param.asInt();//sx
|
||||
strip.setSpeed(effectSpeed);
|
||||
colorUpdated(6);
|
||||
effectSpeed = param.asInt();//sx
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V6)
|
||||
{
|
||||
effectIntensity = param.asInt();//ix
|
||||
strip.setIntensity(effectIntensity);
|
||||
colorUpdated(6);
|
||||
effectIntensity = param.asInt();//ix
|
||||
colorUpdated(9);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V7)
|
||||
@@ -86,4 +90,4 @@ BLYNK_WRITE(V8)
|
||||
{
|
||||
notifyDirect = (param.asInt()>0); //send notifications
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -2,10 +2,12 @@
|
||||
* MQTT communication protocol for home automation
|
||||
*/
|
||||
|
||||
#define WLED_MQTT_PORT 1883
|
||||
|
||||
void parseMQTTBriPayload(char* payload)
|
||||
{
|
||||
if (strcmp(payload, "ON") == 0) {bri = briLast; colorUpdated(1);}
|
||||
else if (strcmp(payload, "T" ) == 0) {handleSet("win&T=2");}
|
||||
else if (strcmp(payload, "T" ) == 0) {toggleOnOff(); colorUpdated(1);}
|
||||
else {
|
||||
uint8_t in = strtoul(payload, NULL, 10);
|
||||
if (in == 0 && bri > 0) briLast = bri;
|
||||
@@ -14,6 +16,7 @@ void parseMQTTBriPayload(char* payload)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void callbackMQTT(char* topic, byte* payload, unsigned int length) {
|
||||
|
||||
DEBUG_PRINT("MQTT callb rec: ");
|
||||
@@ -24,7 +27,7 @@ void callbackMQTT(char* topic, byte* payload, unsigned int length) {
|
||||
|
||||
if (strstr(topic, "/col"))
|
||||
{
|
||||
colorFromDecOrHexString(col, &white, (char*)payload);
|
||||
colorFromDecOrHexString(col, (char*)payload);
|
||||
colorUpdated(1);
|
||||
} else if (strstr(topic, "/api"))
|
||||
{
|
||||
@@ -37,6 +40,7 @@ void callbackMQTT(char* topic, byte* payload, unsigned int length) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void publishMQTT()
|
||||
{
|
||||
if (mqtt == NULL) return;
|
||||
@@ -51,19 +55,20 @@ void publishMQTT()
|
||||
strcat(subuf, "/g");
|
||||
mqtt->publish(subuf, s);
|
||||
|
||||
sprintf(s, "#%X", white*16777216 + col[0]*65536 + col[1]*256 + col[2]);
|
||||
sprintf(s, "#%X", col[3]*16777216 + col[0]*65536 + col[1]*256 + col[2]);
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/c");
|
||||
mqtt->publish(subuf, s);
|
||||
|
||||
//if you want to use this, increase the MQTT buffer in PubSubClient.h to 350+
|
||||
//it will publish the API response to MQTT
|
||||
/*XML_response(false);
|
||||
/*XML_response(false, false);
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/v");
|
||||
mqtt->publish(subuf, obuf);*/
|
||||
}
|
||||
|
||||
|
||||
bool reconnectMQTT()
|
||||
{
|
||||
if (mqtt->connect(escapedMac.c_str()))
|
||||
@@ -93,10 +98,13 @@ bool reconnectMQTT()
|
||||
strcat(subuf, "/api");
|
||||
mqtt->subscribe(subuf);
|
||||
}
|
||||
|
||||
publishMQTT();
|
||||
}
|
||||
return mqtt->connected();
|
||||
}
|
||||
|
||||
|
||||
bool initMQTT()
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED) return false;
|
||||
@@ -105,15 +113,16 @@ bool initMQTT()
|
||||
IPAddress mqttIP;
|
||||
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
||||
{
|
||||
mqtt->setServer(mqttIP,1883);
|
||||
mqtt->setServer(mqttIP, WLED_MQTT_PORT);
|
||||
} else {
|
||||
mqtt->setServer(mqttServer,1883);
|
||||
mqtt->setServer(mqttServer, WLED_MQTT_PORT);
|
||||
}
|
||||
mqtt->setCallback(callbackMQTT);
|
||||
DEBUG_PRINTLN("MQTT ready.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void handleMQTT()
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED || !mqttInit) return;
|
||||
|
@@ -87,6 +87,22 @@ void initServer()
|
||||
serveMessage(200,"Security settings saved.","Rebooting now... (takes ~20 seconds, wait for auto-redirect)",139);
|
||||
reset();
|
||||
});
|
||||
|
||||
server.on("/json", HTTP_ANY, [](){
|
||||
server.send(500, "application/json", "{\"error\":\"Not implemented\"}");
|
||||
});
|
||||
|
||||
server.on("/json/effects", HTTP_GET, [](){
|
||||
server.setContentLength(strlen_P(JSON_mode_names));
|
||||
server.send(200, "application/json", "");
|
||||
server.sendContent_P(JSON_mode_names);
|
||||
});
|
||||
|
||||
server.on("/json/palettes", HTTP_GET, [](){
|
||||
server.setContentLength(strlen_P(JSON_palette_names));
|
||||
server.send(200, "application/json", "");
|
||||
server.sendContent_P(JSON_palette_names);
|
||||
});
|
||||
|
||||
server.on("/version", HTTP_GET, [](){
|
||||
server.send(200, "text/plain", (String)VERSION);
|
||||
@@ -101,9 +117,16 @@ void initServer()
|
||||
});
|
||||
|
||||
server.on("/power", HTTP_GET, [](){
|
||||
String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness());
|
||||
val += "mA currently";
|
||||
serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254);
|
||||
String val = "";
|
||||
if (strip.currentMilliamps == 0)
|
||||
{
|
||||
val = "Power calculation disabled";
|
||||
} else
|
||||
{
|
||||
val += (String)strip.currentMilliamps;
|
||||
val += "mA currently";
|
||||
}
|
||||
serveMessage(200, val, "This is just an estimate (does not account for factors like wire resistance). It is NOT a measurement!", 254);
|
||||
});
|
||||
|
||||
server.on("/u", HTTP_GET, [](){
|
||||
@@ -113,7 +136,7 @@ void initServer()
|
||||
});
|
||||
|
||||
server.on("/teapot", HTTP_GET, [](){
|
||||
serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254);
|
||||
serveMessage(418, "418. I'm a teapot.", "(Tangible Embedded Advanced Project Of Twinkling)", 254);
|
||||
});
|
||||
|
||||
server.on("/build", HTTP_GET, [](){
|
||||
@@ -132,7 +155,13 @@ void initServer()
|
||||
server.on("/list", HTTP_GET, handleFileList);
|
||||
#endif
|
||||
//init ota page
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
httpUpdater.setup(&server);
|
||||
#else
|
||||
server.on("/update", HTTP_GET, [](){
|
||||
serveMessage(500, "Not implemented", "OTA updates are unsupported in this build.", 254);
|
||||
});
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
server.on("/edit", HTTP_GET, [](){
|
||||
@@ -157,6 +186,17 @@ void initServer()
|
||||
DEBUG_PRINTLN("URI: " + server.uri());
|
||||
DEBUG_PRINTLN("Body: " + server.arg(0));
|
||||
|
||||
//make API CORS compatible
|
||||
if (server.method() == HTTP_OPTIONS)
|
||||
{
|
||||
server.sendHeader("Access-Control-Allow-Origin", "*");
|
||||
server.sendHeader("Access-Control-Max-Age", "10000");
|
||||
server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
|
||||
server.sendHeader("Access-Control-Allow-Headers", "*");
|
||||
server.send(200);
|
||||
return;
|
||||
}
|
||||
|
||||
//workaround for subpage issue
|
||||
if (server.uri().length() == 1)
|
||||
{
|
||||
@@ -165,7 +205,9 @@ void initServer()
|
||||
}
|
||||
|
||||
if(!handleSet(server.uri())){
|
||||
if(!handleAlexaApiCall(server.uri(),server.arg(0)))
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
if(!espalexa.handleAlexaApiCall(server.uri(),server.arg(0)))
|
||||
#endif
|
||||
server.send(404, "text/plain", "Not Found");
|
||||
}
|
||||
});
|
||||
@@ -179,43 +221,6 @@ void initServer()
|
||||
#endif
|
||||
}
|
||||
|
||||
void buildCssColorString()
|
||||
{
|
||||
String cs[]={"","","","","",""};
|
||||
switch (currentTheme)
|
||||
{
|
||||
default: cs[0]="D9B310"; cs[1]="0B3C5D"; cs[2]="1D2731"; cs[3]="328CC1"; cs[4]="000"; cs[5]="328CC1"; break; //night
|
||||
case 1: cs[0]="eee"; cs[1]="ddd"; cs[2]="b9b9b9"; cs[3]="049"; cs[4]="777"; cs[5]="049"; break; //modern
|
||||
case 2: cs[0]="abc"; cs[1]="fff"; cs[2]="ddd"; cs[3]="000"; cs[4]="0004"; cs[5]="000"; break; //bright
|
||||
case 3: cs[0]="c09f80"; cs[1]="d7cec7"; cs[2]="76323f"; cs[3]="888"; cs[4]="3334"; cs[5]="888"; break; //wine
|
||||
case 4: cs[0]="3cc47c"; cs[1]="828081"; cs[2]="d9a803"; cs[3]="1e392a"; cs[4]="000a"; cs[5]="1e392a"; break; //electric
|
||||
case 5: cs[0]="57bc90"; cs[1]="a5a5af"; cs[2]="015249"; cs[3]="88c9d4"; cs[4]="0004"; cs[5]="88c9d4"; break; //mint
|
||||
case 6: cs[0]="f7c331"; cs[1]="dcc7aa"; cs[2]="6b7a8f"; cs[3]="f7882f"; cs[4]="0007"; cs[5]="f7882f"; break; //amber
|
||||
case 7: cs[0]="fc3"; cs[1]="124"; cs[2]="334"; cs[3]="f1d"; cs[4]="f00"; cs[5]="f1d"; break;//club
|
||||
case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air
|
||||
case 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie
|
||||
case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal
|
||||
case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64
|
||||
case 12: cs[0]="fbe8a6"; cs[1]="d2fdff"; cs[2]="b4dfe5"; cs[3]="f4976c"; cs[4]=""; cs[5]="303c6c"; break; //c64
|
||||
case 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end
|
||||
case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom
|
||||
}
|
||||
cssColorString="<style>:root{--aCol:#";
|
||||
cssColorString+=cs[0];
|
||||
cssColorString+=";--bCol:#";
|
||||
cssColorString+=cs[1];
|
||||
cssColorString+=";--cCol:#";
|
||||
cssColorString+=cs[2];
|
||||
cssColorString+=";--dCol:#";
|
||||
cssColorString+=cs[3];
|
||||
cssColorString+=";--sCol:#";
|
||||
cssColorString+=cs[4];
|
||||
cssColorString+=";--tCol:#";
|
||||
cssColorString+=cs[5];
|
||||
cssColorString+=";--cFn:";
|
||||
cssColorString+=cssFont;
|
||||
cssColorString+=";}";
|
||||
}
|
||||
|
||||
void serveIndexOrWelcome()
|
||||
{
|
||||
@@ -247,36 +252,52 @@ void serveRealtimeError(bool settings)
|
||||
server.send(200, "text/plain", mesg);
|
||||
}
|
||||
|
||||
|
||||
void getCSSColors()
|
||||
{
|
||||
char cs[6][9];
|
||||
getThemeColors(cs);
|
||||
oappend("<style>:root{--aCol:#"); oappend(cs[0]);
|
||||
oappend(";--bCol:#"); oappend(cs[1]);
|
||||
oappend(";--cCol:#"); oappend(cs[2]);
|
||||
oappend(";--dCol:#"); oappend(cs[3]);
|
||||
oappend(";--sCol:#"); oappend(cs[4]);
|
||||
oappend(";--tCol:#"); oappend(cs[5]);
|
||||
oappend(";--cFn:"); oappend(cssFont);
|
||||
oappend(";}");
|
||||
}
|
||||
|
||||
|
||||
void serveIndex()
|
||||
{
|
||||
bool serveMobile = false;
|
||||
if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent"));
|
||||
else if (uiConfiguration == 2) serveMobile = true;
|
||||
|
||||
if (!realtimeActive || enableRealtimeUI) //do not serve while receiving realtime
|
||||
if (realtimeActive && !enableRealtimeUI) //do not serve while receiving realtime
|
||||
{
|
||||
if (serveMobile)
|
||||
{
|
||||
server.setContentLength(strlen_P(PAGE_indexM));
|
||||
server.send(200, "text/html", "");
|
||||
server.sendContent_P(PAGE_indexM);
|
||||
} else
|
||||
{
|
||||
server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3));
|
||||
server.send(200, "text/html", "");
|
||||
server.sendContent_P(PAGE_index0);
|
||||
server.sendContent(cssColorString);
|
||||
server.sendContent_P(PAGE_index1);
|
||||
server.sendContent_P(PAGE_index2);
|
||||
server.sendContent_P(PAGE_index3);
|
||||
}
|
||||
} else {
|
||||
serveRealtimeError(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//error message is not gzipped
|
||||
#ifdef WLED_DISABLE_MOBILE_UI
|
||||
if (!serveMobile) server.sendHeader("Content-Encoding","gzip");
|
||||
#else
|
||||
server.sendHeader("Content-Encoding","gzip");
|
||||
#endif
|
||||
|
||||
server.send_P(200, "text/html",
|
||||
(serveMobile) ? PAGE_indexM : PAGE_index0,
|
||||
(serveMobile) ? PAGE_indexM_L : PAGE_index0_L);
|
||||
}
|
||||
|
||||
|
||||
void serveMessage(int code, String headl, String subl="", int optionType)
|
||||
{
|
||||
olen = 0;
|
||||
getCSSColors();
|
||||
|
||||
String messageBody = "<h2>";
|
||||
messageBody += headl;
|
||||
messageBody += "</h2>";
|
||||
@@ -298,69 +319,72 @@ void serveMessage(int code, String headl, String subl="", int optionType)
|
||||
messageBody += "<script>setTimeout(RP," + String((optionType-120)*1000) + ")</script>";
|
||||
}
|
||||
messageBody += "</body></html>";
|
||||
server.setContentLength(strlen_P(PAGE_msg0) + cssColorString.length() + strlen_P(PAGE_msg1) + messageBody.length());
|
||||
server.setContentLength(strlen_P(PAGE_msg0) + olen + strlen_P(PAGE_msg1) + messageBody.length());
|
||||
server.send(code, "text/html", "");
|
||||
server.sendContent_P(PAGE_msg0);
|
||||
server.sendContent(cssColorString);
|
||||
server.sendContent(obuf);
|
||||
server.sendContent_P(PAGE_msg1);
|
||||
server.sendContent(messageBody);
|
||||
}
|
||||
|
||||
|
||||
void serveSettings(byte subPage)
|
||||
{
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
|
||||
if (!realtimeActive || enableRealtimeUI) //do not serve while receiving realtime
|
||||
{
|
||||
#ifdef WLED_FLASH_512K_MODE //disable welcome page if not enough storage
|
||||
if (subPage == 255) {serveIndex(); return;}
|
||||
#endif
|
||||
|
||||
int pl0, pl1;
|
||||
switch (subPage)
|
||||
{
|
||||
case 1: pl0 = strlen_P(PAGE_settings_wifi0); pl1 = strlen_P(PAGE_settings_wifi1); break;
|
||||
case 2: pl0 = strlen_P(PAGE_settings_leds0); pl1 = strlen_P(PAGE_settings_leds1); break;
|
||||
case 3: pl0 = strlen_P(PAGE_settings_ui0); pl1 = strlen_P(PAGE_settings_ui1); break;
|
||||
case 4: pl0 = strlen_P(PAGE_settings_sync0); pl1 = strlen_P(PAGE_settings_sync1); break;
|
||||
case 5: pl0 = strlen_P(PAGE_settings_time0); pl1 = strlen_P(PAGE_settings_time1); break;
|
||||
case 6: pl0 = strlen_P(PAGE_settings_sec0); pl1 = strlen_P(PAGE_settings_sec1); break;
|
||||
case 255: pl0 = strlen_P(PAGE_welcome0); pl1 = strlen_P(PAGE_welcome1); break;
|
||||
default: pl0 = strlen_P(PAGE_settings0); pl1 = strlen_P(PAGE_settings1);
|
||||
}
|
||||
|
||||
getSettingsJS(subPage);
|
||||
int sCssLength = (subPage >0 && subPage <7)?strlen_P(PAGE_settingsCss):0;
|
||||
|
||||
server.setContentLength(pl0 + cssColorString.length() + olen + sCssLength + pl1);
|
||||
server.send(200, "text/html", "");
|
||||
|
||||
switch (subPage)
|
||||
{
|
||||
case 1: server.sendContent_P(PAGE_settings_wifi0); break;
|
||||
case 2: server.sendContent_P(PAGE_settings_leds0); break;
|
||||
case 3: server.sendContent_P(PAGE_settings_ui0); break;
|
||||
case 4: server.sendContent_P(PAGE_settings_sync0); break;
|
||||
case 5: server.sendContent_P(PAGE_settings_time0); break;
|
||||
case 6: server.sendContent_P(PAGE_settings_sec0); break;
|
||||
case 255: server.sendContent_P(PAGE_welcome0); break;
|
||||
default: server.sendContent_P(PAGE_settings0);
|
||||
}
|
||||
server.sendContent(obuf);
|
||||
server.sendContent(cssColorString);
|
||||
if (subPage >0 && subPage <7) server.sendContent_P(PAGE_settingsCss);
|
||||
switch (subPage)
|
||||
{
|
||||
case 1: server.sendContent_P(PAGE_settings_wifi1); break;
|
||||
case 2: server.sendContent_P(PAGE_settings_leds1); break;
|
||||
case 3: server.sendContent_P(PAGE_settings_ui1); break;
|
||||
case 4: server.sendContent_P(PAGE_settings_sync1); break;
|
||||
case 5: server.sendContent_P(PAGE_settings_time1); break;
|
||||
case 6: server.sendContent_P(PAGE_settings_sec1); break;
|
||||
case 255: server.sendContent_P(PAGE_welcome1); break;
|
||||
default: server.sendContent_P(PAGE_settings1);
|
||||
}
|
||||
} else {
|
||||
serveRealtimeError(true);
|
||||
}
|
||||
}
|
||||
if (realtimeActive && !enableRealtimeUI) //do not serve while receiving realtime
|
||||
{
|
||||
serveRealtimeError(true);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef WLED_DISABLE_MOBILE_UI //disable welcome page if not enough storage
|
||||
if (subPage == 255) {serveIndex(); return;}
|
||||
#endif
|
||||
|
||||
int pl0, pl1;
|
||||
switch (subPage) //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage
|
||||
{
|
||||
case 1: pl0 = strlen_P(PAGE_settings_wifi0); pl1 = strlen_P(PAGE_settings_wifi1); break;
|
||||
case 2: pl0 = strlen_P(PAGE_settings_leds0); pl1 = strlen_P(PAGE_settings_leds1); break;
|
||||
case 3: pl0 = strlen_P(PAGE_settings_ui0); pl1 = strlen_P(PAGE_settings_ui1); break;
|
||||
case 4: pl0 = strlen_P(PAGE_settings_sync0); pl1 = strlen_P(PAGE_settings_sync1); break;
|
||||
case 5: pl0 = strlen_P(PAGE_settings_time0); pl1 = strlen_P(PAGE_settings_time1); break;
|
||||
case 6: pl0 = strlen_P(PAGE_settings_sec0); pl1 = strlen_P(PAGE_settings_sec1); break;
|
||||
case 255: pl0 = strlen_P(PAGE_welcome0); pl1 = strlen_P(PAGE_welcome1); break;
|
||||
default: pl0 = strlen_P(PAGE_settings0); pl1 = strlen_P(PAGE_settings1);
|
||||
}
|
||||
|
||||
uint16_t sCssLength = (subPage >0 && subPage <7)?strlen_P(PAGE_settingsCss):0;
|
||||
|
||||
getSettingsJS(subPage);
|
||||
|
||||
getCSSColors();
|
||||
|
||||
server.setContentLength(pl0 + olen + sCssLength + pl1);
|
||||
server.send(200, "text/html", "");
|
||||
|
||||
switch (subPage)
|
||||
{
|
||||
case 1: server.sendContent_P(PAGE_settings_wifi0); break;
|
||||
case 2: server.sendContent_P(PAGE_settings_leds0); break;
|
||||
case 3: server.sendContent_P(PAGE_settings_ui0 ); break;
|
||||
case 4: server.sendContent_P(PAGE_settings_sync0); break;
|
||||
case 5: server.sendContent_P(PAGE_settings_time0); break;
|
||||
case 6: server.sendContent_P(PAGE_settings_sec0 ); break;
|
||||
case 255: server.sendContent_P(PAGE_welcome0 ); break;
|
||||
default: server.sendContent_P(PAGE_settings0 );
|
||||
}
|
||||
server.sendContent(obuf);
|
||||
|
||||
if (subPage >0 && subPage <7) server.sendContent_P(PAGE_settingsCss);
|
||||
switch (subPage)
|
||||
{
|
||||
case 1: server.sendContent_P(PAGE_settings_wifi1); break;
|
||||
case 2: server.sendContent_P(PAGE_settings_leds1); break;
|
||||
case 3: server.sendContent_P(PAGE_settings_ui1 ); break;
|
||||
case 4: server.sendContent_P(PAGE_settings_sync1); break;
|
||||
case 5: server.sendContent_P(PAGE_settings_time1); break;
|
||||
case 6: server.sendContent_P(PAGE_settings_sec1 ); break;
|
||||
case 255: server.sendContent_P(PAGE_welcome1 ); break;
|
||||
default: server.sendContent_P(PAGE_settings1 );
|
||||
}
|
||||
}
|
||||
|
155
wled00/wled19_ir.ino
Normal file
155
wled00/wled19_ir.ino
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Infrared sensor support for generic 24 key RGB remote
|
||||
*/
|
||||
|
||||
#if defined(WLED_DISABLE_INFRARED) || defined(ARDUINO_ARCH_ESP32)
|
||||
void handleIR(){}
|
||||
#else
|
||||
|
||||
IRrecv* irrecv;
|
||||
//change pin in NpbWrapper.h
|
||||
|
||||
decode_results results;
|
||||
|
||||
unsigned long irCheckedTime = 0;
|
||||
uint32_t lastValidCode = 0;
|
||||
uint16_t irTimesRepeated = 0;
|
||||
|
||||
|
||||
//Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control
|
||||
//IR codes themselves can be defined directly after "case" or in "ir_codes.h"
|
||||
bool decodeIRCustom(uint32_t code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
//just examples, feel free to modify or remove
|
||||
case IRCUSTOM_ONOFF : toggleOnOff(); break;
|
||||
case IRCUSTOM_MACRO1 : applyMacro(1); break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(2); //don't update color again if we apply macro, it already does it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//relatively change brightness, minumum A=5
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary =0)
|
||||
{
|
||||
int16_t new_val = (int16_t) *property + amount;
|
||||
if (new_val > 0xFF) new_val = 0xFF;
|
||||
else if (new_val < lowerBoundary) new_val = lowerBoundary;
|
||||
*property = new_val;
|
||||
}
|
||||
|
||||
|
||||
void decodeIR(uint32_t code)
|
||||
{
|
||||
if (code == 0xFFFFFFFF) //repeated code, continue brightness up/down
|
||||
{
|
||||
irTimesRepeated++;
|
||||
if (lastValidCode == IR24_BRIGHTER)
|
||||
{
|
||||
relativeChange(&bri, 10); colorUpdated(2);
|
||||
}
|
||||
else if (lastValidCode == IR24_DARKER)
|
||||
{
|
||||
relativeChange(&bri, -10, 5); colorUpdated(2);
|
||||
}
|
||||
else if (lastValidCode == IR24_ON && irTimesRepeated > 7)
|
||||
{
|
||||
nightlightActive = true;
|
||||
nightlightStartTime = millis();
|
||||
colorUpdated(2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
lastValidCode = 0; irTimesRepeated = 0;
|
||||
|
||||
if (decodeIRCustom(code)) return;
|
||||
if (code > 0xFFFFFF) return; //invalid code
|
||||
else if (code > 0xFF0000) decodeIR44(code); //is in 44-key remote range
|
||||
else if (code > 0xF70000 && code < 0xF80000) decodeIR24(code); //is in 24-key remote range
|
||||
//code <= 0xF70000 also invalid
|
||||
}
|
||||
|
||||
|
||||
void decodeIR24(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_ON : bri = briLast; break;
|
||||
case IR24_RED : colorFromUint32(COLOR_RED); break;
|
||||
case IR24_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR24_ORANGE : colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR24_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR24_YELLOW : colorFromUint32(COLOR_YELLOW); break;
|
||||
case IR24_GREEN : colorFromUint32(COLOR_GREEN); break;
|
||||
case IR24_GREENISH : colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR24_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR24_CYAN : colorFromUint32(COLOR_CYAN); break;
|
||||
case IR24_AQUA : colorFromUint32(COLOR_AQUA); break;
|
||||
case IR24_BLUE : colorFromUint32(COLOR_BLUE); break;
|
||||
case IR24_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR24_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
|
||||
case IR24_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
|
||||
case IR24_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
|
||||
case IR24_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
|
||||
void decodeIR44(uint32_t code)
|
||||
{
|
||||
//not implemented for now
|
||||
}
|
||||
|
||||
|
||||
void initIR()
|
||||
{
|
||||
if (irEnabled)
|
||||
{
|
||||
irrecv = new IRrecv(IR_PIN);
|
||||
irrecv->enableIRIn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleIR()
|
||||
{
|
||||
if (irEnabled && millis() - irCheckedTime > 120)
|
||||
{
|
||||
irCheckedTime = millis();
|
||||
if (irEnabled)
|
||||
{
|
||||
if (irrecv == NULL)
|
||||
{
|
||||
initIR(); return;
|
||||
}
|
||||
|
||||
if (irrecv->decode(&results))
|
||||
{
|
||||
Serial.print("IR recv\r\n0x");
|
||||
Serial.println((uint32_t)results.value, HEX);
|
||||
Serial.println();
|
||||
decodeIR(results.value);
|
||||
irrecv->resume();
|
||||
}
|
||||
} else if (irrecv != NULL)
|
||||
{
|
||||
irrecv->disableIRIn();
|
||||
delete irrecv; irrecv = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user