Merge branch 'master' into dev
This commit is contained in:
commit
1a80439825
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
github: [Aircoookie]
|
||||||
|
custom: ['https://paypal.me/Aircoookie']
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -2,6 +2,36 @@
|
|||||||
|
|
||||||
### Builds after release 0.12.0
|
### Builds after release 0.12.0
|
||||||
|
|
||||||
|
#### Build 2106140
|
||||||
|
|
||||||
|
- Updated main logo
|
||||||
|
- Reduced flash usage by 0.8kB by using 8-bit instead of 32-bit PNGs for welcome and 404 pages
|
||||||
|
- Added a check to stop Alexa reporting an error if state set by macro differs from the expected state
|
||||||
|
|
||||||
|
#### Build 2106100
|
||||||
|
|
||||||
|
- Added support for multiple buttons with various types (PR #1977)
|
||||||
|
- Fixed infinite playlists (PR #2020)
|
||||||
|
- Added `r` to playlist object, allows for shuffle regardless of the `repeat` value
|
||||||
|
- Improved accuracy of NTP time sync
|
||||||
|
- Added possibility for WLED UDP sync to sync system time
|
||||||
|
- Improved UDP sync accuracy, if both sender and receiver are NTP synced
|
||||||
|
- Fixed a cache issue with restored tabs
|
||||||
|
- Cache CORS request
|
||||||
|
- Disable WiFi sleep by default on ESP32
|
||||||
|
|
||||||
|
#### Build 2105230
|
||||||
|
|
||||||
|
- No longer retain MQTT `/v` topic to alleviate storage loads on MQTT broker
|
||||||
|
- Fixed Sunrise calculation (atan_t approx. used outside of value range)
|
||||||
|
|
||||||
|
#### Build 2105200
|
||||||
|
|
||||||
|
- Fixed WS281x output on ESP32
|
||||||
|
- Fixed potential out-of-bounds write in MQTT
|
||||||
|
- Fixed IR pin not changeable if IR disabled
|
||||||
|
- Fixed XML API <wv> containing -1 on Manual only RGBW mode (see #888, #1783)
|
||||||
|
|
||||||
#### Build 2105171
|
#### Build 2105171
|
||||||
|
|
||||||
- Always copy MQTT payloads to prevent non-0-terminated strings
|
- Always copy MQTT payloads to prevent non-0-terminated strings
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 602 B |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.12.0-b3",
|
"version": "0.12.2-bl4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "wled",
|
"name": "wled",
|
||||||
"version": "0.12.2-bl3",
|
"version": "0.12.2-bl4",
|
||||||
"description": "Tools for WLED project",
|
"description": "Tools for WLED project",
|
||||||
"main": "tools/cdata.js",
|
"main": "tools/cdata.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth
|
default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth
|
||||||
|
|
||||||
# Single binaries (uncomment your board)
|
# Single binaries (uncomment your board)
|
||||||
|
; default_envs = elekstube_ips
|
||||||
; default_envs = nodemcuv2
|
; default_envs = nodemcuv2
|
||||||
; default_envs = esp01_1m_full
|
; default_envs = esp01_1m_full
|
||||||
; default_envs = esp07
|
; default_envs = esp07
|
||||||
@ -47,7 +48,8 @@ extra_configs =
|
|||||||
# arduino core 2.7.0 = platformIO 2.5.0
|
# arduino core 2.7.0 = platformIO 2.5.0
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
arduino_core_2_6_3 = espressif8266@2.3.3
|
arduino_core_2_6_3 = espressif8266@2.3.3
|
||||||
arduino_core_2_7_4 = espressif8266@^2.6.2
|
arduino_core_2_7_4 = espressif8266@2.6.2
|
||||||
|
arduino_core_3_0_0 = espressif8266@3.0.0
|
||||||
|
|
||||||
# Development platforms
|
# Development platforms
|
||||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||||
@ -131,6 +133,8 @@ ldscript_4m1m = eagle.flash.4m1m.ld
|
|||||||
build_flags =
|
build_flags =
|
||||||
-DESP8266
|
-DESP8266
|
||||||
-DFP_IN_IROM
|
-DFP_IN_IROM
|
||||||
|
;-Wno-deprecated-declarations
|
||||||
|
;-Wno-register
|
||||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||||
; lwIP 2 - Higher Bandwidth no Features
|
; lwIP 2 - Higher Bandwidth no Features
|
||||||
@ -418,3 +422,37 @@ platform_packages = ${common.platform_packages}
|
|||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags_esp8266}
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# EleksTube-IPS
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
[env:elekstube_ips]
|
||||||
|
board = esp32dev
|
||||||
|
platform = espressif32@3.2
|
||||||
|
upload_speed = 921600
|
||||||
|
lib_deps = ${env.lib_deps}
|
||||||
|
TFT_eSPI
|
||||||
|
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
|
||||||
|
-D USERMOD_RTC
|
||||||
|
-D USERMOD_ELEKSTUBE_IPS
|
||||||
|
-D LEDPIN=12
|
||||||
|
-D RLYPIN=27
|
||||||
|
-D BTNPIN=34
|
||||||
|
-D WLED_DISABLE_INFRARED
|
||||||
|
-D DEFAULT_LED_COUNT=6
|
||||||
|
# Display config
|
||||||
|
-D ST7789_DRIVER
|
||||||
|
-D TFT_WIDTH=135
|
||||||
|
-D TFT_HEIGHT=240
|
||||||
|
-D CGRAM_OFFSET
|
||||||
|
-D TFT_SDA_READ
|
||||||
|
-D TFT_MOSI=23
|
||||||
|
-D TFT_SCLK=18
|
||||||
|
-D TFT_DC=25
|
||||||
|
-D TFT_RST=26
|
||||||
|
-D SPI_FREQUENCY=40000000
|
||||||
|
-D USER_SETUP_LOADED
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
lib_ignore =
|
||||||
|
ESPAsyncTCP
|
||||||
|
ESPAsyncUDP
|
||||||
|
@ -37,6 +37,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
|||||||
- MQTT
|
- MQTT
|
||||||
- Blynk IoT
|
- Blynk IoT
|
||||||
- E1.31, Art-Net, DDP and TPM2.net
|
- E1.31, Art-Net, DDP and TPM2.net
|
||||||
|
- [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios))
|
||||||
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
||||||
- UDP realtime
|
- UDP realtime
|
||||||
- Alexa voice control (including dimming and color)
|
- Alexa voice control (including dimming and color)
|
||||||
|
@ -44,7 +44,7 @@ starlette==0.14.2
|
|||||||
# via platformio
|
# via platformio
|
||||||
tabulate==0.8.9
|
tabulate==0.8.9
|
||||||
# via platformio
|
# via platformio
|
||||||
urllib3==1.26.4
|
urllib3==1.26.5
|
||||||
# via requests
|
# via requests
|
||||||
uvicorn==0.13.4
|
uvicorn==0.13.4
|
||||||
# via platformio
|
# via platformio
|
||||||
|
6
tools/WLED_ESP32_4MB_1MB_FS.csv
Normal file
6
tools/WLED_ESP32_4MB_1MB_FS.csv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x5000,
|
||||||
|
otadata, data, ota, 0xe000, 0x2000,
|
||||||
|
app0, app, ota_0, 0x10000, 0x17B000,
|
||||||
|
app1, app, ota_1, 0x18B000,0x17B000,
|
||||||
|
spiffs, data, spiffs, 0x306000,0x0FA000,
|
|
70
usermods/EleksTube_IPS/ChipSelect.h
Normal file
70
usermods/EleksTube_IPS/ChipSelect.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef CHIP_SELECT_H
|
||||||
|
#define CHIP_SELECT_H
|
||||||
|
|
||||||
|
#include "Hardware.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* `digit`s are as defined in Hardware.h, 0 == seconds ones, 5 == hours tens.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ChipSelect {
|
||||||
|
private:
|
||||||
|
uint8_t digits_map;
|
||||||
|
const uint8_t all_on = 0x3F;
|
||||||
|
const uint8_t all_off = 0x00;
|
||||||
|
public:
|
||||||
|
ChipSelect() : digits_map(all_off) {}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
// Documented in README.md. Q7 and Q6 are unused. Q5 is Seconds Ones, Q0 is Hours Tens.
|
||||||
|
// Q7 is the first bit written, Q0 is the last. So we push two dummy bits, then start with
|
||||||
|
// Seconds Ones and end with Hours Tens.
|
||||||
|
// CS is Active Low, but digits_map is 1 for enable, 0 for disable. So we bit-wise NOT first.
|
||||||
|
|
||||||
|
uint8_t to_shift = (~digits_map) << 2;
|
||||||
|
|
||||||
|
digitalWrite(CSSR_LATCH_PIN, LOW);
|
||||||
|
shiftOut(CSSR_DATA_PIN, CSSR_CLOCK_PIN, LSBFIRST, to_shift);
|
||||||
|
digitalWrite(CSSR_LATCH_PIN, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin()
|
||||||
|
{
|
||||||
|
pinMode(CSSR_LATCH_PIN, OUTPUT);
|
||||||
|
pinMode(CSSR_DATA_PIN, OUTPUT);
|
||||||
|
pinMode(CSSR_CLOCK_PIN, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(CSSR_DATA_PIN, LOW);
|
||||||
|
digitalWrite(CSSR_CLOCK_PIN, LOW);
|
||||||
|
digitalWrite(CSSR_LATCH_PIN, LOW);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These speak the indexes defined in Hardware.h.
|
||||||
|
// So 0 is disabled, 1 is enabled (even though CS is active low, this gets mapped.)
|
||||||
|
// So bit 0 (LSB), is index 0, is SECONDS_ONES
|
||||||
|
// Translation to what the 74HC595 uses is done in update()
|
||||||
|
void setDigitMap(uint8_t map, bool update_=true) { digits_map = map; if (update_) update(); }
|
||||||
|
uint8_t getDigitMap() { return digits_map; }
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
// Sets just the one digit by digit number
|
||||||
|
void setDigit(uint8_t digit, bool update_=true) { setDigitMap(0x01 << digit, update_); }
|
||||||
|
void setAll(bool update_=true) { setDigitMap(all_on, update_); }
|
||||||
|
void clear(bool update_=true) { setDigitMap(all_off, update_); }
|
||||||
|
void setSecondsOnes() { setDigit(SECONDS_ONES); }
|
||||||
|
void setSecondsTens() { setDigit(SECONDS_TENS); }
|
||||||
|
void setMinutesOnes() { setDigit(MINUTES_ONES); }
|
||||||
|
void setMinutesTens() { setDigit(MINUTES_TENS); }
|
||||||
|
void setHoursOnes() { setDigit(HOURS_ONES); }
|
||||||
|
void setHoursTens() { setDigit(HOURS_TENS); }
|
||||||
|
bool isSecondsOnes() { return (digits_map&SECONDS_ONES_MAP > 0); }
|
||||||
|
bool isSecondsTens() { return (digits_map&SECONDS_TENS_MAP > 0); }
|
||||||
|
bool isMinutesOnes() { return (digits_map&MINUTES_ONES_MAP > 0); }
|
||||||
|
bool isMinutesTens() { return (digits_map&MINUTES_TENS_MAP > 0); }
|
||||||
|
bool isHoursOnes() { return (digits_map&HOURS_ONES_MAP > 0); }
|
||||||
|
bool isHoursTens() { return (digits_map&HOURS_TENS_MAP > 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CHIP_SELECT_H
|
52
usermods/EleksTube_IPS/Hardware.h
Normal file
52
usermods/EleksTube_IPS/Hardware.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Define the hardware for the EleksTube IPS clock. Mostly pin definitions
|
||||||
|
*/
|
||||||
|
#ifndef ELEKSTUBEHAX_HARDWARE_H
|
||||||
|
#define ELEKSTUBEHAX_HARDWARE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <Arduino.h> // for HIGH and LOW
|
||||||
|
|
||||||
|
// Common indexing scheme, used to identify the digit
|
||||||
|
#define SECONDS_ONES (0)
|
||||||
|
#define SECONDS_TENS (1)
|
||||||
|
#define MINUTES_ONES (2)
|
||||||
|
#define MINUTES_TENS (3)
|
||||||
|
#define HOURS_ONES (4)
|
||||||
|
#define HOURS_TENS (5)
|
||||||
|
#define NUM_DIGITS (6)
|
||||||
|
|
||||||
|
#define SECONDS_ONES_MAP (0x01 << SECONDS_ONES)
|
||||||
|
#define SECONDS_TENS_MAP (0x01 << SECONDS_TENS)
|
||||||
|
#define MINUTES_ONES_MAP (0x01 << MINUTES_ONES)
|
||||||
|
#define MINUTES_TENS_MAP (0x01 << MINUTES_TENS)
|
||||||
|
#define HOURS_ONES_MAP (0x01 << HOURS_ONES)
|
||||||
|
#define HOURS_TENS_MAP (0x01 << HOURS_TENS)
|
||||||
|
|
||||||
|
// WS2812 (or compatible) LEDs on the back of the display modules.
|
||||||
|
#define BACKLIGHTS_PIN (12)
|
||||||
|
|
||||||
|
// Buttons, active low, externally pulled up (with actual resistors!)
|
||||||
|
#define BUTTON_LEFT_PIN (33)
|
||||||
|
#define BUTTON_MODE_PIN (32)
|
||||||
|
#define BUTTON_RIGHT_PIN (35)
|
||||||
|
#define BUTTON_POWER_PIN (34)
|
||||||
|
|
||||||
|
// I2C to DS3231 RTC.
|
||||||
|
#define RTC_SCL_PIN (22)
|
||||||
|
#define RTC_SDA_PIN (21)
|
||||||
|
|
||||||
|
// Chip Select shift register, to select the display
|
||||||
|
#define CSSR_DATA_PIN (14)
|
||||||
|
#define CSSR_CLOCK_PIN (16)
|
||||||
|
#define CSSR_LATCH_PIN (17)
|
||||||
|
|
||||||
|
// SPI to displays
|
||||||
|
// DEFINED IN User_Setup.h
|
||||||
|
// Look for: TFT_MOSI, TFT_SCLK, TFT_CS, TFT_DC, and TFT_RST
|
||||||
|
|
||||||
|
// Power for all TFT displays are grounded through a MOSFET so they can all be turned off.
|
||||||
|
// Active HIGH.
|
||||||
|
#define TFT_ENABLE_PIN (27)
|
||||||
|
|
||||||
|
#endif // ELEKSTUBEHAX_HARDWARE_H
|
218
usermods/EleksTube_IPS/TFTs.h
Normal file
218
usermods/EleksTube_IPS/TFTs.h
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#ifndef TFTS_H
|
||||||
|
#define TFTS_H
|
||||||
|
|
||||||
|
#include "wled.h"
|
||||||
|
#include <FS.h>
|
||||||
|
|
||||||
|
#include <TFT_eSPI.h>
|
||||||
|
#include "Hardware.h"
|
||||||
|
#include "ChipSelect.h"
|
||||||
|
|
||||||
|
class TFTs : public TFT_eSPI {
|
||||||
|
private:
|
||||||
|
uint8_t digits[NUM_DIGITS];
|
||||||
|
|
||||||
|
// These read 16- and 32-bit types from the SD card file.
|
||||||
|
// BMP data is stored little-endian, Arduino is little-endian too.
|
||||||
|
// May need to reverse subscript order if porting elsewhere.
|
||||||
|
|
||||||
|
uint16_t read16(fs::File &f) {
|
||||||
|
uint16_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read32(fs::File &f) {
|
||||||
|
uint32_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read();
|
||||||
|
((uint8_t *)&result)[2] = f.read();
|
||||||
|
((uint8_t *)&result)[3] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t output_buffer[TFT_HEIGHT][TFT_WIDTH];
|
||||||
|
|
||||||
|
|
||||||
|
// These BMP functions are stolen directly from the TFT_SPIFFS_BMP example in the TFT_eSPI library.
|
||||||
|
// Unfortunately, they aren't part of the library itself, so I had to copy them.
|
||||||
|
// I've modified drawBmp to buffer the whole image at once instead of doing it line-by-line.
|
||||||
|
|
||||||
|
//// BEGIN STOLEN CODE
|
||||||
|
|
||||||
|
// Draw directly from file stored in RGB565 format
|
||||||
|
bool drawBin(const char *filename) {
|
||||||
|
fs::File bmpFS;
|
||||||
|
|
||||||
|
|
||||||
|
// Open requested file on SD card
|
||||||
|
bmpFS = WLED_FS.open(filename, "r");
|
||||||
|
|
||||||
|
if (!bmpFS)
|
||||||
|
{
|
||||||
|
Serial.print(F("File not found: "));
|
||||||
|
Serial.println(filename);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sz = bmpFS.size();
|
||||||
|
if (sz <= 64800)
|
||||||
|
{
|
||||||
|
bool oldSwapBytes = getSwapBytes();
|
||||||
|
setSwapBytes(true);
|
||||||
|
|
||||||
|
int16_t h = sz / (135 * 2);
|
||||||
|
|
||||||
|
//draw img that is shorter than 240pix into the center
|
||||||
|
int16_t y = (height() - h) /2;
|
||||||
|
|
||||||
|
bmpFS.read((uint8_t *) output_buffer,sz);
|
||||||
|
|
||||||
|
if (!realtimeMode || realtimeOverride) strip.service();
|
||||||
|
|
||||||
|
pushImage(0, y, 135, h, (uint16_t *)output_buffer);
|
||||||
|
|
||||||
|
setSwapBytes(oldSwapBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bmpFS.close();
|
||||||
|
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool drawBmp(const char *filename) {
|
||||||
|
fs::File bmpFS;
|
||||||
|
|
||||||
|
// Open requested file on SD card
|
||||||
|
bmpFS = WLED_FS.open(filename, "r");
|
||||||
|
|
||||||
|
if (!bmpFS)
|
||||||
|
{
|
||||||
|
Serial.print(F("File not found: "));
|
||||||
|
Serial.println(filename);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t seekOffset;
|
||||||
|
int16_t w, h, row;
|
||||||
|
uint8_t r, g, b;
|
||||||
|
|
||||||
|
uint16_t magic = read16(bmpFS);
|
||||||
|
if (magic == 0xFFFF) {
|
||||||
|
Serial.println(F("BMP not found!"));
|
||||||
|
bmpFS.close();
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic != 0x4D42) {
|
||||||
|
Serial.print(F("File not a BMP. Magic: "));
|
||||||
|
Serial.println(magic);
|
||||||
|
bmpFS.close();
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
read32(bmpFS);
|
||||||
|
read32(bmpFS);
|
||||||
|
seekOffset = read32(bmpFS);
|
||||||
|
read32(bmpFS);
|
||||||
|
w = read32(bmpFS);
|
||||||
|
h = read32(bmpFS);
|
||||||
|
|
||||||
|
if ((read16(bmpFS) != 1) || (read16(bmpFS) != 24) || (read32(bmpFS) != 0)) {
|
||||||
|
Serial.println(F("BMP format not recognized."));
|
||||||
|
bmpFS.close();
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw img that is shorter than 240pix into the center
|
||||||
|
int16_t y = (height() - h) /2;
|
||||||
|
|
||||||
|
bool oldSwapBytes = getSwapBytes();
|
||||||
|
setSwapBytes(true);
|
||||||
|
bmpFS.seek(seekOffset);
|
||||||
|
|
||||||
|
uint16_t padding = (4 - ((w * 3) & 3)) & 3;
|
||||||
|
uint8_t lineBuffer[w * 3 + padding];
|
||||||
|
|
||||||
|
uint8_t serviceStrip = (!realtimeMode || realtimeOverride) ? 7 : 0;
|
||||||
|
// row is decremented as the BMP image is drawn bottom up
|
||||||
|
for (row = h-1; row >= 0; row--) {
|
||||||
|
if ((row & 0b00000111) == serviceStrip) strip.service(); //still refresh backlight to mitigate stutter every few rows
|
||||||
|
bmpFS.read(lineBuffer, sizeof(lineBuffer));
|
||||||
|
uint8_t* bptr = lineBuffer;
|
||||||
|
|
||||||
|
// Convert 24 to 16 bit colours while copying to output buffer.
|
||||||
|
for (uint16_t col = 0; col < w; col++)
|
||||||
|
{
|
||||||
|
b = *bptr++;
|
||||||
|
g = *bptr++;
|
||||||
|
r = *bptr++;
|
||||||
|
output_buffer[row][col] = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pushImage(0, y, w, h, (uint16_t *)output_buffer);
|
||||||
|
setSwapBytes(oldSwapBytes);
|
||||||
|
|
||||||
|
bmpFS.close();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
TFTs() : TFT_eSPI(), chip_select()
|
||||||
|
{ for (uint8_t digit=0; digit < NUM_DIGITS; digit++) digits[digit] = 0; }
|
||||||
|
|
||||||
|
// no == Do not send to TFT. yes == Send to TFT if changed. force == Send to TFT.
|
||||||
|
enum show_t { no, yes, force };
|
||||||
|
// A digit of 0xFF means blank the screen.
|
||||||
|
const static uint8_t blanked = 255;
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
pinMode(TFT_ENABLE_PIN, OUTPUT);
|
||||||
|
digitalWrite(TFT_ENABLE_PIN, HIGH); //enable displays on boot
|
||||||
|
|
||||||
|
// Start with all displays selected.
|
||||||
|
chip_select.begin();
|
||||||
|
chip_select.setAll();
|
||||||
|
|
||||||
|
// Initialize the super class.
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showDigit(uint8_t digit) {
|
||||||
|
chip_select.setDigit(digit);
|
||||||
|
|
||||||
|
if (digits[digit] == blanked) {
|
||||||
|
fillScreen(TFT_BLACK);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Filenames are no bigger than "255.bmp\0"
|
||||||
|
char file_name[10];
|
||||||
|
sprintf(file_name, "/%d.bmp", digits[digit]);
|
||||||
|
if (WLED_FS.exists(file_name)) {
|
||||||
|
drawBmp(file_name);
|
||||||
|
} else {
|
||||||
|
sprintf(file_name, "/%d.bin", digits[digit]);
|
||||||
|
drawBin(file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDigit(uint8_t digit, uint8_t value, show_t show=yes) {
|
||||||
|
uint8_t old_value = digits[digit];
|
||||||
|
digits[digit] = value;
|
||||||
|
|
||||||
|
if (show != no && (old_value != value || show == force)) {
|
||||||
|
showDigit(digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t getDigit(uint8_t digit) { return digits[digit]; }
|
||||||
|
|
||||||
|
void showAllDigits() { for (uint8_t digit=0; digit < NUM_DIGITS; digit++) showDigit(digit); }
|
||||||
|
|
||||||
|
// Making chip_select public so we don't have to proxy all methods, and the caller can just use it directly.
|
||||||
|
ChipSelect chip_select;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TFTS_H
|
47
usermods/EleksTube_IPS/User_Setup.h
Normal file
47
usermods/EleksTube_IPS/User_Setup.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This is intended to over-ride `User_Setup.h` that comes with the TFT_eSPI library.
|
||||||
|
* I hate having to modify the library code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ST7789 135 x 240 display with no chip select line
|
||||||
|
|
||||||
|
#define ST7789_DRIVER // Configure all registers
|
||||||
|
|
||||||
|
#define TFT_WIDTH 135
|
||||||
|
#define TFT_HEIGHT 240
|
||||||
|
|
||||||
|
#define CGRAM_OFFSET // Library will add offsets required
|
||||||
|
|
||||||
|
//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||||
|
//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||||
|
|
||||||
|
//#define TFT_INVERSION_ON
|
||||||
|
//#define TFT_INVERSION_OFF
|
||||||
|
|
||||||
|
// EleksTube IPS
|
||||||
|
#define TFT_SDA_READ // Read and write on the MOSI/SDA pin, no separate MISO pin
|
||||||
|
#define TFT_MOSI 23
|
||||||
|
#define TFT_SCLK 18
|
||||||
|
//#define TFT_CS -1 // Not connected
|
||||||
|
#define TFT_DC 25 // Data Command, aka Register Select or RS
|
||||||
|
#define TFT_RST 26 // Connect reset to ensure display initialises
|
||||||
|
|
||||||
|
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||||
|
//#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||||
|
//#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||||
|
//#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||||
|
//#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||||
|
//#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||||
|
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||||
|
//#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||||
|
|
||||||
|
//#define SMOOTH_FONT
|
||||||
|
|
||||||
|
|
||||||
|
//#define SPI_FREQUENCY 27000000
|
||||||
|
#define SPI_FREQUENCY 40000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To make the Library not over-write all this:
|
||||||
|
*/
|
||||||
|
#define USER_SETUP_LOADED
|
31
usermods/EleksTube_IPS/readme.md
Normal file
31
usermods/EleksTube_IPS/readme.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# EleksTube IPS Clock usermod
|
||||||
|
|
||||||
|
This usermod allows WLED to run on the EleksTube IPS clock.
|
||||||
|
It enables running all WLED effects on the background SK6812 lighting, while displaying digit bitmaps on the 6 IPS screens.
|
||||||
|
Code is largely based on https://github.com/SmittyHalibut/EleksTubeHAX by Mark Smith!
|
||||||
|
|
||||||
|
Supported:
|
||||||
|
- Display with custom bitmaps or raw RGB565 images (.bin) from filesystem
|
||||||
|
- Background lighting
|
||||||
|
- Power button
|
||||||
|
- RTC (with RTC usermod)
|
||||||
|
- Standard WLED time features (NTP, DST, timezones)
|
||||||
|
|
||||||
|
Not supported:
|
||||||
|
- 3 navigation buttons, on-device setup
|
||||||
|
|
||||||
|
Your images must be exactly 135 pixels wide and 1-240 pixels high.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Compile and upload to clock using the `elekstube_ips` PlatformIO environment
|
||||||
|
Once uploaded (the clock can be flashed like any ESP32 module), go to `[WLED-IP]/edit` and upload the 0-9.bin files from [here](https://github.com/Aircoookie/NixieThemes/tree/master/themes/RealisticNixie/bin).
|
||||||
|
You can find more clockfaces in the [NixieThemes](https://github.com/Aircoookie/NixieThemes/) repo.
|
||||||
|
Use LED pin 12, relay pin 27 and button pin 34.
|
||||||
|
|
||||||
|
## Use of RGB565 images
|
||||||
|
|
||||||
|
Binary 16-bit per pixel RGB565 format `.bin` images are now supported. This has the benefit of only using 2/3rds of the file size a `.bmp` has.
|
||||||
|
The drawback is that this format cannot be handled by common image programs and that an extra conversion step is needed.
|
||||||
|
You can use https://lvgl.io/tools/imageconverter to convert your .bmp to a .bin file (settings `True color` and `Binary RGB565`)
|
||||||
|
Thank you to @RedNax67 for adding .bin support.
|
60
usermods/EleksTube_IPS/usermod_elekstube_ips.h
Normal file
60
usermods/EleksTube_IPS/usermod_elekstube_ips.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TFTs.h"
|
||||||
|
#include "wled.h"
|
||||||
|
|
||||||
|
//Large parts of the code are from https://github.com/SmittyHalibut/EleksTubeHAX
|
||||||
|
|
||||||
|
class ElekstubeIPSUsermod : public Usermod {
|
||||||
|
private:
|
||||||
|
TFTs tfts;
|
||||||
|
void updateClockDisplay(TFTs::show_t show=TFTs::yes) {
|
||||||
|
bool set[6] = {false};
|
||||||
|
for (uint8_t i = 0; i<6; i++) {
|
||||||
|
char c = cronixieDisplay[i];
|
||||||
|
if (c >= '0' && c <= '9') {
|
||||||
|
tfts.setDigit(5-i, c - '0', show); set[i] = true;
|
||||||
|
} else if (c >= 'A' && c <= 'G') {
|
||||||
|
tfts.setDigit(5-i, c - 'A' + 10, show); set[i] = true; //10.bmp to 16.bmp static display
|
||||||
|
} else if (c == '-' || c == '_' || c == ' ') {
|
||||||
|
tfts.setDigit(5-i, 255, show); set[i] = true; //blank
|
||||||
|
} else {
|
||||||
|
set[i] = false; //display HHMMSS time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t hr = hour(localTime);
|
||||||
|
uint8_t hrTens = hr/10;
|
||||||
|
uint8_t mi = minute(localTime);
|
||||||
|
uint8_t mittens = mi/10;
|
||||||
|
uint8_t s = second(localTime);
|
||||||
|
uint8_t sTens = s/10;
|
||||||
|
if (!set[0]) tfts.setDigit(HOURS_TENS, hrTens, show);
|
||||||
|
if (!set[1]) tfts.setDigit(HOURS_ONES, hr - hrTens*10, show);
|
||||||
|
if (!set[2]) tfts.setDigit(MINUTES_TENS, mittens, show);
|
||||||
|
if (!set[3]) tfts.setDigit(MINUTES_ONES, mi - mittens*10, show);
|
||||||
|
if (!set[4]) tfts.setDigit(SECONDS_TENS, sTens, show);
|
||||||
|
if (!set[5]) tfts.setDigit(SECONDS_ONES, s - sTens*10, show);
|
||||||
|
}
|
||||||
|
unsigned long lastTime = 0;
|
||||||
|
public:
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
tfts.begin();
|
||||||
|
tfts.fillScreen(TFT_BLACK);
|
||||||
|
|
||||||
|
for (int8_t i = 5; i >= 0; i--) {
|
||||||
|
tfts.setDigit(i, 255, TFTs::force); //turn all off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (toki.isTick()) {
|
||||||
|
updateLocalTime();
|
||||||
|
updateClockDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_ELEKSTUBE_IPS;
|
||||||
|
}
|
||||||
|
};
|
8
usermods/RTC/readme.md
Normal file
8
usermods/RTC/readme.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# DS1307/DS3231 Real time clock
|
||||||
|
|
||||||
|
Gets the time from I2C RTC module on boot. This allows clocks to operate e.g. if temporarily no WiFi is available.
|
||||||
|
The stored time is updated each time NTP is synced.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Add the build flag `-D USERMOD_RTC` to your platformio environment.
|
35
usermods/RTC/usermod_rtc.h
Normal file
35
usermods/RTC/usermod_rtc.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/dependencies/time/DS1307RTC.h"
|
||||||
|
#include "wled.h"
|
||||||
|
|
||||||
|
//Connect DS1307 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL))
|
||||||
|
|
||||||
|
class RTCUsermod : public Usermod {
|
||||||
|
private:
|
||||||
|
unsigned long lastTime = 0;
|
||||||
|
bool disabled = false;
|
||||||
|
public:
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
time_t rtcTime = RTC.get();
|
||||||
|
if (rtcTime) {
|
||||||
|
toki.setTime(rtcTime,TOKI_NO_MS_ACCURACY,TOKI_TS_RTC);
|
||||||
|
updateLocalTime();
|
||||||
|
} else {
|
||||||
|
if (!RTC.chipPresent()) disabled = true; //don't waste time if H/W error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (!disabled && toki.isTick()) {
|
||||||
|
time_t t = toki.second();
|
||||||
|
if (t != RTC.get()) RTC.set(t); //set RTC to NTP/UI-provided value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_RTC;
|
||||||
|
}
|
||||||
|
};
|
16
usermods/SN_Photoresistor/platformio_override.ini
Normal file
16
usermods/SN_Photoresistor/platformio_override.ini
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
; Options
|
||||||
|
; -------
|
||||||
|
; USERMOD_SN_PHOTORESISTOR - define this to have this user mod included wled00\usermods_list.cpp
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE - the voltage supplied to the sensor, defaults to 5v
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_ADC_PRECISION - the ADC precision is the number of distinguishable ADC inputs, defaults to 1024.0 (10 bits)
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE - the resistor size, defaults to 10000.0 (10K hms)
|
||||||
|
; USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE - the offset value to report on, defaults to 25
|
||||||
|
;
|
||||||
|
[env:usermod_sn_photoresistor_d1_mini]
|
||||||
|
extends = env:d1_mini
|
||||||
|
build_flags =
|
||||||
|
${common.build_flags_esp8266}
|
||||||
|
-D USERMOD_SN_PHOTORESISTOR
|
||||||
|
lib_deps = ${env.lib_deps}
|
30
usermods/SN_Photoresistor/readme.md
Normal file
30
usermods/SN_Photoresistor/readme.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# SN_Photoresistor usermod
|
||||||
|
|
||||||
|
This usermod will read from an attached photoresistor sensor like the KY-018 sensor.
|
||||||
|
The luminance is displayed both in the Info section of the web UI as well as published to the `/luminance` MQTT topic if enabled.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Copy the example `platformio_override.ini` to the root directory. This file should be placed in the same directory as `platformio.ini`.
|
||||||
|
|
||||||
|
### Define Your Options
|
||||||
|
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR` - define this to have this user mod included wled00\usermods_list.cpp
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL` - the number of milliseconds between measurements, defaults to 60 seconds
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE` - the voltage supplied to the sensor, defaults to 5v
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_ADC_PRECISION` - the ADC precision is the number of distinguishable ADC inputs, defaults to 1024.0 (10 bits)
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE` - the resistor size, defaults to 10000.0 (10K hms)
|
||||||
|
* `USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE` - the offset value to report on, defaults to 25
|
||||||
|
|
||||||
|
All parameters can be configured at runtime using Usermods settings page.
|
||||||
|
|
||||||
|
## Project link
|
||||||
|
|
||||||
|
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||||
|
|
||||||
|
### PlatformIO requirements
|
||||||
|
|
||||||
|
If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:usermod_sn_photoresistor_d1_mini`.
|
||||||
|
|
||||||
|
## Change Log
|
128
usermods/SN_Photoresistor/usermod_sn_photoresistor.h
Normal file
128
usermods/SN_Photoresistor/usermod_sn_photoresistor.h
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wled.h"
|
||||||
|
|
||||||
|
//Pin defaults for QuinLed Dig-Uno
|
||||||
|
#define PHOTORESISTOR_PIN A0
|
||||||
|
|
||||||
|
// the frequency to check photoresistor, 10 seconds
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// how many seconds after boot to take first measurement, 10 seconds
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT 10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// supplied voltage
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 10 bits
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_ADC_PRECISION
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_ADC_PRECISION 1024.0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// resistor size 10K hms
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// only report if differance grater than offset value
|
||||||
|
#ifndef USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE
|
||||||
|
#define USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Usermod_SN_Photoresistor : public Usermod
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// set last reading as "40 sec before boot", so first reading is taken after 20 sec
|
||||||
|
unsigned long lastMeasurement = UINT32_MAX - (USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT);
|
||||||
|
// flag to indicate we have finished the first getTemperature call
|
||||||
|
// allows this library to report to the user how long until the first
|
||||||
|
// measurement
|
||||||
|
bool getLuminanceComplete = false;
|
||||||
|
uint16_t lastLDRValue = -1000;
|
||||||
|
|
||||||
|
bool checkBoundSensor(float newValue, float prevValue, float maxDiff)
|
||||||
|
{
|
||||||
|
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getLuminance()
|
||||||
|
{
|
||||||
|
// http://forum.arduino.cc/index.php?topic=37555.0
|
||||||
|
// https://forum.arduino.cc/index.php?topic=185158.0
|
||||||
|
float volts = analogRead(PHOTORESISTOR_PIN) * (USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE / USERMOD_SN_PHOTORESISTOR_ADC_PRECISION);
|
||||||
|
float amps = volts / USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE;
|
||||||
|
float lux = amps * 1000000 * 2.0;
|
||||||
|
|
||||||
|
lastMeasurement = millis();
|
||||||
|
getLuminanceComplete = true;
|
||||||
|
return uint16_t(lux);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
pinMode(PHOTORESISTOR_PIN, INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
unsigned long now = millis();
|
||||||
|
|
||||||
|
// check to see if we are due for taking a measurement
|
||||||
|
// lastMeasurement will not be updated until the conversion
|
||||||
|
// is complete the the reading is finished
|
||||||
|
if (now - lastMeasurement < USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t currentLDRValue = getLuminance();
|
||||||
|
if (checkBoundSensor(currentLDRValue, lastLDRValue, USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE))
|
||||||
|
{
|
||||||
|
lastLDRValue = currentLDRValue;
|
||||||
|
|
||||||
|
if (WLED_MQTT_CONNECTED)
|
||||||
|
{
|
||||||
|
char subuf[45];
|
||||||
|
strcpy(subuf, mqttDeviceTopic);
|
||||||
|
strcat_P(subuf, PSTR("/luminance"));
|
||||||
|
mqtt->publish(subuf, 0, true, String(lastLDRValue).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_PRINTLN("Missing MQTT connection. Not publishing data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToJsonInfo(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull()) user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
JsonArray lux = user.createNestedArray(F("Luminance"));
|
||||||
|
|
||||||
|
if (!getLuminanceComplete)
|
||||||
|
{
|
||||||
|
// if we haven't read the sensor yet, let the user know
|
||||||
|
// that we are still waiting for the first measurement
|
||||||
|
lux.add((USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
||||||
|
lux.add(F(" sec until read"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lux.add(lastLDRValue);
|
||||||
|
lux.add(F(" lux"));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_SN_PHOTORESISTOR;
|
||||||
|
}
|
||||||
|
};
|
14
usermods/SN_Photoresistor/usermods_list.cpp
Normal file
14
usermods/SN_Photoresistor/usermods_list.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "wled.h"
|
||||||
|
/*
|
||||||
|
* Register your v2 usermods here!
|
||||||
|
*/
|
||||||
|
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||||
|
#include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void registerUsermods()
|
||||||
|
{
|
||||||
|
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||||
|
usermods.add(new Usermod_SN_Photoresistor());
|
||||||
|
#endif
|
||||||
|
}
|
@ -42,30 +42,24 @@ uint16_t WS2812FX::mode_static(void) {
|
|||||||
* Blink/strobe function
|
* Blink/strobe function
|
||||||
* Alternate between color1 and color2
|
* Alternate between color1 and color2
|
||||||
* if(strobe == true) then create a strobe effect
|
* if(strobe == true) then create a strobe effect
|
||||||
* NOTE: Maybe re-rework without timer
|
|
||||||
*/
|
*/
|
||||||
uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
|
uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
|
||||||
uint16_t stateTime = SEGENV.aux1;
|
|
||||||
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
|
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
|
||||||
uint32_t onTime = 0;
|
uint32_t onTime = FRAMETIME;
|
||||||
uint32_t offTime = cycleTime;
|
if (!strobe) onTime += ((cycleTime * SEGMENT.intensity) >> 8);
|
||||||
|
cycleTime += FRAMETIME*2;
|
||||||
if (!strobe) {
|
uint32_t it = now / cycleTime;
|
||||||
onTime = (cycleTime * SEGMENT.intensity) >> 8;
|
uint32_t rem = now % cycleTime;
|
||||||
offTime = cycleTime - onTime;
|
|
||||||
|
bool on = false;
|
||||||
|
if (it != SEGENV.step //new iteration, force on state for one frame, even if set time is too brief
|
||||||
|
|| rem <= onTime) {
|
||||||
|
on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
stateTime = ((SEGENV.aux0 & 1) == 0) ? onTime : offTime;
|
SEGENV.step = it; //save previous iteration
|
||||||
stateTime += 20;
|
|
||||||
|
|
||||||
if (now - SEGENV.step > stateTime)
|
|
||||||
{
|
|
||||||
SEGENV.aux0++;
|
|
||||||
SEGENV.aux1 = stateTime;
|
|
||||||
SEGENV.step = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t color = ((SEGENV.aux0 & 1) == 0) ? color1 : color2;
|
uint32_t color = on ? color1 : color2;
|
||||||
if (color == color1 && do_palette)
|
if (color == color1 && do_palette)
|
||||||
{
|
{
|
||||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
#define SEGENV _segment_runtimes[_segment_index]
|
#define SEGENV _segment_runtimes[_segment_index]
|
||||||
#define SEGLEN _virtualSegmentLength
|
#define SEGLEN _virtualSegmentLength
|
||||||
#define SEGACT SEGMENT.stop
|
#define SEGACT SEGMENT.stop
|
||||||
#define SPEED_FORMULA_L (uint16_t)(5 + (50*(255 - SEGMENT.speed))/SEGLEN)
|
#define SPEED_FORMULA_L 5U + (50U*(255U - SEGMENT.speed))/SEGLEN
|
||||||
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
||||||
|
|
||||||
// some common colors
|
// some common colors
|
||||||
|
@ -991,7 +991,7 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t paletteIndex = i;
|
uint8_t paletteIndex = i;
|
||||||
if (mapping) paletteIndex = (i*255)/(SEGLEN -1);
|
if (mapping && SEGLEN > 1) paletteIndex = (i*255)/(SEGLEN -1);
|
||||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||||
|
@ -46,7 +46,10 @@ void onAlexaChange(EspalexaDevice* dev)
|
|||||||
bri = briLast;
|
bri = briLast;
|
||||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||||
}
|
}
|
||||||
} else applyPreset(macroAlexaOn);
|
} else {
|
||||||
|
applyPreset(macroAlexaOn);
|
||||||
|
if (bri == 0) espalexaDevice->setValue(briLast); //stop Alexa from complaining if macroAlexaOn does not actually turn on
|
||||||
|
}
|
||||||
} else if (m == EspalexaDeviceProperty::off)
|
} else if (m == EspalexaDeviceProperty::off)
|
||||||
{
|
{
|
||||||
if (!macroAlexaOff)
|
if (!macroAlexaOff)
|
||||||
@ -57,7 +60,10 @@ void onAlexaChange(EspalexaDevice* dev)
|
|||||||
bri = 0;
|
bri = 0;
|
||||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||||
}
|
}
|
||||||
} else applyPreset(macroAlexaOff);
|
} else {
|
||||||
|
applyPreset(macroAlexaOff);
|
||||||
|
if (bri != 0) espalexaDevice->setValue(0); //stop Alexa from complaining if macroAlexaOff does not actually turn off
|
||||||
|
}
|
||||||
} else if (m == EspalexaDeviceProperty::bri)
|
} else if (m == EspalexaDeviceProperty::bri)
|
||||||
{
|
{
|
||||||
bri = espalexaDevice->getValue();
|
bri = espalexaDevice->getValue();
|
||||||
|
@ -160,7 +160,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
}
|
}
|
||||||
CJSON(touchThreshold,hw[F("btn")][F("tt")]);
|
CJSON(touchThreshold,hw[F("btn")][F("tt")]);
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
|
||||||
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||||
if (hw_ir_pin > -2) {
|
if (hw_ir_pin > -2) {
|
||||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||||
@ -169,7 +168,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
irPin = -1;
|
irPin = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
CJSON(irEnabled, hw["ir"]["type"]);
|
CJSON(irEnabled, hw["ir"]["type"]);
|
||||||
|
|
||||||
JsonObject relay = hw[F("relay")];
|
JsonObject relay = hw[F("relay")];
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
|
#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h"
|
||||||
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
|
#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h"
|
||||||
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
|
#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h"
|
||||||
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
|
#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h
|
||||||
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
|
#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h"
|
||||||
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
|
#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h"
|
||||||
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
|
#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h"
|
||||||
@ -55,6 +55,9 @@
|
|||||||
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
|
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
|
||||||
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
|
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
|
||||||
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
|
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
|
||||||
|
#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h"
|
||||||
|
#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h"
|
||||||
|
#define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h"
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
@ -62,7 +65,7 @@
|
|||||||
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
||||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||||
|
|
||||||
//Notifier callMode
|
//Notifier callMode
|
||||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||||
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
||||||
#define NOTIFIER_CALL_MODE_BUTTON 2
|
#define NOTIFIER_CALL_MODE_BUTTON 2
|
||||||
@ -79,7 +82,7 @@
|
|||||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
||||||
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
|
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
|
||||||
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
||||||
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
||||||
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
|
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
|
||||||
|
|
||||||
//realtime modes
|
//realtime modes
|
||||||
@ -190,6 +193,9 @@
|
|||||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||||
#define SEG_OPTION_TRANSITIONAL 7
|
#define SEG_OPTION_TRANSITIONAL 7
|
||||||
|
|
||||||
|
//Playlist option byte
|
||||||
|
#define PL_OPTION_SHUFFLE 0x01
|
||||||
|
|
||||||
// WLED Error modes
|
// WLED Error modes
|
||||||
#define ERR_NONE 0 // All good :)
|
#define ERR_NONE 0 // All good :)
|
||||||
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
||||||
@ -235,7 +241,11 @@
|
|||||||
// string temp buffer (now stored in stack locally)
|
// string temp buffer (now stored in stack locally)
|
||||||
#define OMAX 2048
|
#define OMAX 2048
|
||||||
|
|
||||||
#define E131_MAX_UNIVERSE_COUNT 9
|
#ifdef WLED_USE_ETHERNET
|
||||||
|
#define E131_MAX_UNIVERSE_COUNT 20
|
||||||
|
#else
|
||||||
|
#define E131_MAX_UNIVERSE_COUNT 10
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
|
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<img alt="" src=" data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAFMSURBVFhH7ZTfbYNADMaPKDNUrJA85CEjdIjOgNQV+sASlZgmI/AIK6AuQfngnDrmjtpHItQ/P+l0juHsz2cH9+fJ/G7nreldfnDnp+ln/ZIlxbIfQmIwJOekCrEJ8FUvASEWEXoBiuSERcTO75uhuwFWff86bi57n3ZC+rW3YLqB5rn11ldCEPNr2LwFJgHHy8G1bTsu3oKYX4N5BrQ8ZAYewSoBGDjr0ElWCUC/rT2X7MqynL7tG4Dc45BwEYM9H5w7DqHMdfNCURR9nue3Iobk55MtOYeLoOQ8vmoG6o+0FaLrOm9FwC3wayLgx5I2WHpGIGYorulfgPYQ3AZLz4hQ9TMBVVVleJGrRUWz2YgQOg8bPjzzrit7vwcRQb5NTiARRPPzMYItoCpoWZITMkao+mRkddpqQ6z6FN+DfwFJrOm55GfewC/CuU/E4tQYg7BPYQAAAABJRU5ErkJggg==">
|
<img alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAbUExURQAAAAB81gCU/zKq/////9bW1oCAgGhoaAAAAGPLX8AAAAAJdFJOU///////////AFNPeBIAAAAJcEhZcwAADsAAAA7AAWrWiQkAAACdSURBVDhPxc9bDoUgEANQebP/FUuHMjBGY/B+3EYR7RH0qC/ZBc6HwCljgHO+xZIVSI2sYgHaG7EBWh8jWoxTrCBFdDJ+BD4lbIHxAcz8APAVLTsrZE4eQD5qzt3cAFTYokC4YCN9Gybgu4yAQtBFLQXHuHABA7JMeOEC/E0W5uy9gv4vo5QHK2i7yq2C8UABM4HmL+CSTXCTF1DrCX6+Gp9zB5dsAAAAAElFTkSuQmCC">
|
||||||
<h1>404 Not Found</h1>
|
<h1>404 Not Found</h1>
|
||||||
<b>Akemi does not know where you are headed...</b><br><br>
|
<b>Akemi does not know where you are headed...</b><br><br>
|
||||||
<button onclick="window.location.href='/sliders'">Back to controls</button>
|
<button onclick="window.location.href='/sliders'">Back to controls</button>
|
||||||
|
@ -1032,6 +1032,8 @@ function cmpP(a, b)
|
|||||||
function handleJson(s)
|
function handleJson(s)
|
||||||
{
|
{
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
|
var e1 = gId('fxlist');
|
||||||
|
var e2 = gId('selectPalette');
|
||||||
|
|
||||||
isOn = s.on;
|
isOn = s.on;
|
||||||
gId('sliderBri').value= s.bri;
|
gId('sliderBri').value= s.bri;
|
||||||
@ -1084,6 +1086,28 @@ function handleJson(s)
|
|||||||
selectedPal = i.pal;
|
selectedPal = i.pal;
|
||||||
selectedFx = i.fx;
|
selectedFx = i.fx;
|
||||||
|
|
||||||
|
/*/--- AC addition ---//
|
||||||
|
// unfortunately this will trigger JSON request loop due to onchange event on input elements
|
||||||
|
// and it may not be necessary with websockes
|
||||||
|
|
||||||
|
// Effects
|
||||||
|
var selFx = e1.querySelector(`input[name="fx"][value="${i.fx}"]`);
|
||||||
|
if (selFx) selFx.checked = true;
|
||||||
|
else location.reload(); //effect list is gone (e.g. if restoring tab). Reload.
|
||||||
|
|
||||||
|
var selElement = e1.querySelector('.selected');
|
||||||
|
if (selElement) selElement.classList.remove('selected');
|
||||||
|
var selectedEffect = e1.querySelector(`.lstI[data-id="${i.fx}"]`);
|
||||||
|
if (selectedEffect) selectedEffect.classList.add('selected');
|
||||||
|
|
||||||
|
// Palettes
|
||||||
|
var selPa = e2.querySelector(`input[name="palette"][value="${i.pal}"]`);
|
||||||
|
if (selPa) selPa.checked = true;
|
||||||
|
selElement = e2.querySelector('.selected');
|
||||||
|
if (selElement) selElement.classList.remove('selected');
|
||||||
|
e2.querySelector(`.lstI[data-id="${i.pal}"]`).classList.add('selected');
|
||||||
|
//--- AC addition ---/*/
|
||||||
|
|
||||||
displayRover(lastinfo, s);
|
displayRover(lastinfo, s);
|
||||||
clearErrorToast();
|
clearErrorToast();
|
||||||
|
|
||||||
@ -1097,9 +1121,6 @@ function requestJson(command, rinfo = true, verbose = true, callback = null)
|
|||||||
lastUpdate = new Date();
|
lastUpdate = new Date();
|
||||||
if (!jsonTimeout) jsonTimeout = setTimeout(showErrorToast, 3000);
|
if (!jsonTimeout) jsonTimeout = setTimeout(showErrorToast, 3000);
|
||||||
var req = null;
|
var req = null;
|
||||||
var e1 = gId('fxlist');
|
|
||||||
var e2 = gId('selectPalette');
|
|
||||||
|
|
||||||
var url = (loc?`http://${locip}`:'') + (rinfo ? '/json/si': (command ? '/json/state':'/json/si'));
|
var url = (loc?`http://${locip}`:'') + (rinfo ? '/json/si': (command ? '/json/state':'/json/si'));
|
||||||
|
|
||||||
var type = command ? 'post':'get';
|
var type = command ? 'post':'get';
|
||||||
|
@ -283,11 +283,11 @@ Color Order:
|
|||||||
<option value="4">BGR</option>
|
<option value="4">BGR</option>
|
||||||
<option value="5">GBR</option>
|
<option value="5">GBR</option>
|
||||||
</select><br>
|
</select><br>
|
||||||
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:35px" onchange="UI()"/>
|
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:40px" onchange="UI()"/>
|
||||||
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:40px" onchange="UI()"/>
|
||||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:40px" onchange="UI()"/>
|
||||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:40px" onchange="UI()"/>
|
||||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:40px" onchange="UI()"/>
|
||||||
<br>
|
<br>
|
||||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />
|
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />
|
||||||
<div id="dig${i}" style="display:inline">
|
<div id="dig${i}" style="display:inline">
|
||||||
@ -311,7 +311,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
|||||||
var c = gId("btns").innerHTML;
|
var c = gId("btns").innerHTML;
|
||||||
var bt = "BT" + i;
|
var bt = "BT" + i;
|
||||||
var be = "BE" + i;
|
var be = "BE" + i;
|
||||||
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" style="width:35px" value="${p}">`;
|
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" style="width:40px" value="${p}">`;
|
||||||
c += `<select name="${be}">`
|
c += `<select name="${be}">`
|
||||||
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
|
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
|
||||||
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
|
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
|
||||||
@ -393,7 +393,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
|||||||
</div><hr style="width:260px">
|
</div><hr style="width:260px">
|
||||||
<div id="btns"></div>
|
<div id="btns"></div>
|
||||||
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
||||||
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()" style="width:35px"><select name="IT" onchange="UI()">
|
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()" style="width:40px"><select name="IT" onchange="UI()">
|
||||||
<option value="0">Remote disabled</option>
|
<option value="0">Remote disabled</option>
|
||||||
<option value="1">24-key RGB</option>
|
<option value="1">24-key RGB</option>
|
||||||
<option value="2">24-key with CT</option>
|
<option value="2">24-key with CT</option>
|
||||||
@ -407,7 +407,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
|
|||||||
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div>
|
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div>
|
||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br>
|
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br>
|
||||||
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()" style="width:35px"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()" style="width:40px"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')"> ×</span><br>
|
||||||
<hr style="width:260px">
|
<hr style="width:260px">
|
||||||
<h3>Defaults</h3>
|
<h3>Defaults</h3>
|
||||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||||
|
@ -19,28 +19,6 @@ function GetV(){var d=document;}
|
|||||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||||
</div>
|
</div>
|
||||||
<h2>Sync setup</h2>
|
<h2>Sync setup</h2>
|
||||||
<!--
|
|
||||||
<h3>Button setup</h3>
|
|
||||||
Button type:
|
|
||||||
<select name=BT>
|
|
||||||
<option value=0>Disabled</option>
|
|
||||||
<option value=2>Pushbutton</option>
|
|
||||||
<option value=4>Switch</option>
|
|
||||||
</select><br>
|
|
||||||
Infrared remote:
|
|
||||||
<select name=IR>
|
|
||||||
<option value=0>Disabled</option>
|
|
||||||
<option value=1>24-key RGB</option>
|
|
||||||
<option value=2>24-key with CT</option>
|
|
||||||
<option value=3>40-key blue</option>
|
|
||||||
<option value=4>44-key RGB</option>
|
|
||||||
<option value=5>21-key RGB</option>
|
|
||||||
<option value=6>6-key black</option>
|
|
||||||
<option value=7>9-key red</option>
|
|
||||||
<option value=8>JSON remote</option>
|
|
||||||
</select><br>
|
|
||||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
|
||||||
-->
|
|
||||||
<h3>WLED Broadcast</h3>
|
<h3>WLED Broadcast</h3>
|
||||||
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
|
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
|
||||||
2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br>
|
2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br>
|
||||||
|
@ -76,11 +76,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function addRow(i,p,l,d) {
|
function addRow(i,p,l,d) {
|
||||||
var t = gId("macros");
|
var t = gId("macros"); // table
|
||||||
var rCnt = t.rows.length;
|
var rCnt = t.rows.length; // get the number of rows.
|
||||||
var tr = t.insertRow(rCnt);
|
var tr = t.insertRow(rCnt); // table row.
|
||||||
|
|
||||||
var td = document.createElement('td');
|
var td = document.createElement('td'); // TABLE DEFINITION.
|
||||||
td = tr.insertCell(0);
|
td = tr.insertCell(0);
|
||||||
td.innerHTML = `Button ${i}:`;
|
td.innerHTML = `Button ${i}:`;
|
||||||
td = tr.insertCell(1);
|
td = tr.insertCell(1);
|
||||||
@ -179,17 +179,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div>For analog button set <i>double</i> to:
|
<a href="https://github.com/Aircoookie/WLED/wiki/Macros#analog-button" target="_blank">Analog Button setup</a>
|
||||||
<ul>
|
|
||||||
<li>250=global brightness</li>
|
|
||||||
<li>249=effect speed</li>
|
|
||||||
<li>248=effect intensity</li>
|
|
||||||
<li>247=palette</li>
|
|
||||||
<li>200=primary color hue</li>
|
|
||||||
<li>0..32=segment X opacity</li>
|
|
||||||
</ul>
|
|
||||||
More details: <a href="https://github.com/Aircoookie/WLED/wiki/Macros#analog-button" target="_blank">Analog Button setup</a>
|
|
||||||
</div>
|
|
||||||
<h3>Time-controlled presets</h3>
|
<h3>Time-controlled presets</h3>
|
||||||
<div style="display: inline-block">
|
<div style="display: inline-block">
|
||||||
<table id="TMT">
|
<table id="TMT">
|
||||||
|
@ -31,11 +31,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 999px;
|
width: 950px;
|
||||||
max-width: 85%;
|
max-width: 82%;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
image-rendering: crisp-edges;
|
image-rendering: crisp-edges;
|
||||||
margin: 25px 0 -10px 0;
|
margin: 4vh 0 0 0;
|
||||||
animation: fi 1s;
|
animation: fi 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<img alt="" src=" data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAAAjCAYAAACjOOUsAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsAAAA7AAWrWiQkAAATfSURBVGhD7ZlPaBVHHMdnS2Ox5iKYGIyYJwQlUTHG6kUwtSAIBsEiBopgKR5i68mbIPgEwZun0uYgouIlobQIKQheIsSLaBSaRFoEc3gtMa9HLaiH7X4n81tn583u/HkTaZ/7gR+zMzvv93bfZ3/777GSkpL/AJFo3Tg/H7OuPtGxY7CTsZnjkd/3lRTi/qMKgfGXt8TAO6KfT2TG1f7u6ROlyBXgI9HaQRW4+JR3ox92Z1p1XO3PLCUVORHHvFMSDDeJBuJvH4mlZdS+C3c7B+Ln3fvivw59w0MMOzP/FYvj75K4PMhDDDszdbM7rk1V4hcPD/MQw858MbEnPvJgf3x29hQPMdwUbqc2qRIhCBVGrQk+Lzm9mq6NkIe2t20N7xOf7NjK2w13rlltM+Sh7VvLu+/YOMib6NyMVR7IQ9u7qY33ibb2bbxd/9mvVnkgD217ZTXvE72fbuHtle1X3VxIuH1QOZ2mmG5yaH4yr0giBKryVCDTJBICG+SpJDJNIiFQlacCmSaREKjKU4FMX5F+p1NIk8OExTwbgeD1b7+zotOrlUBQm2FFp1cbgeDtyzlWdHq1EQie/fMH8z29Br0myiwdr7PkWpSGC2se/8IqtWnRa+y7Ur+Q3FF97/X7ZFjV/4B1Dz1Pw5WrlZ/Y7T330gjFikkE9Xo9jSJ0Vah+Ru7nVWNRFWq3Iacai6qQ9kfOl1eNuirUfZ7wrcbgEqkCOyc6MmEDVdyrXUd5ENR3rUiqwI6LnTx8oQp8M783E66cWjiWCarMZlnRSix5PwSTSBXY0WFXdf9HfK+FKlSBoX6rjEQ8XMutD3nn+1Yg5L755Mrzk0qkh2xMwLOYr0iXa6CJZu9KQ+N7LSSoAuma6EKRn1TiwaUn0bO3r/gy7v42/3nf+cEzxFGq5jD1TYTYJhAqj4pt3iI/mdMpTbQRqD4HhqhA9S40r28L3ZWmz4kUjlAFNvucSNBzomtF5vlJJVarVb53mMgHLMBRRBEaNWez3xFqW5vN0+znyQ/5Ahlho6OjcVdXl+jxiVmhHn8Gq+jendq+cpPRvUO1fuUmo3mHavvKTUb3DtX2lZtM3jtUWRqQ3TRMBrLMjMgVkAiB2waX/1nwgURygTv885BICOzrH+BjPpBICBzo38nHfJBFksDFxUU2NjaWjhMNAwSJ1Ems/n2RDQ0NsQNzn4sVjF1vvyGWGOvp6cmsk+frJLpWISFXo1cVElI1+lQhIVejTxUSajVCYp5AoB0k6AhIRQqJo7OnGRe87gIfxl9N1Y8nlpcTKpUK+/rlSdFLDghpft5fUTho0GJD5WW0RetUWi1PgwMNmbtTFdhXaRBowdj2H3kuVGQeyIkg5GVQtE6mFfPoPMgUSqSjgo4Gdqk/whfxpGeSaqJIxjFGsbCwkF2fBHJh3ZH5RpE2RxtBedJtkmi1PLSMdXwgh0KJAIkBEiLQV5MODw9ndiBvp/I2VIwZd5T4EPJQLvRNGCVSYgr0xSotIyMjYkkPfV7eUFNOHa2cx+X3BkaJAIkoxJAWCBwfHxc9PdhBbFzSRgixzHfahVbNA2x/b8JKoi0QaKpE7KC8cVjGmOha06p5fAgq0aYSS8ITROLk5GRUq9UyAt/XUVgSGNyl0kNrMyBHchCUeSwJejotKSkp+VBh7F9fIy7OdlOyMwAAAABJRU5ErkJggg==">
|
<img alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG0AAAAfCAMAAADazLOuAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABLUExURQAAAAB81gCU/zKq///mo7sWMN8bO+ZIYtZaAP9rAP+HMsCiG+TAIOnMS0KqNU7KPnLUZOrq6v///4CAgGhoaL+/v6CgoExMTAAAAAlm4O8AAAAZdFJOU////////////////////////////////wABNAq3AAAACXBIWXMAAA7DAAAOwwHHb6hkAAACN0lEQVRIS73VjVLCMBAEYIr8CYKkrdj3f1J37zaXFCpTO+piaDgbPq9px9VQ0qyrvKj4q6m0Zr1h+M7xF1zRmnWzqV9/0d2jttGotO1uv9dUObwej5oqp7fzWVPl8n69aprzoOUUbbvdIbV3OLwitXc6vSG1d7m8I3feSEN0j2CeNbOY4MxigjOLCc4sZsTV2l1cCyy4wIILLLjAxtykltq2rbTU+qi01N5rXNO2leaFORoija2l5MM5a02ac9Ya16Sk5tgaPrUpjZub0BL6YqSxKwbH77XUUmSkJXSl8QtaMuyJhq5maL5nTKVpZC13VmtMpTFT2g4vJjTuGfMzzXftiUZnhdtgb1xofvypRon5TjNnxYN9zJo6K5ruSIzQtGuVZn0x91rKvdHBvm39E7SyZ4y06Gz8BDBFKzsXmhcwyfsGZ9VpbhoiCinaxPNmGWmWWrNU2jB0q6HvOhN1JUtCixQtp2g51ZVUXIPS2RMAD++T2nY/DrDjOMDO4wC7jmNYj3d73nrXug8Yt9uNB8xNU1cKNXWlUFNXCjV1pZhGTE83m2vWfYf/NGj4Bg1zu5JD3/MnH5ZWfLOksbmGWGjgXMN5/C2GXYGFFW9Nmtle6Xut0Gm+JsayCj8z0nhjGvYJzVf4aSzmNYsr+u7Q2JIdoX3YOQjOslmsW1jJ3120nE9gfo79hTaNdcsqVR610lvO47pllae9ReZ805zKo2a3iaY5c75pTmVCA6dJ5H7N0sr/asPwBehb7ifEhusRAAAAAElFTkSuQmCC">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<h1>Welcome to WLED!</h1>
|
<h1>Welcome to WLED!</h1>
|
||||||
<h3>Thank you for installing my application!</h3>
|
<h3>Thank you for installing my application!</h3>
|
||||||
|
@ -100,8 +100,8 @@ void handleIR();
|
|||||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||||
#include "FX.h"
|
#include "FX.h"
|
||||||
|
|
||||||
void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist = false);
|
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||||
bool deserializeState(JsonObject root, bool fromPlaylist = false);
|
bool deserializeState(JsonObject root, byte presetId = 0);
|
||||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true, uint8_t versionAPI = 1);
|
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true, uint8_t versionAPI = 1);
|
||||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||||
void serializeInfo(JsonObject root);
|
void serializeInfo(JsonObject root);
|
||||||
@ -130,6 +130,7 @@ bool initMqtt();
|
|||||||
void publishMqtt();
|
void publishMqtt();
|
||||||
|
|
||||||
//ntp.cpp
|
//ntp.cpp
|
||||||
|
void handleTime();
|
||||||
void handleNetworkTime();
|
void handleNetworkTime();
|
||||||
void sendNTPPacket();
|
void sendNTPPacket();
|
||||||
bool checkNTPResponse();
|
bool checkNTPResponse();
|
||||||
@ -140,6 +141,7 @@ void setCountdown();
|
|||||||
byte weekdayMondayFirst();
|
byte weekdayMondayFirst();
|
||||||
void checkTimers();
|
void checkTimers();
|
||||||
void calculateSunriseAndSunset();
|
void calculateSunriseAndSunset();
|
||||||
|
void setTimeFromAPI(uint32_t timein);
|
||||||
|
|
||||||
//overlay.cpp
|
//overlay.cpp
|
||||||
void initCronixie();
|
void initCronixie();
|
||||||
@ -156,11 +158,11 @@ void _drawOverlayCronixie();
|
|||||||
//playlist.cpp
|
//playlist.cpp
|
||||||
void shufflePlaylist();
|
void shufflePlaylist();
|
||||||
void unloadPlaylist();
|
void unloadPlaylist();
|
||||||
void loadPlaylist(JsonObject playlistObject);
|
void loadPlaylist(JsonObject playlistObject, byte presetId = 0);
|
||||||
void handlePlaylist();
|
void handlePlaylist();
|
||||||
|
|
||||||
//presets.cpp
|
//presets.cpp
|
||||||
bool applyPreset(byte index, bool fromPlaylist = false);
|
bool applyPreset(byte index);
|
||||||
void savePreset(byte index, bool persist = true, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
void savePreset(byte index, bool persist = true, const char* pname = nullptr, JsonObject saveobj = JsonObject());
|
||||||
void deletePreset(byte index);
|
void deletePreset(byte index);
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ Please do not close or refresh the page :)</div></body></html>)=====";
|
|||||||
const char PAGE_welcome[] PROGMEM = R"=====(<!DOCTYPE html><html><head><meta charset="utf-8"><meta
|
const char PAGE_welcome[] PROGMEM = R"=====(<!DOCTYPE html><html><head><meta charset="utf-8"><meta
|
||||||
content="width=device-width" name="viewport"><meta name="theme-color"
|
content="width=device-width" name="viewport"><meta name="theme-color"
|
||||||
content="#222222"><title>Welcome!</title><style>
|
content="#222222"><title>Welcome!</title><style>
|
||||||
body{font-family:Verdana,Helvetica,sans-serif;text-align:center;background-color:#222;margin:0;color:#fff}button{outline:0;cursor:pointer;padding:8px;margin:10px;width:230px;text-transform:uppercase;font-family:helvetica;font-size:19px;background-color:#333;color:#fff;border:0 solid #fff;border-radius:25px;filter:drop-shadow(0 0 1px #000)}img{width:999px;max-width:85%;image-rendering:pixelated;image-rendering:crisp-edges;margin:25px 0 -10px 0;animation:fi 1s}@keyframes fi{from{opacity:0}to{opacity:1}}.main{animation:fi 1.5s .7s both}
|
body{font-family:Verdana,Helvetica,sans-serif;text-align:center;background-color:#222;margin:0;color:#fff}button{outline:0;cursor:pointer;padding:8px;margin:10px;width:230px;text-transform:uppercase;font-family:helvetica;font-size:19px;background-color:#333;color:#fff;border:0 solid #fff;border-radius:25px;filter:drop-shadow(0 0 1px #000)}img{width:950px;max-width:82%;image-rendering:pixelated;image-rendering:crisp-edges;margin:4vh 0 0 0;animation:fi 1s}@keyframes fi{from{opacity:0}to{opacity:1}}.main{animation:fi 1.5s .7s both}
|
||||||
</style></head><body><img alt=""
|
</style></head><body><img alt=""
|
||||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAAAjCAYAAACjOOUsAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsAAAA7AAWrWiQkAAATfSURBVGhD7ZlPaBVHHMdnS2Ox5iKYGIyYJwQlUTHG6kUwtSAIBsEiBopgKR5i68mbIPgEwZun0uYgouIlobQIKQheIsSLaBSaRFoEc3gtMa9HLaiH7X4n81tn583u/HkTaZ/7gR+zMzvv93bfZ3/777GSkpL/AJFo3Tg/H7OuPtGxY7CTsZnjkd/3lRTi/qMKgfGXt8TAO6KfT2TG1f7u6ROlyBXgI9HaQRW4+JR3ox92Z1p1XO3PLCUVORHHvFMSDDeJBuJvH4mlZdS+C3c7B+Ln3fvivw59w0MMOzP/FYvj75K4PMhDDDszdbM7rk1V4hcPD/MQw858MbEnPvJgf3x29hQPMdwUbqc2qRIhCBVGrQk+Lzm9mq6NkIe2t20N7xOf7NjK2w13rlltM+Sh7VvLu+/YOMib6NyMVR7IQ9u7qY33ibb2bbxd/9mvVnkgD217ZTXvE72fbuHtle1X3VxIuH1QOZ2mmG5yaH4yr0giBKryVCDTJBICG+SpJDJNIiFQlacCmSaREKjKU4FMX5F+p1NIk8OExTwbgeD1b7+zotOrlUBQm2FFp1cbgeDtyzlWdHq1EQie/fMH8z29Br0myiwdr7PkWpSGC2se/8IqtWnRa+y7Ur+Q3FF97/X7ZFjV/4B1Dz1Pw5WrlZ/Y7T330gjFikkE9Xo9jSJ0Vah+Ru7nVWNRFWq3Iacai6qQ9kfOl1eNuirUfZ7wrcbgEqkCOyc6MmEDVdyrXUd5ENR3rUiqwI6LnTx8oQp8M783E66cWjiWCarMZlnRSix5PwSTSBXY0WFXdf9HfK+FKlSBoX6rjEQ8XMutD3nn+1Yg5L755Mrzk0qkh2xMwLOYr0iXa6CJZu9KQ+N7LSSoAuma6EKRn1TiwaUn0bO3r/gy7v42/3nf+cEzxFGq5jD1TYTYJhAqj4pt3iI/mdMpTbQRqD4HhqhA9S40r28L3ZWmz4kUjlAFNvucSNBzomtF5vlJJVarVb53mMgHLMBRRBEaNWez3xFqW5vN0+znyQ/5Ahlho6OjcVdXl+jxiVmhHn8Gq+jendq+cpPRvUO1fuUmo3mHavvKTUb3DtX2lZtM3jtUWRqQ3TRMBrLMjMgVkAiB2waX/1nwgURygTv885BICOzrH+BjPpBICBzo38nHfJBFksDFxUU2NjaWjhMNAwSJ1Ems/n2RDQ0NsQNzn4sVjF1vvyGWGOvp6cmsk+frJLpWISFXo1cVElI1+lQhIVejTxUSajVCYp5AoB0k6AhIRQqJo7OnGRe87gIfxl9N1Y8nlpcTKpUK+/rlSdFLDghpft5fUTho0GJD5WW0RetUWi1PgwMNmbtTFdhXaRBowdj2H3kuVGQeyIkg5GVQtE6mFfPoPMgUSqSjgo4Gdqk/whfxpGeSaqJIxjFGsbCwkF2fBHJh3ZH5RpE2RxtBedJtkmi1PLSMdXwgh0KJAIkBEiLQV5MODw9ndiBvp/I2VIwZd5T4EPJQLvRNGCVSYgr0xSotIyMjYkkPfV7eUFNOHa2cx+X3BkaJAIkoxJAWCBwfHxc9PdhBbFzSRgixzHfahVbNA2x/b8JKoi0QaKpE7KC8cVjGmOha06p5fAgq0aYSS8ITROLk5GRUq9UyAt/XUVgSGNyl0kNrMyBHchCUeSwJejotKSkp+VBh7F9fIy7OdlOyMwAAAABJRU5ErkJggg==">
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAG0AAAAfCAMAAADazLOuAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAABLUExURQAAAAB81gCU/zKq///mo7sWMN8bO+ZIYtZaAP9rAP+HMsCiG+TAIOnMS0KqNU7KPnLUZOrq6v///4CAgGhoaL+/v6CgoExMTAAAAAlm4O8AAAAZdFJOU////////////////////////////////wABNAq3AAAACXBIWXMAAA7DAAAOwwHHb6hkAAACN0lEQVRIS73VjVLCMBAEYIr8CYKkrdj3f1J37zaXFCpTO+piaDgbPq9px9VQ0qyrvKj4q6m0Zr1h+M7xF1zRmnWzqV9/0d2jttGotO1uv9dUObwej5oqp7fzWVPl8n69aprzoOUUbbvdIbV3OLwitXc6vSG1d7m8I3feSEN0j2CeNbOY4MxigjOLCc4sZsTV2l1cCyy4wIILLLjAxtykltq2rbTU+qi01N5rXNO2leaFORoija2l5MM5a02ac9Ya16Sk5tgaPrUpjZub0BL6YqSxKwbH77XUUmSkJXSl8QtaMuyJhq5maL5nTKVpZC13VmtMpTFT2g4vJjTuGfMzzXftiUZnhdtgb1xofvypRon5TjNnxYN9zJo6K5ruSIzQtGuVZn0x91rKvdHBvm39E7SyZ4y06Gz8BDBFKzsXmhcwyfsGZ9VpbhoiCinaxPNmGWmWWrNU2jB0q6HvOhN1JUtCixQtp2g51ZVUXIPS2RMAD++T2nY/DrDjOMDO4wC7jmNYj3d73nrXug8Yt9uNB8xNU1cKNXWlUFNXCjV1pZhGTE83m2vWfYf/NGj4Bg1zu5JD3/MnH5ZWfLOksbmGWGjgXMN5/C2GXYGFFW9Nmtle6Xut0Gm+JsayCj8z0nhjGvYJzVf4aSzmNYsr+u7Q2JIdoX3YOQjOslmsW1jJ3120nE9gfo79hTaNdcsqVR610lvO47pllae9ReZ805zKo2a3iaY5c75pTmVCA6dJ5H7N0sr/asPwBehb7ifEhusRAAAAAElFTkSuQmCC">
|
||||||
<div class="main"><h1>Welcome to WLED!</h1><h3>
|
<div class="main"><h1>Welcome to WLED!</h1><h3>
|
||||||
Thank you for installing my application!</h3><b>Next steps:</b><br><br>
|
Thank you for installing my application!</h3><b>Next steps:</b><br><br>
|
||||||
Connect the module to your local WiFi here!<br><button
|
Connect the module to your local WiFi here!<br><button
|
||||||
@ -95,7 +95,7 @@ content="width=device-width" name="viewport"><meta name="theme-color"
|
|||||||
content="#222222"><title>Not found</title><style>
|
content="#222222"><title>Not found</title><style>
|
||||||
body{font-family:Verdana,Helvetica,sans-serif;text-align:center;background-color:#222;margin:0;color:#fff}img{width:400px;max-width:50%;image-rendering:pixelated;image-rendering:crisp-edges;margin:25px 0 -10px 0}button{outline:0;cursor:pointer;padding:8px;margin:10px;width:230px;text-transform:uppercase;font-family:helvetica;font-size:19px;background-color:#333;color:#fff;border:0 solid #fff;border-radius:25px}
|
body{font-family:Verdana,Helvetica,sans-serif;text-align:center;background-color:#222;margin:0;color:#fff}img{width:400px;max-width:50%;image-rendering:pixelated;image-rendering:crisp-edges;margin:25px 0 -10px 0}button{outline:0;cursor:pointer;padding:8px;margin:10px;width:230px;text-transform:uppercase;font-family:helvetica;font-size:19px;background-color:#333;color:#fff;border:0 solid #fff;border-radius:25px}
|
||||||
</style></head><body><img alt=""
|
</style></head><body><img alt=""
|
||||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAFMSURBVFhH7ZTfbYNADMaPKDNUrJA85CEjdIjOgNQV+sASlZgmI/AIK6AuQfngnDrmjtpHItQ/P+l0juHsz2cH9+fJ/G7nreldfnDnp+ln/ZIlxbIfQmIwJOekCrEJ8FUvASEWEXoBiuSERcTO75uhuwFWff86bi57n3ZC+rW3YLqB5rn11ldCEPNr2LwFJgHHy8G1bTsu3oKYX4N5BrQ8ZAYewSoBGDjr0ElWCUC/rT2X7MqynL7tG4Dc45BwEYM9H5w7DqHMdfNCURR9nue3Iobk55MtOYeLoOQ8vmoG6o+0FaLrOm9FwC3wayLgx5I2WHpGIGYorulfgPYQ3AZLz4hQ9TMBVVVleJGrRUWz2YgQOg8bPjzzrit7vwcRQb5NTiARRPPzMYItoCpoWZITMkao+mRkddpqQ6z6FN+DfwFJrOm55GfewC/CuU/E4tQYg7BPYQAAAABJRU5ErkJggg==">
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAbUExURQAAAAB81gCU/zKq/////9bW1oCAgGhoaAAAAGPLX8AAAAAJdFJOU///////////AFNPeBIAAAAJcEhZcwAADsAAAA7AAWrWiQkAAACdSURBVDhPxc9bDoUgEANQebP/FUuHMjBGY/B+3EYR7RH0qC/ZBc6HwCljgHO+xZIVSI2sYgHaG7EBWh8jWoxTrCBFdDJ+BD4lbIHxAcz8APAVLTsrZE4eQD5qzt3cAFTYokC4YCN9Gybgu4yAQtBFLQXHuHABA7JMeOEC/E0W5uy9gv4vo5QHK2i7yq2C8UABM4HmL+CSTXCTF1DrCX6+Gp9zB5dsAAAAAElFTkSuQmCC">
|
||||||
<h1>404 Not Found</h1><b>Akemi does not know where you are headed...</b><br><br>
|
<h1>404 Not Found</h1><b>Akemi does not know where you are headed...</b><br><br>
|
||||||
<button onclick='window.location.href="/sliders"'>Back to controls</button>
|
<button onclick='window.location.href="/sliders"'>Back to controls</button>
|
||||||
</body></html>)=====";
|
</body></html>)=====";
|
||||||
|
File diff suppressed because one or more lines are too long
600
wled00/html_ui.h
600
wled00/html_ui.h
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Autogenerated from wled00/data/index.htm, do not edit!!
|
// Autogenerated from wled00/data/index.htm, do not edit!!
|
||||||
const uint16_t PAGE_index_L = 33960;
|
const uint16_t PAGE_index_L = 33959;
|
||||||
const uint8_t PAGE_index[] PROGMEM = {
|
const uint8_t PAGE_index[] PROGMEM = {
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xcc, 0x7d, 0x7b, 0x5f, 0xe2, 0xc8,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xcc, 0x7d, 0x7b, 0x5f, 0xe2, 0xc8,
|
||||||
0xb6, 0xe8, 0xff, 0x7e, 0x0a, 0x9a, 0x9e, 0xe9, 0x81, 0x26, 0xbc, 0x1f, 0xad, 0xd8, 0x19, 0x4f,
|
0xb6, 0xe8, 0xff, 0x7e, 0x0a, 0x9a, 0x9e, 0xe9, 0x81, 0x26, 0xbc, 0x1f, 0xad, 0xd8, 0x19, 0x4f,
|
||||||
@ -1833,303 +1833,303 @@ const uint8_t PAGE_index[] PROGMEM = {
|
|||||||
0x09, 0x40, 0x61, 0xd7, 0x38, 0xa1, 0x6a, 0x0a, 0x72, 0xfc, 0x06, 0x36, 0xd2, 0x7c, 0x67, 0x96,
|
0x09, 0x40, 0x61, 0xd7, 0x38, 0xa1, 0x6a, 0x0a, 0x72, 0xfc, 0x06, 0x36, 0xd2, 0x7c, 0x67, 0x96,
|
||||||
0xd9, 0x89, 0x11, 0x32, 0x1b, 0xf9, 0xb9, 0x7b, 0xc9, 0x44, 0xfc, 0xa9, 0x8b, 0x50, 0xb8, 0xd0,
|
0xd9, 0x89, 0x11, 0x32, 0x1b, 0xf9, 0xb9, 0x7b, 0xc9, 0x44, 0xfc, 0xa9, 0x8b, 0x50, 0xb8, 0xd0,
|
||||||
0x95, 0x79, 0x95, 0x1e, 0x38, 0xfc, 0x79, 0x34, 0x53, 0x91, 0xdc, 0xbd, 0xf3, 0x31, 0x78, 0xe7,
|
0x95, 0x79, 0x95, 0x1e, 0x38, 0xfc, 0x79, 0x34, 0x53, 0x91, 0xdc, 0xbd, 0xf3, 0x31, 0x78, 0xe7,
|
||||||
0x75, 0x2d, 0x46, 0x17, 0x3b, 0xa1, 0x4a, 0xe7, 0xa3, 0x50, 0xb2, 0xe1, 0x60, 0x7e, 0x11, 0x57,
|
0x75, 0x2d, 0x46, 0x17, 0x3b, 0xa1, 0x4a, 0xe7, 0xa3, 0x50, 0xb2, 0xe1, 0xc4, 0xfc, 0x9a, 0x20,
|
||||||
0x0f, 0x29, 0xc4, 0xdc, 0x3a, 0x82, 0x93, 0x0e, 0x10, 0x21, 0x14, 0xec, 0x1c, 0x76, 0x2f, 0xec,
|
0xd9, 0x76, 0xec, 0x47, 0x1c, 0x7a, 0x0f, 0x59, 0xc6, 0xdc, 0x3a, 0x0e, 0x94, 0x3e, 0x12, 0x21,
|
||||||
0x25, 0x31, 0x2a, 0x8a, 0x78, 0x78, 0xfc, 0x6b, 0x7e, 0xb3, 0x92, 0x51, 0xf1, 0xf8, 0x67, 0x21,
|
0x74, 0xf0, 0x1c, 0x99, 0x2f, 0xec, 0x25, 0x31, 0x2a, 0x8a, 0x90, 0x79, 0xfc, 0x6b, 0x7e, 0xb3,
|
||||||
0xaa, 0x72, 0x74, 0x3c, 0x2e, 0x58, 0xd0, 0xb7, 0x2a, 0x1c, 0x5f, 0xd8, 0xbb, 0x99, 0x67, 0x09,
|
0x92, 0x81, 0xf3, 0xf8, 0x67, 0x21, 0xaa, 0x72, 0x00, 0x3d, 0x2e, 0x58, 0xd0, 0xb7, 0x2a, 0x62,
|
||||||
0xfb, 0xd2, 0xd6, 0xe2, 0xe2, 0xc1, 0x86, 0x49, 0x3a, 0x2b, 0x7f, 0xfc, 0xc0, 0x34, 0x23, 0x7b,
|
0x5f, 0xd8, 0xbb, 0x99, 0x67, 0x09, 0xbb, 0xdb, 0xd6, 0x42, 0xe7, 0xc1, 0xcc, 0x49, 0xfa, 0x33,
|
||||||
0x9c, 0x0b, 0xe0, 0xa6, 0x87, 0xf1, 0xd8, 0xf7, 0xd4, 0xf3, 0x59, 0xae, 0x8d, 0x6d, 0x36, 0x4b,
|
0x7f, 0xfc, 0xc0, 0x64, 0x25, 0x3b, 0xa5, 0x0b, 0xf8, 0xa7, 0x87, 0xf1, 0xd8, 0xf7, 0xd4, 0xf3,
|
||||||
0x16, 0xbd, 0x65, 0x94, 0x94, 0x0f, 0xc3, 0xc6, 0xc3, 0xe0, 0xbe, 0x7c, 0x58, 0xd4, 0x1f, 0xc2,
|
0x59, 0xae, 0x8d, 0x6d, 0x36, 0x4b, 0x16, 0xbd, 0x65, 0x94, 0x94, 0x0f, 0xc3, 0xc6, 0xc3, 0xe0,
|
||||||
0x0a, 0x6b, 0xaf, 0x5f, 0x35, 0x5d, 0xe8, 0x35, 0x18, 0xb0, 0xd8, 0xf8, 0x85, 0xaa, 0x28, 0x83,
|
0xbe, 0x7c, 0x58, 0xd4, 0x1f, 0xc2, 0x50, 0x6b, 0xaf, 0x5f, 0x35, 0x5d, 0xe8, 0x35, 0x18, 0xf6,
|
||||||
0x73, 0x76, 0x7f, 0x6f, 0x31, 0x13, 0x2a, 0x49, 0x13, 0x91, 0x47, 0xa0, 0xc5, 0xf8, 0x87, 0x33,
|
0xd8, 0x3e, 0x86, 0xaa, 0x28, 0x9b, 0x74, 0xf6, 0x90, 0x6f, 0xb1, 0x24, 0x2a, 0xa9, 0x17, 0x91,
|
||||||
0x0a, 0xb0, 0xe9, 0x1d, 0xcc, 0x7d, 0x92, 0x73, 0x1c, 0x4c, 0xe7, 0xa1, 0xf0, 0x73, 0xc1, 0x88,
|
0x6a, 0xa0, 0xc5, 0x3e, 0x88, 0x93, 0x0e, 0xb0, 0x75, 0x1e, 0x2c, 0x82, 0x92, 0x73, 0x9c, 0x5d,
|
||||||
0xac, 0xf3, 0x6e, 0x77, 0xad, 0x1b, 0x04, 0x15, 0x42, 0x64, 0x92, 0x54, 0x7b, 0x55, 0x72, 0xdf,
|
0xe7, 0xa1, 0xf0, 0x73, 0xc1, 0xab, 0xac, 0xf3, 0x6e, 0x77, 0xad, 0xdb, 0x0c, 0x15, 0x42, 0xaa,
|
||||||
0x7e, 0x82, 0xc8, 0x4c, 0xf2, 0xb0, 0xb6, 0xf8, 0xe8, 0x6b, 0x74, 0x52, 0x5a, 0xa5, 0xfd, 0x0b,
|
0x92, 0x54, 0xdb, 0x59, 0x32, 0xe8, 0x7e, 0x82, 0xe0, 0x4d, 0xf2, 0x3c, 0xb7, 0xb8, 0xf1, 0x6b,
|
||||||
0xc7, 0xa0, 0x9a, 0x76, 0x77, 0x05, 0x36, 0x62, 0xf1, 0x87, 0x1b, 0xd5, 0x44, 0x0b, 0xdc, 0xb0,
|
0xa4, 0x54, 0x5a, 0x65, 0x06, 0x0c, 0xc7, 0x20, 0xac, 0x76, 0x77, 0x05, 0xc2, 0x62, 0x09, 0x89,
|
||||||
0x10, 0x2b, 0xc4, 0xbe, 0xfa, 0x01, 0x91, 0x42, 0x50, 0xfd, 0xea, 0x73, 0x10, 0x0d, 0xf5, 0x6b,
|
0x1b, 0xd5, 0xa4, 0x0f, 0xdc, 0xb0, 0x90, 0x3c, 0xc4, 0xbe, 0xfa, 0x01, 0xa9, 0x43, 0x50, 0xfd,
|
||||||
0x70, 0x5e, 0x5d, 0x54, 0x51, 0x55, 0xbc, 0x7f, 0x8e, 0xc4, 0xf3, 0x55, 0x1b, 0xa5, 0x78, 0x21,
|
0xea, 0x73, 0x9c, 0x0d, 0xf5, 0x6b, 0x70, 0x5e, 0xdd, 0x65, 0x51, 0x55, 0xbc, 0x7f, 0x8e, 0xdc,
|
||||||
0xd0, 0x8a, 0x84, 0x68, 0x61, 0xc5, 0xa2, 0x05, 0x55, 0xda, 0xd6, 0xda, 0x78, 0x3c, 0x38, 0xd8,
|
0xf4, 0x55, 0x1b, 0xa5, 0x04, 0x22, 0xd0, 0x8a, 0x84, 0xf4, 0x61, 0xc5, 0xd2, 0x07, 0x55, 0xda,
|
||||||
0x66, 0x69, 0x8f, 0x9b, 0x3e, 0x42, 0xe6, 0x41, 0xd8, 0x60, 0x77, 0xe3, 0xae, 0xed, 0xda, 0xdd,
|
0xd6, 0xda, 0x78, 0x3c, 0x38, 0xd8, 0x66, 0x81, 0x90, 0x9b, 0x3e, 0x42, 0x09, 0x42, 0x1e, 0x61,
|
||||||
0x80, 0x3f, 0x57, 0xb0, 0x00, 0xab, 0x5a, 0x14, 0x31, 0x1f, 0xa9, 0x85, 0x8a, 0x00, 0x8f, 0x58,
|
0x77, 0xe3, 0xae, 0xed, 0xda, 0xdd, 0x80, 0x3f, 0x57, 0x30, 0x12, 0xab, 0x5a, 0x14, 0x61, 0x21,
|
||||||
0x93, 0x54, 0x06, 0x25, 0x40, 0xd4, 0xc6, 0x32, 0xe2, 0x67, 0xf3, 0x52, 0x97, 0xb0, 0x21, 0xdb,
|
0xa9, 0x85, 0x8a, 0x46, 0x8f, 0x58, 0xd9, 0x54, 0xc6, 0x2d, 0x40, 0x60, 0xc7, 0x32, 0x28, 0x68,
|
||||||
0x41, 0xe5, 0x73, 0x77, 0x63, 0x2d, 0x82, 0xf4, 0x7b, 0xb7, 0xfd, 0xe2, 0x2f, 0x6b, 0x44, 0xf7,
|
0xf3, 0xde, 0x97, 0xb0, 0x21, 0xdb, 0x41, 0xe5, 0x73, 0x77, 0x63, 0x2d, 0x82, 0xf4, 0x7b, 0xb7,
|
||||||
0x46, 0xd8, 0xc8, 0x84, 0x18, 0xad, 0x58, 0x8f, 0x2a, 0x99, 0xf4, 0x16, 0xf7, 0xae, 0x81, 0x34,
|
0x9d, 0x36, 0x28, 0x6b, 0x44, 0xf7, 0x46, 0x64, 0xc9, 0x84, 0x78, 0xb1, 0x58, 0x0f, 0x3c, 0x99,
|
||||||
0x35, 0xc1, 0xb9, 0xdb, 0xf0, 0xd1, 0x75, 0x09, 0x07, 0x68, 0x52, 0xc6, 0x2a, 0x12, 0x01, 0x3b,
|
0xf4, 0x16, 0xf7, 0xae, 0x81, 0x57, 0x35, 0xd9, 0xba, 0xdb, 0x70, 0xe3, 0x75, 0x09, 0x4d, 0x68,
|
||||||
0x45, 0x03, 0x78, 0xe9, 0x23, 0x91, 0x16, 0xca, 0xcf, 0x74, 0x8e, 0x0e, 0x5e, 0x7b, 0xb6, 0x1e,
|
0x82, 0xc8, 0x2a, 0x58, 0x01, 0xfb, 0x4d, 0x03, 0x78, 0xe9, 0x23, 0x91, 0x46, 0xcc, 0xcf, 0xf4,
|
||||||
0xb5, 0xb2, 0x0c, 0x50, 0xa3, 0x39, 0x7e, 0x7c, 0xfa, 0xd4, 0xd1, 0x7e, 0xe9, 0x4e, 0xcd, 0xa6,
|
0x9f, 0x0e, 0x5e, 0x7b, 0xb6, 0x1e, 0xd8, 0xb2, 0x8c, 0x61, 0xa3, 0xf9, 0x86, 0x7c, 0xfa, 0xd4,
|
||||||
0x17, 0x8b, 0xbb, 0x1f, 0xee, 0x3b, 0xea, 0x96, 0x11, 0xc9, 0xc7, 0xfc, 0x8e, 0x79, 0x2b, 0xb6,
|
0xd1, 0x7e, 0xe9, 0x7e, 0xcf, 0xa6, 0xa3, 0x8b, 0xbb, 0x1f, 0xee, 0x3b, 0xea, 0x22, 0x12, 0xf9,
|
||||||
0x52, 0x1e, 0x1b, 0xf5, 0x17, 0x9d, 0x62, 0x22, 0x55, 0x18, 0x79, 0x64, 0x0f, 0xc3, 0xf2, 0x07,
|
0xc9, 0xfc, 0x8d, 0xea, 0x8b, 0x4e, 0x31, 0x91, 0x1a, 0x8c, 0x3c, 0xb2, 0x87, 0x61, 0xf9, 0x03,
|
||||||
0x68, 0x58, 0xc2, 0xb2, 0xe5, 0x23, 0x07, 0x72, 0x37, 0x7a, 0x9c, 0xa5, 0x39, 0xec, 0x54, 0xa0,
|
0x24, 0x2c, 0x21, 0xd9, 0xf2, 0x11, 0xa4, 0x6e, 0xf4, 0x34, 0x4b, 0x73, 0x58, 0xa9, 0x40, 0xbb,
|
||||||
0xdf, 0xe0, 0xa0, 0x1a, 0xc4, 0x0e, 0xfb, 0xb9, 0x0b, 0x6f, 0xe5, 0x5b, 0x7f, 0x80, 0x40, 0xab,
|
0xc1, 0x21, 0x35, 0x88, 0x19, 0xf6, 0x73, 0x17, 0xbe, 0xca, 0xb7, 0xfe, 0x00, 0x61, 0x56, 0x69,
|
||||||
0x34, 0x6c, 0xdd, 0x87, 0x18, 0x13, 0xed, 0x25, 0xe9, 0x5d, 0xc7, 0x81, 0x21, 0x2f, 0x1c, 0x8c,
|
0x44, 0xba, 0x07, 0x31, 0xe6, 0xd0, 0x4b, 0xd2, 0xbb, 0x8e, 0x03, 0x33, 0x5e, 0xb8, 0x17, 0xd7,
|
||||||
0x6b, 0xa6, 0xe9, 0x90, 0x64, 0x0b, 0x1d, 0x4b, 0x5c, 0xaa, 0x4f, 0x02, 0x17, 0xd1, 0x51, 0x42,
|
0x0c, 0xd3, 0x21, 0xc7, 0x16, 0x1a, 0x96, 0xb8, 0x54, 0x9e, 0x04, 0x2e, 0x62, 0xa3, 0x84, 0x88,
|
||||||
0x44, 0xa3, 0x84, 0xc3, 0x35, 0xe4, 0x31, 0xbb, 0x90, 0x0a, 0x51, 0xc7, 0x88, 0xca, 0x11, 0x09,
|
0x45, 0x09, 0x77, 0x6b, 0x48, 0x63, 0x76, 0x21, 0x13, 0xa2, 0x8e, 0x11, 0x93, 0x23, 0x12, 0x6a,
|
||||||
0xc5, 0x16, 0x8f, 0x6d, 0x64, 0xcd, 0xae, 0x00, 0x8a, 0x85, 0xff, 0xdb, 0x87, 0x1f, 0x77, 0x5f,
|
0x2d, 0x1e, 0xda, 0xc8, 0x9a, 0x5d, 0x01, 0xca, 0x0a, 0xff, 0xb7, 0x0f, 0x3f, 0xee, 0xbe, 0xb2,
|
||||||
0xd9, 0x6b, 0x17, 0xd1, 0xbf, 0x87, 0xe9, 0x17, 0xb8, 0x03, 0x41, 0xc7, 0x02, 0xe6, 0x46, 0xf7,
|
0xd7, 0x2e, 0x62, 0x7f, 0x0f, 0xd3, 0x2f, 0x70, 0x06, 0x82, 0x86, 0x05, 0xac, 0x8d, 0xee, 0x85,
|
||||||
0x43, 0xd7, 0x36, 0xc5, 0xd1, 0xf7, 0x4b, 0xac, 0x7d, 0x13, 0x7c, 0x9e, 0x09, 0x12, 0xde, 0x77,
|
0xae, 0xad, 0xb7, 0xa3, 0x6f, 0x85, 0x58, 0xd6, 0x26, 0x64, 0x3c, 0x73, 0xb7, 0xbd, 0xef, 0x3c,
|
||||||
0x1e, 0x62, 0x1b, 0x0a, 0x64, 0x76, 0x33, 0x9b, 0x85, 0x79, 0xee, 0x80, 0xb6, 0x90, 0x92, 0x4c,
|
0x44, 0x36, 0x14, 0x78, 0xea, 0x66, 0x36, 0x0b, 0xf3, 0xdc, 0x01, 0x65, 0x21, 0xe5, 0x98, 0x92,
|
||||||
0x49, 0xed, 0x84, 0x22, 0xc0, 0xc1, 0x44, 0xfe, 0x1d, 0x86, 0x8c, 0xcf, 0xb4, 0xdb, 0xa8, 0x28,
|
0xd6, 0x09, 0x45, 0x78, 0x83, 0x89, 0xfc, 0x3b, 0x0c, 0x19, 0x55, 0x69, 0x77, 0x51, 0x51, 0x06,
|
||||||
0xc3, 0x2f, 0x6b, 0x9a, 0xa5, 0xf7, 0xa9, 0xa5, 0xd0, 0xaa, 0x54, 0x26, 0x55, 0xe1, 0x11, 0xfa,
|
0x5f, 0xd6, 0xf4, 0x4a, 0xef, 0x53, 0x4b, 0x61, 0x4c, 0xa9, 0x4a, 0xaa, 0x82, 0x23, 0xf4, 0x1d,
|
||||||
0x0e, 0x5f, 0x7a, 0x1d, 0xd1, 0x97, 0x23, 0xb4, 0x9a, 0xec, 0x5f, 0xce, 0x8e, 0x08, 0xf2, 0x7b,
|
0xbe, 0xf2, 0x3a, 0xa2, 0x2f, 0x47, 0xe8, 0x34, 0xd9, 0xbb, 0x9c, 0xdd, 0x10, 0xe4, 0xf7, 0x4a,
|
||||||
0xa5, 0xff, 0xac, 0x52, 0xde, 0xcb, 0x07, 0x42, 0x5c, 0xe4, 0x41, 0xd8, 0x53, 0x69, 0xb0, 0x38,
|
0xfb, 0x59, 0x25, 0xbc, 0x97, 0x0f, 0x84, 0xb0, 0xc8, 0x83, 0xa8, 0xa7, 0xd2, 0x5f, 0x71, 0x5a,
|
||||||
0xb1, 0xa6, 0xb5, 0x28, 0x8d, 0x55, 0xb7, 0x0c, 0x81, 0x51, 0x9f, 0xa5, 0x4b, 0x30, 0xcf, 0x0e,
|
0x4d, 0x6b, 0x51, 0x9a, 0xaa, 0x6e, 0x19, 0xe2, 0xa2, 0x3e, 0xcb, 0x96, 0x60, 0x9c, 0x1d, 0x26,
|
||||||
0x93, 0xf4, 0xe6, 0xf2, 0xca, 0xca, 0xb3, 0x60, 0x16, 0xc2, 0xd3, 0x30, 0x87, 0x9f, 0xa7, 0x70,
|
0xe9, 0xcd, 0xe5, 0x95, 0x95, 0x67, 0xc1, 0x2c, 0x84, 0x9f, 0x61, 0x0e, 0x2f, 0x4f, 0xe1, 0x36,
|
||||||
0x1c, 0xa8, 0xbd, 0xc2, 0xa2, 0xa7, 0x0f, 0x57, 0xa1, 0x3a, 0x82, 0xe1, 0xbc, 0xf4, 0xcd, 0x4c,
|
0x50, 0x7b, 0x85, 0x05, 0x4f, 0x1f, 0xae, 0x42, 0x75, 0xba, 0xc2, 0x79, 0xe9, 0x99, 0x99, 0x86,
|
||||||
0xc3, 0x9c, 0x3b, 0x0d, 0xef, 0x41, 0x27, 0x99, 0xaf, 0xbd, 0xc6, 0x6b, 0x6f, 0xb4, 0x91, 0x58,
|
0x39, 0x77, 0x1a, 0xde, 0x83, 0x4a, 0x32, 0x5f, 0x7b, 0x8d, 0xd7, 0xde, 0x68, 0x23, 0xb1, 0x78,
|
||||||
0x3c, 0x6c, 0xba, 0xc0, 0x73, 0x2b, 0x9d, 0xd1, 0x8d, 0x09, 0xdd, 0xe3, 0x5a, 0x5b, 0x2b, 0xde,
|
0xd8, 0x74, 0x7d, 0xe7, 0x56, 0x3a, 0xa3, 0xcb, 0x10, 0x9a, 0xc7, 0xb5, 0xb6, 0x56, 0xbc, 0x77,
|
||||||
0x3b, 0xa2, 0x61, 0xe4, 0xfc, 0xba, 0xf6, 0x10, 0x04, 0x0d, 0xbb, 0x35, 0x18, 0xe1, 0x44, 0xc4,
|
0x44, 0xc1, 0xc8, 0xf9, 0x75, 0xed, 0x21, 0xc8, 0x19, 0x76, 0x6a, 0x30, 0x82, 0x89, 0x88, 0xf5,
|
||||||
0x7a, 0x09, 0xd7, 0x05, 0xfd, 0xf5, 0x65, 0x56, 0x7c, 0xa4, 0x31, 0xe6, 0x59, 0x9a, 0x20, 0xb7,
|
0x12, 0x8e, 0x0b, 0xfa, 0xeb, 0xcb, 0xac, 0xf8, 0x48, 0x63, 0xcc, 0xb3, 0x34, 0x41, 0x66, 0x41,
|
||||||
0x20, 0x87, 0x27, 0xf9, 0x7c, 0x5d, 0x9c, 0x6a, 0xde, 0x88, 0x2f, 0x28, 0x22, 0x87, 0x80, 0x4d,
|
0x0e, 0x4e, 0xf2, 0xf9, 0x9a, 0x38, 0xd5, 0xbc, 0x11, 0x5d, 0x50, 0xc4, 0x0d, 0x01, 0x93, 0x58,
|
||||||
0x2c, 0xd5, 0x4c, 0x0f, 0x69, 0x32, 0x14, 0x61, 0x7c, 0xf1, 0x09, 0x65, 0x51, 0x75, 0xc3, 0x56,
|
0x2a, 0x99, 0x1e, 0xd2, 0x64, 0x28, 0x82, 0xf8, 0xe2, 0x13, 0xaa, 0xa2, 0xea, 0xf2, 0xac, 0x70,
|
||||||
0x08, 0xb9, 0xef, 0x7d, 0xdb, 0xbc, 0x8d, 0x11, 0x2a, 0x45, 0x47, 0x66, 0x1c, 0x1d, 0xf8, 0xf7,
|
0x6d, 0xdf, 0xfb, 0xb6, 0x79, 0xd1, 0x22, 0x50, 0x8a, 0x8e, 0xa7, 0x38, 0x36, 0xf0, 0xef, 0xa7,
|
||||||
0xd3, 0x46, 0x87, 0xef, 0x63, 0x23, 0xdc, 0x41, 0x87, 0xa3, 0x05, 0xd3, 0x87, 0x33, 0xb9, 0x60,
|
0x8d, 0x0e, 0xdf, 0xc7, 0x46, 0xb0, 0x83, 0x0e, 0xc7, 0x0a, 0xa6, 0x0f, 0x67, 0x72, 0xc1, 0x1e,
|
||||||
0x9f, 0x34, 0x19, 0xbe, 0xa2, 0x67, 0xfd, 0x13, 0xae, 0xb6, 0x22, 0xfc, 0x01, 0xbb, 0xba, 0x32,
|
0x69, 0x32, 0x78, 0x45, 0xcf, 0xfa, 0x27, 0x1c, 0x6d, 0x45, 0xf0, 0x03, 0x76, 0x74, 0x65, 0x28,
|
||||||
0x14, 0x7e, 0xfd, 0xc0, 0xb4, 0xcc, 0xd8, 0x9b, 0xd8, 0x69, 0x42, 0x87, 0x15, 0x06, 0x79, 0x6b,
|
0xfc, 0xfa, 0x81, 0xc9, 0x94, 0xb1, 0x37, 0xb1, 0xd3, 0x84, 0x0e, 0x2b, 0xcc, 0xf1, 0xd6, 0x5c,
|
||||||
0x2e, 0x05, 0x45, 0x43, 0x85, 0xb7, 0x1c, 0xeb, 0x3c, 0x58, 0x30, 0x73, 0xce, 0x0f, 0x88, 0x12,
|
0x0a, 0x62, 0x85, 0x0a, 0x6f, 0x39, 0xd2, 0x79, 0xb0, 0x60, 0xd6, 0x9c, 0x1f, 0x10, 0x91, 0xb3,
|
||||||
0x5a, 0xc3, 0xf2, 0x87, 0x45, 0x98, 0x17, 0x43, 0x5b, 0xf4, 0x32, 0x0f, 0xb9, 0x1f, 0x18, 0x59,
|
0x86, 0xdd, 0x0f, 0x0b, 0x30, 0x2f, 0x86, 0xb6, 0xe8, 0x65, 0x1e, 0x72, 0x3f, 0x30, 0xb1, 0x86,
|
||||||
0x43, 0x0d, 0x6c, 0x84, 0x84, 0x49, 0xe2, 0x21, 0x16, 0x82, 0x06, 0xb5, 0xae, 0x05, 0x3a, 0x15,
|
0x12, 0xd8, 0x08, 0x08, 0x93, 0xc4, 0x43, 0x2c, 0x04, 0x0d, 0x6a, 0x5d, 0x0b, 0x73, 0x2a, 0xa6,
|
||||||
0x53, 0x00, 0x0b, 0x6c, 0x4e, 0xa2, 0x0a, 0x67, 0xac, 0xbe, 0x11, 0x57, 0xfb, 0x0b, 0xeb, 0x9c,
|
0x00, 0x06, 0xd8, 0x9c, 0x44, 0x15, 0xcc, 0x58, 0x7d, 0x23, 0x9e, 0xf6, 0x17, 0xd6, 0x38, 0xf3,
|
||||||
0x79, 0x06, 0x70, 0xef, 0x65, 0x8f, 0xdb, 0x24, 0x2c, 0xee, 0xd2, 0xd5, 0xb5, 0x98, 0x11, 0x21,
|
0x0c, 0xe0, 0xdc, 0xcb, 0xfe, 0xb6, 0x49, 0x58, 0xdc, 0xa5, 0xab, 0x6b, 0x31, 0x23, 0x42, 0x5a,
|
||||||
0x2d, 0x0b, 0xf5, 0x01, 0xa9, 0xec, 0xc3, 0x4b, 0x04, 0x67, 0x8f, 0x46, 0xff, 0x01, 0xdf, 0xc5,
|
0x16, 0xea, 0x03, 0x52, 0xd9, 0x83, 0x97, 0xc8, 0xcd, 0x1e, 0x8d, 0xfe, 0x03, 0xbe, 0x8b, 0x99,
|
||||||
0xcc, 0xd9, 0xab, 0xf7, 0xe9, 0x76, 0xac, 0x38, 0x4d, 0x2e, 0xa9, 0x12, 0x5a, 0xeb, 0xd9, 0x2a,
|
0xb3, 0x4f, 0xef, 0xd3, 0xed, 0x58, 0x71, 0x9a, 0x5c, 0x52, 0x25, 0xb4, 0xd6, 0xb3, 0x55, 0xc8,
|
||||||
0x68, 0xd1, 0x03, 0x68, 0xb9, 0xe1, 0x03, 0x88, 0xb9, 0xa1, 0x1a, 0xd7, 0x7a, 0x3d, 0xd2, 0x5c,
|
0xa2, 0x07, 0x90, 0x69, 0xc3, 0x07, 0xd0, 0x69, 0x43, 0x35, 0xae, 0xf5, 0x7a, 0xa4, 0x39, 0x78,
|
||||||
0x3c, 0x18, 0xbd, 0x32, 0xc5, 0xb7, 0x82, 0xc3, 0x47, 0x39, 0xf8, 0xc6, 0x5e, 0x36, 0xd6, 0x00,
|
0x30, 0x7a, 0x65, 0x62, 0x6e, 0x05, 0x77, 0x8f, 0x72, 0xf0, 0x8d, 0xbd, 0x6c, 0xac, 0x01, 0x7c,
|
||||||
0x5e, 0x27, 0xb7, 0x10, 0x91, 0x10, 0xc1, 0xc4, 0x81, 0x9e, 0xf1, 0x29, 0xc9, 0x74, 0xf9, 0xa8,
|
0x4e, 0x6e, 0x21, 0x20, 0x21, 0x5a, 0x88, 0xc3, 0x3c, 0xe3, 0x53, 0x12, 0xe9, 0xf2, 0x51, 0x83,
|
||||||
0x41, 0x67, 0xa3, 0x4a, 0x3d, 0x54, 0xa8, 0x18, 0xe9, 0x23, 0xca, 0xef, 0xb2, 0xb5, 0x51, 0xa3,
|
0xca, 0x46, 0x95, 0x7a, 0xa0, 0x50, 0x31, 0xd2, 0x47, 0x54, 0xdf, 0x65, 0x6b, 0xa3, 0x46, 0xe3,
|
||||||
0xf1, 0xd5, 0x4c, 0x34, 0x89, 0x34, 0xab, 0x53, 0x44, 0xec, 0x9d, 0xc6, 0x41, 0x72, 0x6d, 0x4a,
|
0xab, 0x99, 0x68, 0x12, 0x49, 0x56, 0xa7, 0x88, 0xd7, 0x3b, 0x8d, 0x83, 0xe4, 0xda, 0x94, 0x55,
|
||||||
0x2b, 0xea, 0x22, 0x10, 0x8c, 0x40, 0x93, 0x53, 0x88, 0x20, 0x3c, 0xf5, 0xc9, 0xb1, 0xbb, 0x08,
|
0xd4, 0x05, 0x20, 0x18, 0x81, 0x26, 0xa5, 0x10, 0x21, 0x78, 0xea, 0x93, 0x63, 0x67, 0x11, 0x4c,
|
||||||
0x26, 0xc6, 0x12, 0x0a, 0x15, 0x64, 0x47, 0x8a, 0x2b, 0xdc, 0x8e, 0x8a, 0x68, 0x2d, 0xfe, 0x12,
|
0x8c, 0xe5, 0x13, 0x2a, 0xc4, 0x8e, 0x14, 0x56, 0xb8, 0x1d, 0x15, 0xcf, 0x5a, 0xfc, 0x25, 0x2e,
|
||||||
0x9f, 0x5a, 0x7a, 0x16, 0xa9, 0x78, 0x75, 0x70, 0x19, 0x6a, 0xb2, 0x4a, 0xa2, 0xfe, 0xb3, 0x18,
|
0xb5, 0xf4, 0x2b, 0x52, 0xd1, 0xea, 0xe0, 0x30, 0xd4, 0x64, 0x94, 0x44, 0xfd, 0x67, 0xb1, 0x47,
|
||||||
0x24, 0x7d, 0x0e, 0xc7, 0xb5, 0x29, 0x88, 0x46, 0xaa, 0x49, 0x34, 0x4e, 0x98, 0xb4, 0x2b, 0x10,
|
0xfa, 0x1c, 0x8e, 0x6b, 0x53, 0x10, 0x8d, 0x54, 0x93, 0x68, 0x9c, 0x30, 0x69, 0x55, 0x20, 0x6a,
|
||||||
0x35, 0xd5, 0xe8, 0xe5, 0xf8, 0x3a, 0x65, 0x10, 0x6e, 0xf9, 0x45, 0x0e, 0x5f, 0x4d, 0x4e, 0xf8,
|
0xaa, 0xd1, 0xcb, 0xf1, 0x75, 0xca, 0x10, 0xdc, 0xf2, 0x8b, 0x1c, 0xbe, 0x9a, 0x9c, 0xf0, 0x3a,
|
||||||
0x1d, 0x19, 0x22, 0x1b, 0x7d, 0x02, 0x5c, 0xed, 0xb3, 0x67, 0xa0, 0x44, 0x40, 0xfa, 0x2c, 0x64,
|
0x32, 0x04, 0x36, 0xfa, 0x04, 0xb8, 0xda, 0x67, 0xcf, 0x40, 0x09, 0x80, 0xf4, 0x59, 0xc8, 0x96,
|
||||||
0x4b, 0x6d, 0xd3, 0x58, 0x06, 0xd7, 0xa0, 0xdb, 0x4b, 0xac, 0xc4, 0xb6, 0x31, 0x86, 0xbd, 0x94,
|
0xda, 0xa6, 0xb1, 0x0c, 0xae, 0x41, 0x92, 0x97, 0x58, 0x89, 0x2d, 0x63, 0x0c, 0x6b, 0x29, 0xef,
|
||||||
0xf7, 0x88, 0xc8, 0x59, 0xaf, 0xb8, 0xdb, 0xaf, 0xa4, 0xcb, 0x6e, 0xdf, 0x23, 0x62, 0xa4, 0x2e,
|
0x11, 0x81, 0xb3, 0x5e, 0x71, 0xb7, 0x5f, 0xc9, 0x96, 0xdd, 0xbe, 0x47, 0xb4, 0x48, 0x5d, 0xbc,
|
||||||
0x60, 0x7e, 0xba, 0x81, 0x5c, 0x6f, 0x60, 0x48, 0x5c, 0x7c, 0x71, 0xa8, 0x0c, 0x48, 0x39, 0x82,
|
0xfc, 0x74, 0x03, 0xb9, 0xde, 0xc0, 0x90, 0x78, 0xf8, 0xe2, 0x50, 0x99, 0x8f, 0x72, 0xfc, 0x0c,
|
||||||
0x86, 0xcc, 0x73, 0x94, 0x6f, 0x30, 0xdf, 0x6f, 0x98, 0x2d, 0x97, 0x76, 0xca, 0x5f, 0x66, 0x95,
|
0x99, 0xe5, 0x28, 0xdf, 0x60, 0xbc, 0xdf, 0x30, 0x5a, 0x2e, 0xad, 0x94, 0xbf, 0xcc, 0x26, 0x59,
|
||||||
0xac, 0x8f, 0xee, 0x33, 0x0c, 0x94, 0x6b, 0x36, 0xc9, 0xef, 0x89, 0x42, 0x94, 0xf6, 0x62, 0x56,
|
0x1f, 0xdd, 0x67, 0x98, 0x27, 0xd7, 0x2c, 0x92, 0xdf, 0x13, 0xf1, 0x27, 0xad, 0xc5, 0xac, 0x5a,
|
||||||
0xad, 0xcd, 0xff, 0xff, 0x2c, 0x94, 0x8d, 0xe9, 0x7d, 0x99, 0xb1, 0x72, 0xb8, 0xc9, 0x34, 0xd4,
|
0x9b, 0xff, 0xff, 0xd9, 0x27, 0x1b, 0xd3, 0xfb, 0x32, 0x53, 0xe5, 0x70, 0x93, 0x61, 0xa8, 0xd1,
|
||||||
0x68, 0xfb, 0x0b, 0x6d, 0x55, 0x8d, 0x36, 0xbe, 0xdc, 0x78, 0x39, 0xac, 0x99, 0x2d, 0x3f, 0x59,
|
0xf6, 0x17, 0x5a, 0xaa, 0x1a, 0x6d, 0x7c, 0xb9, 0xe9, 0x72, 0x58, 0x33, 0x5a, 0x7e, 0xb2, 0xe6,
|
||||||
0xf3, 0xcb, 0x26, 0xb4, 0xc9, 0x62, 0x19, 0xff, 0x76, 0x73, 0xdd, 0x6e, 0xd9, 0x04, 0xab, 0x16,
|
0x97, 0x4d, 0x68, 0x93, 0xbd, 0x32, 0xfe, 0xed, 0xe6, 0xba, 0xd5, 0xb2, 0x09, 0x56, 0x2d, 0x06,
|
||||||
0x13, 0x66, 0xb3, 0xaf, 0x91, 0x66, 0x8c, 0x38, 0x7a, 0xd2, 0xb4, 0x79, 0xa3, 0xed, 0xed, 0xa6,
|
0xcc, 0x66, 0x5f, 0x23, 0xcd, 0x14, 0x71, 0xf4, 0xa4, 0x61, 0xf3, 0x46, 0xcb, 0xdb, 0x4d, 0x0b,
|
||||||
0x85, 0x65, 0x1b, 0x5c, 0x6d, 0x55, 0xc2, 0x35, 0xab, 0x8f, 0x34, 0xab, 0x5c, 0xad, 0x95, 0x19,
|
0xcb, 0x16, 0xb8, 0xda, 0xaa, 0x84, 0x6b, 0x56, 0x1e, 0x69, 0x36, 0xb9, 0x5a, 0x2b, 0x33, 0x9a,
|
||||||
0x4d, 0xfc, 0xe9, 0xc8, 0x16, 0xda, 0x80, 0xed, 0xf1, 0x11, 0xcc, 0xc1, 0xe2, 0xd2, 0xc8, 0xad,
|
0xf8, 0xd3, 0x71, 0x2d, 0xb4, 0x01, 0xdb, 0xe3, 0x23, 0x18, 0x83, 0xc5, 0xa5, 0x89, 0x5b, 0xc3,
|
||||||
0xe1, 0xc1, 0x20, 0xd5, 0xb2, 0xa3, 0x8d, 0x26, 0x9e, 0xb9, 0xce, 0x17, 0x96, 0x0d, 0x3f, 0x3c,
|
0x7f, 0x41, 0x2a, 0x65, 0x47, 0x1b, 0x0d, 0x3c, 0x73, 0x9d, 0xe5, 0x2b, 0x1b, 0x7e, 0x78, 0xc4,
|
||||||
0x62, 0x12, 0xda, 0x3e, 0x42, 0xf6, 0xa2, 0xdf, 0x8d, 0xb4, 0x71, 0x96, 0x08, 0xb5, 0x69, 0x71,
|
0x20, 0xb4, 0x7d, 0x84, 0xec, 0x43, 0xbf, 0x1b, 0x69, 0xe3, 0x2c, 0x11, 0x6a, 0xd3, 0xde, 0x9c,
|
||||||
0xce, 0x55, 0xe9, 0x9b, 0x58, 0xef, 0xfe, 0xab, 0x80, 0xd7, 0xfb, 0xcd, 0x7c, 0xae, 0xd0, 0x43,
|
0xab, 0xd2, 0x37, 0xb1, 0xde, 0xfd, 0x57, 0x01, 0xaf, 0xf7, 0x9b, 0xf9, 0x5c, 0xa1, 0x87, 0x6a,
|
||||||
0x35, 0x21, 0x42, 0x0a, 0x3b, 0x26, 0x92, 0x3e, 0xa9, 0xcc, 0x20, 0x2f, 0x3e, 0x07, 0x91, 0xb1,
|
0x42, 0x84, 0x14, 0x76, 0x4c, 0x24, 0x7d, 0x52, 0x19, 0x41, 0x5e, 0x7c, 0x0e, 0x22, 0x63, 0x8f,
|
||||||
0xcf, 0x77, 0x71, 0xff, 0x39, 0xee, 0x15, 0x21, 0x91, 0x7c, 0xca, 0x79, 0xfb, 0xd9, 0x3e, 0x16,
|
0xef, 0xe2, 0xfe, 0x73, 0x9c, 0x2b, 0x42, 0x22, 0xf9, 0x94, 0xeb, 0xf6, 0xb3, 0x3d, 0x2c, 0x6a,
|
||||||
0xb5, 0x1d, 0xad, 0x02, 0x14, 0x58, 0xac, 0x9c, 0x1f, 0x3e, 0x82, 0x7d, 0x73, 0x63, 0xd0, 0xd5,
|
0x3b, 0x5a, 0x85, 0x27, 0xb0, 0x58, 0x35, 0x3f, 0x7c, 0x04, 0xfb, 0xe6, 0xc6, 0xa0, 0xab, 0x31,
|
||||||
0x98, 0xb4, 0x21, 0x95, 0x21, 0x79, 0xd6, 0xda, 0xac, 0xfe, 0x88, 0xdb, 0x26, 0xb5, 0x57, 0x82,
|
0x69, 0x43, 0x2a, 0x03, 0xf2, 0xac, 0xb5, 0x59, 0xfd, 0x11, 0xb7, 0x4d, 0x6a, 0xaf, 0x04, 0x07,
|
||||||
0x83, 0x09, 0xaa, 0xe3, 0x0e, 0xf1, 0x77, 0xc4, 0xa2, 0x84, 0x4c, 0xe6, 0xd3, 0x1d, 0x0b, 0x5a,
|
0x13, 0x54, 0xc7, 0x1d, 0xe2, 0xef, 0x88, 0x45, 0x09, 0x99, 0xcc, 0xa7, 0x3b, 0x16, 0xb4, 0x9c,
|
||||||
0x4e, 0x1b, 0xa6, 0x58, 0x7a, 0xa7, 0x7c, 0xf9, 0x09, 0x03, 0x69, 0xb1, 0x4c, 0xf6, 0x2f, 0x65,
|
0x36, 0x4c, 0xb1, 0xf4, 0x4e, 0xf9, 0xf2, 0x13, 0xe6, 0xd1, 0x62, 0x99, 0xec, 0x5f, 0xca, 0x20,
|
||||||
0x18, 0x18, 0xe2, 0xad, 0xae, 0x2c, 0xc5, 0x69, 0xff, 0x46, 0xac, 0x85, 0x94, 0xe9, 0xc9, 0x32,
|
0x30, 0xc4, 0x5b, 0x5d, 0x59, 0x8a, 0xd1, 0xfe, 0x8d, 0x58, 0x0b, 0x29, 0xae, 0x93, 0x65, 0x6c,
|
||||||
0xb6, 0x1a, 0xd8, 0x6c, 0x40, 0xcd, 0x13, 0x9a, 0xe5, 0xc5, 0xa5, 0xe1, 0x1c, 0x46, 0x3f, 0x8f,
|
0x33, 0xb0, 0xd9, 0x7c, 0x9a, 0x27, 0x34, 0xcb, 0x8b, 0x4b, 0xc3, 0x35, 0x8c, 0x7e, 0x1e, 0xe5,
|
||||||
0x72, 0xe9, 0x51, 0xaf, 0x7a, 0xa4, 0xd6, 0x95, 0x0d, 0x35, 0x1b, 0x50, 0x3f, 0xcf, 0x7c, 0x5a,
|
0xd2, 0x9f, 0x5e, 0xf5, 0x48, 0xad, 0x2b, 0x0b, 0x6a, 0x36, 0x9f, 0x7e, 0x9e, 0xf1, 0xb4, 0xb2,
|
||||||
0xd9, 0x48, 0x34, 0x37, 0x2b, 0x4b, 0x07, 0x7a, 0x74, 0x80, 0x01, 0xcf, 0xee, 0xcd, 0xc9, 0x31,
|
0x90, 0x68, 0x6e, 0x56, 0x96, 0x0e, 0xf4, 0xd8, 0x00, 0x03, 0x9e, 0xdd, 0x9b, 0x93, 0x63, 0xba,
|
||||||
0xdd, 0x11, 0x1c, 0x78, 0x48, 0x39, 0x63, 0x95, 0x31, 0x6a, 0x4c, 0x04, 0xab, 0xbd, 0x1b, 0x64,
|
0x23, 0x38, 0xec, 0x90, 0x72, 0xc5, 0x2a, 0x23, 0xd4, 0x98, 0x08, 0x56, 0x7b, 0x37, 0xc8, 0x22,
|
||||||
0x91, 0x11, 0xb8, 0x46, 0x9d, 0xc3, 0x7a, 0x7f, 0x7d, 0xbd, 0xbf, 0xfe, 0x46, 0xcf, 0x3b, 0xc3,
|
0x23, 0x6c, 0x8d, 0x3a, 0x87, 0xf5, 0xfe, 0xfa, 0x7a, 0x7f, 0xfd, 0x8d, 0x7e, 0x77, 0x86, 0x31,
|
||||||
0x1c, 0xfd, 0x58, 0x78, 0xc3, 0x5a, 0xd3, 0x95, 0xca, 0x25, 0xf1, 0x84, 0xb7, 0x9d, 0x08, 0xa2,
|
0xfa, 0xb1, 0xf0, 0x85, 0xb5, 0xa6, 0x2b, 0x95, 0x49, 0xe2, 0x09, 0x5f, 0x3b, 0x11, 0x42, 0x6b,
|
||||||
0x35, 0xe5, 0x05, 0x95, 0xeb, 0xf5, 0xa5, 0x7e, 0x74, 0x4f, 0x8d, 0xed, 0x14, 0x60, 0xa5, 0x6e,
|
0xca, 0x0b, 0x2a, 0xd7, 0xeb, 0x4b, 0xbd, 0xe8, 0x9e, 0x1a, 0xdb, 0x29, 0xc0, 0x4a, 0xdd, 0xf0,
|
||||||
0xf8, 0x29, 0x24, 0x03, 0xcf, 0x1a, 0x5c, 0xfe, 0x17, 0x0c, 0xae, 0x6d, 0x81, 0xe9, 0xf4, 0xf1,
|
0x53, 0x48, 0x06, 0x9e, 0x35, 0xb8, 0xfc, 0x2f, 0x18, 0x5c, 0xdb, 0x02, 0xd3, 0xe9, 0xe3, 0x11,
|
||||||
0x88, 0x88, 0xd3, 0x39, 0xfe, 0xde, 0x6a, 0xbd, 0x15, 0xf5, 0x25, 0x9a, 0xd7, 0x2f, 0xc1, 0xf2,
|
0x11, 0xa7, 0x73, 0xfc, 0xbd, 0xd5, 0x7a, 0x2b, 0xea, 0x4b, 0x34, 0xaf, 0x5f, 0x82, 0xe5, 0x55,
|
||||||
0xaa, 0xaa, 0xe2, 0x93, 0x49, 0x08, 0xc4, 0xb5, 0x38, 0x78, 0xe1, 0xf1, 0x35, 0xd9, 0x97, 0x87,
|
0x55, 0x45, 0x27, 0x93, 0x10, 0x88, 0x6b, 0x71, 0xf0, 0xc2, 0xe3, 0x6b, 0xb2, 0x2f, 0x0f, 0xa7,
|
||||||
0x53, 0x40, 0x65, 0x38, 0x6c, 0x46, 0x49, 0x5b, 0x8f, 0x37, 0x8c, 0x0e, 0x33, 0x78, 0x1a, 0xe1,
|
0x80, 0xca, 0x70, 0xd8, 0x8c, 0x91, 0xb6, 0x1e, 0x6f, 0x18, 0x1d, 0x66, 0xf0, 0x34, 0xc2, 0x87,
|
||||||
0x43, 0x9e, 0x70, 0xa2, 0xa2, 0x49, 0x3c, 0x8e, 0x4a, 0xd5, 0xd5, 0x25, 0x4f, 0x08, 0xcf, 0x5e,
|
0x3c, 0xe1, 0x44, 0xc5, 0x92, 0x78, 0x1c, 0x95, 0xaa, 0xab, 0x4b, 0x9e, 0x10, 0x9e, 0xbd, 0x38,
|
||||||
0x1c, 0xa1, 0x1c, 0x34, 0x4e, 0x25, 0x98, 0xb0, 0x2b, 0xc3, 0xe8, 0xf2, 0x08, 0xef, 0x3c, 0x63,
|
0x42, 0x39, 0x68, 0x9c, 0x4a, 0x30, 0x61, 0x57, 0x66, 0xd1, 0xe5, 0x11, 0xde, 0x79, 0xc6, 0x58,
|
||||||
0x2c, 0xf3, 0x30, 0x3e, 0xe9, 0xec, 0x74, 0xc3, 0xee, 0xce, 0x93, 0x63, 0x51, 0xae, 0x22, 0xdf,
|
0xe6, 0x61, 0x7c, 0xd2, 0xd9, 0xe9, 0x86, 0xdd, 0x9d, 0x27, 0xc7, 0xa2, 0x1c, 0x45, 0xbe, 0x97,
|
||||||
0xcb, 0x80, 0x22, 0xdc, 0x6f, 0x15, 0x7c, 0x69, 0xb8, 0xf3, 0xdc, 0xbb, 0xee, 0x64, 0xc3, 0x65,
|
0xe1, 0x44, 0xb8, 0xdf, 0x2a, 0xf4, 0xd2, 0x70, 0xe7, 0xb9, 0x77, 0xdd, 0xc9, 0x86, 0xcb, 0x6e,
|
||||||
0xb7, 0xb3, 0xde, 0x70, 0xae, 0x10, 0xe8, 0x4d, 0x21, 0x89, 0xa9, 0xf0, 0xbd, 0xb4, 0x66, 0xda,
|
0x67, 0xbd, 0xe1, 0x5c, 0x21, 0xcc, 0x9b, 0x42, 0x12, 0x53, 0xe1, 0x79, 0x69, 0xcd, 0xb4, 0x9d,
|
||||||
0x4e, 0xe3, 0xb9, 0xad, 0xc1, 0x8c, 0x9a, 0xbe, 0x89, 0x25, 0x09, 0x64, 0x30, 0x51, 0x15, 0x1f,
|
0xc6, 0x73, 0x5b, 0x83, 0x19, 0x35, 0x7d, 0x13, 0x4b, 0x12, 0xc8, 0x60, 0xa2, 0x2a, 0x3a, 0x14,
|
||||||
0x0a, 0xad, 0x5c, 0xd4, 0x6e, 0x22, 0xfd, 0xb2, 0xcc, 0x1a, 0x57, 0x65, 0x7b, 0xfc, 0x91, 0xf1,
|
0x5a, 0xb9, 0xa8, 0xdd, 0x44, 0xfa, 0x65, 0x99, 0x35, 0xae, 0xca, 0xf6, 0xe8, 0x23, 0xe3, 0xc7,
|
||||||
0x63, 0xc4, 0xf9, 0xd7, 0x0f, 0xe2, 0x86, 0xf3, 0x54, 0xac, 0x10, 0x79, 0x7f, 0x37, 0xf5, 0xc1,
|
0x88, 0xf3, 0xaf, 0x1f, 0xc4, 0x0d, 0xe7, 0xa9, 0x48, 0x21, 0xf2, 0xfe, 0x6e, 0x6a, 0x83, 0x33,
|
||||||
0x99, 0x87, 0x08, 0xc4, 0xa5, 0x05, 0xbe, 0x30, 0x7c, 0x50, 0x0d, 0xe9, 0xf6, 0x0f, 0x55, 0xa4,
|
0x0f, 0xf1, 0x87, 0x4b, 0xfb, 0x7b, 0x61, 0xf6, 0xa0, 0x1a, 0xd2, 0xad, 0x1f, 0xaa, 0x38, 0x17,
|
||||||
0x0b, 0x2d, 0xca, 0x85, 0x53, 0xbb, 0xf5, 0x9f, 0x98, 0xc9, 0xe7, 0x5d, 0xfa, 0xe5, 0x7e, 0x3d,
|
0x5a, 0x8c, 0x0b, 0xa7, 0x76, 0xeb, 0x3f, 0x31, 0x93, 0xcf, 0xbb, 0xf4, 0xcb, 0xfd, 0x7a, 0xde,
|
||||||
0xef, 0xda, 0x3f, 0xe2, 0xe0, 0xd0, 0x75, 0xf8, 0xa8, 0x5d, 0xfc, 0x02, 0xff, 0xb7, 0x44, 0x07,
|
0xb5, 0x7f, 0xc4, 0xa1, 0xa1, 0xeb, 0xf0, 0x51, 0xbb, 0xf8, 0x05, 0xfe, 0x6f, 0x89, 0x0d, 0xc8,
|
||||||
0xe4, 0x9b, 0xe2, 0xa2, 0x54, 0x0a, 0x8d, 0xaa, 0x27, 0x69, 0xff, 0xa2, 0x91, 0xad, 0xa4, 0x2d,
|
0x37, 0xc5, 0x45, 0xa9, 0xef, 0x19, 0x55, 0x4f, 0xd2, 0xfe, 0x45, 0x23, 0x57, 0x49, 0x5b, 0x5e,
|
||||||
0xb3, 0x89, 0xac, 0x3d, 0x68, 0xab, 0xcd, 0xb5, 0x86, 0xf2, 0x25, 0x2d, 0x92, 0xa6, 0x72, 0x19,
|
0x13, 0x59, 0x7b, 0xd0, 0x56, 0x9b, 0x6b, 0x0d, 0xe5, 0x4b, 0x5a, 0x1c, 0x4d, 0xe5, 0x30, 0x5c,
|
||||||
0x2e, 0x07, 0x04, 0xef, 0xed, 0xe1, 0xd9, 0xf9, 0xba, 0x66, 0x93, 0x2c, 0x3c, 0x58, 0xd8, 0x7c,
|
0x0e, 0x08, 0xbe, 0xdb, 0xc3, 0xb3, 0xf3, 0x75, 0xcd, 0x22, 0x59, 0xf8, 0xaf, 0xb0, 0xf1, 0x36,
|
||||||
0x1b, 0x64, 0xb0, 0x30, 0x7e, 0x84, 0x92, 0x74, 0x98, 0x23, 0x63, 0x2a, 0xa8, 0xcf, 0x4a, 0xe4,
|
0xc8, 0x60, 0x61, 0xfa, 0x08, 0x15, 0xe9, 0x30, 0x47, 0xbe, 0x54, 0x50, 0x9f, 0x95, 0xc8, 0xa3,
|
||||||
0x51, 0xd4, 0xf2, 0xdb, 0x08, 0xe7, 0xab, 0xb0, 0x16, 0x3a, 0x18, 0x1d, 0xb1, 0xa1, 0x35, 0xd4,
|
0xa8, 0x65, 0xb7, 0x11, 0xae, 0x57, 0x61, 0x2d, 0x70, 0x30, 0x3a, 0x62, 0x33, 0x6b, 0x48, 0xfa,
|
||||||
0x01, 0x43, 0xc3, 0x4e, 0x28, 0xd4, 0x16, 0xa2, 0x2e, 0x44, 0x92, 0xe4, 0xaf, 0xb9, 0x82, 0xf2,
|
0x87, 0x86, 0x95, 0x50, 0xa8, 0x2d, 0x44, 0x5d, 0x88, 0x24, 0xc9, 0x5f, 0x73, 0x05, 0xe5, 0x8b,
|
||||||
0xc5, 0xa2, 0x64, 0x36, 0xf3, 0x27, 0xcd, 0xa9, 0x92, 0xa7, 0xcc, 0xa9, 0xc0, 0x36, 0x7b, 0x5b,
|
0x45, 0xc9, 0x6c, 0xe6, 0x4f, 0x1a, 0x53, 0x25, 0x4f, 0x19, 0x53, 0x81, 0x6d, 0xf6, 0xb6, 0xfc,
|
||||||
0x7e, 0xa2, 0xcc, 0x9e, 0xb4, 0x01, 0x27, 0xc3, 0xc2, 0x15, 0xce, 0x8b, 0xb9, 0x0b, 0xe7, 0xc6,
|
0x44, 0x19, 0x3d, 0x69, 0x03, 0x4e, 0x86, 0x85, 0x2b, 0x5c, 0x17, 0x73, 0x17, 0xae, 0x8d, 0xc3,
|
||||||
0x61, 0x83, 0x47, 0xc8, 0x89, 0x47, 0xe8, 0x26, 0xeb, 0xf5, 0xa8, 0x66, 0xef, 0xa5, 0x19, 0x52,
|
0x06, 0x8f, 0x90, 0x13, 0x8f, 0xd0, 0x4d, 0xd6, 0xeb, 0x51, 0xcd, 0xda, 0x4b, 0x33, 0xa3, 0x8a,
|
||||||
0xc5, 0xcf, 0x30, 0xa4, 0x0a, 0x9e, 0x61, 0x48, 0x95, 0xf2, 0x86, 0xd0, 0x6b, 0x7e, 0xec, 0x8a,
|
0x9f, 0x61, 0x46, 0x15, 0x3c, 0xc3, 0x8c, 0x2a, 0xe5, 0x0d, 0xa1, 0xd7, 0xfc, 0xd8, 0x15, 0xdf,
|
||||||
0xef, 0xf4, 0xd8, 0x0f, 0xd6, 0xfa, 0x62, 0xa7, 0xbc, 0x86, 0x2c, 0x1e, 0x9d, 0xab, 0xdd, 0xd0,
|
0xe9, 0xb1, 0x1f, 0xac, 0xf5, 0xc5, 0x4e, 0x79, 0x0d, 0x59, 0x3c, 0x3a, 0x57, 0xbb, 0xa1, 0x69,
|
||||||
0x74, 0xd6, 0xe5, 0x06, 0x55, 0x2e, 0x47, 0x13, 0x4d, 0x8c, 0x8a, 0x98, 0x7f, 0x49, 0x28, 0xc2,
|
0xac, 0xcb, 0x0d, 0xaa, 0x1c, 0x8e, 0x26, 0x9a, 0x18, 0x15, 0x11, 0xff, 0x92, 0x50, 0x04, 0x25,
|
||||||
0x12, 0x72, 0xec, 0xbf, 0xe5, 0x4d, 0x5c, 0x44, 0x44, 0xa0, 0x55, 0x4e, 0x53, 0xf4, 0x44, 0xc6,
|
0xe4, 0xc8, 0x7f, 0xcb, 0x9b, 0xb8, 0x88, 0x88, 0x40, 0xab, 0x5c, 0xa6, 0xe8, 0x89, 0x8c, 0xb6,
|
||||||
0x5b, 0x22, 0x40, 0xdb, 0x42, 0xbe, 0x09, 0xed, 0xb8, 0x8a, 0x44, 0x62, 0xa2, 0xe5, 0xdd, 0x5d,
|
0x44, 0x80, 0xb6, 0x85, 0x6c, 0x13, 0xda, 0x71, 0x15, 0x69, 0xc4, 0x44, 0xcb, 0xbb, 0xbb, 0xee,
|
||||||
0x77, 0x13, 0x14, 0x60, 0x21, 0x3d, 0xb1, 0xdd, 0xe6, 0x7e, 0xc3, 0x67, 0x6e, 0x33, 0xf4, 0x20,
|
0x26, 0x28, 0xc0, 0x42, 0x7a, 0x62, 0xbb, 0xcd, 0xfd, 0x86, 0xc7, 0xdc, 0x66, 0xe8, 0x41, 0xec,
|
||||||
0xfa, 0xb4, 0xbe, 0x38, 0xf4, 0xfb, 0x51, 0xe8, 0xf9, 0x39, 0x7a, 0xa4, 0xb1, 0x65, 0x64, 0xb4,
|
0x69, 0x7d, 0x71, 0xe8, 0xf7, 0xa3, 0xd0, 0xf3, 0x73, 0xf4, 0x48, 0x63, 0xcb, 0xc8, 0x68, 0x6b,
|
||||||
0xb5, 0x8c, 0x9e, 0x02, 0x44, 0xf8, 0x99, 0x6f, 0x6e, 0x2e, 0x4d, 0x86, 0x5b, 0xca, 0x7d, 0x3d,
|
0x19, 0x3d, 0x05, 0x88, 0xf0, 0x32, 0xdf, 0xdc, 0x5c, 0x9a, 0x0c, 0xb7, 0x94, 0xf3, 0x7a, 0x78,
|
||||||
0x3c, 0x6f, 0x6f, 0x01, 0xfe, 0xe2, 0x9b, 0x5b, 0x20, 0xea, 0x68, 0xd8, 0x0a, 0x03, 0xec, 0x24,
|
0xde, 0xde, 0x02, 0xbc, 0xc5, 0x37, 0xb7, 0x40, 0xd4, 0xd1, 0xb0, 0x15, 0x06, 0xd8, 0x45, 0xac,
|
||||||
0x56, 0xda, 0x3a, 0x36, 0x1a, 0xae, 0x82, 0xb6, 0x89, 0xac, 0xc6, 0xc8, 0x04, 0x5d, 0x01, 0x53,
|
0xb4, 0x74, 0x6c, 0x34, 0x5c, 0x85, 0x6c, 0x13, 0x39, 0x8d, 0x91, 0x07, 0xba, 0x02, 0xa6, 0x7a,
|
||||||
0x3d, 0xbf, 0xd0, 0xce, 0x57, 0x42, 0x3d, 0x65, 0xd5, 0xed, 0x33, 0x86, 0x72, 0xf2, 0x3b, 0xaa,
|
0x76, 0xa1, 0x9d, 0xaf, 0x84, 0x7e, 0xdc, 0xaa, 0x5b, 0x67, 0x0c, 0xe5, 0xe4, 0x77, 0x54, 0x57,
|
||||||
0xab, 0x61, 0xfd, 0xd5, 0x8b, 0x4d, 0xaf, 0x9e, 0xe9, 0xec, 0xff, 0x79, 0xb5, 0x8e, 0xfe, 0x96,
|
0xc3, 0xfa, 0xab, 0x17, 0x9b, 0x5e, 0x3d, 0xd3, 0xd9, 0xff, 0xf3, 0x6a, 0x1d, 0xfd, 0x2d, 0xa5,
|
||||||
0xd2, 0x35, 0x37, 0xb2, 0x1c, 0xa9, 0xa6, 0x74, 0x93, 0x8e, 0x02, 0x96, 0x05, 0x8f, 0xda, 0xc6,
|
0x46, 0x6e, 0xe4, 0x38, 0x52, 0x4d, 0xe9, 0x06, 0x1d, 0x05, 0xec, 0x0a, 0x1e, 0xb5, 0x8c, 0xd9,
|
||||||
0x6c, 0x1c, 0x51, 0xc3, 0xa8, 0x23, 0x7c, 0xc2, 0xca, 0xa5, 0x05, 0x34, 0x17, 0xf7, 0x43, 0x2d,
|
0x38, 0xa2, 0x86, 0x49, 0x47, 0xf8, 0x84, 0x8d, 0x4b, 0x0b, 0x68, 0x2e, 0xee, 0x87, 0x5a, 0xc8,
|
||||||
0x68, 0x2f, 0x2f, 0x74, 0x5d, 0x32, 0x5f, 0xf9, 0x53, 0x7c, 0xe6, 0x9a, 0x9b, 0xae, 0x0f, 0xad,
|
0x5e, 0x5e, 0xe8, 0xba, 0x64, 0xbe, 0xf2, 0xa6, 0xf8, 0xcc, 0x35, 0x37, 0x1d, 0x1f, 0x5a, 0xed,
|
||||||
0x96, 0x46, 0x4f, 0xaf, 0xff, 0xb3, 0x9a, 0x51, 0x7b, 0x41, 0x74, 0xc0, 0xb3, 0xf6, 0xa1, 0xe6,
|
0x8c, 0x9e, 0x5e, 0xff, 0x67, 0x35, 0xa3, 0xf6, 0x82, 0xe8, 0x80, 0x67, 0xed, 0x43, 0xcd, 0x25,
|
||||||
0x94, 0xf1, 0x27, 0xb7, 0xa3, 0xc5, 0xc5, 0xe3, 0x4f, 0xee, 0x0a, 0x4d, 0x6c, 0x18, 0x6e, 0xda,
|
0xe3, 0x4f, 0x6e, 0x47, 0x8b, 0x83, 0xc7, 0x9f, 0xdc, 0x15, 0x9a, 0xd8, 0x30, 0xdc, 0xb4, 0x19,
|
||||||
0x0c, 0x1c, 0xa8, 0x52, 0x25, 0xd3, 0x38, 0x3f, 0x4d, 0x0b, 0x10, 0xe7, 0x2f, 0xd6, 0xd4, 0xe0,
|
0x38, 0x50, 0xa5, 0x4a, 0xa6, 0x71, 0x7e, 0x9a, 0xc6, 0x1d, 0xce, 0x5f, 0xac, 0xa9, 0xc1, 0xb1,
|
||||||
0x58, 0x43, 0x4f, 0xde, 0x69, 0x3b, 0xd4, 0xf9, 0x7d, 0xeb, 0x70, 0x0c, 0xc5, 0xfa, 0x46, 0x30,
|
0x86, 0x0a, 0xbc, 0xd3, 0x76, 0xa8, 0xf3, 0xfb, 0xd6, 0xe1, 0x18, 0x3a, 0xf3, 0x8d, 0x60, 0x56,
|
||||||
0x2b, 0x15, 0xec, 0xad, 0x4d, 0x47, 0xed, 0x4d, 0x37, 0xb4, 0xf2, 0x1b, 0x9b, 0x7f, 0x97, 0x36,
|
0xea, 0xce, 0x5b, 0x9b, 0x8e, 0xda, 0x9b, 0x6e, 0x28, 0xdc, 0x37, 0x36, 0xff, 0x2e, 0x6d, 0xe2,
|
||||||
0x71, 0x19, 0x12, 0x11, 0x86, 0xeb, 0x8d, 0xfa, 0xa8, 0xa3, 0x7f, 0x56, 0x4b, 0x9d, 0xc5, 0xc3,
|
0x32, 0xa4, 0x21, 0x0c, 0xd7, 0x1b, 0xf5, 0x51, 0x47, 0xff, 0xac, 0x96, 0x3a, 0x8b, 0x87, 0xbb,
|
||||||
0xdd, 0xfe, 0x7a, 0xb4, 0xc1, 0xca, 0x65, 0x7b, 0xbb, 0xd3, 0x11, 0x95, 0x3c, 0x17, 0xa6, 0x29,
|
0xfd, 0xf5, 0x68, 0x83, 0x01, 0xcb, 0xf6, 0x76, 0xa7, 0x23, 0x2a, 0x79, 0x2e, 0xac, 0x4e, 0x86,
|
||||||
0xc3, 0x07, 0xe2, 0x39, 0x6a, 0x03, 0xd6, 0x6d, 0x5f, 0x1c, 0x84, 0xce, 0x6a, 0x3e, 0x0f, 0xab,
|
0x0f, 0xc4, 0x73, 0xd4, 0x06, 0xac, 0x9b, 0xb5, 0x38, 0x08, 0x9c, 0xd5, 0x7c, 0x1e, 0x56, 0xcf,
|
||||||
0xe7, 0x50, 0x65, 0x0f, 0x5b, 0x37, 0x4b, 0x9b, 0xa9, 0xf3, 0x19, 0x3b, 0xfb, 0xac, 0xad, 0x95,
|
0xa1, 0xca, 0x1e, 0xb6, 0x6e, 0x96, 0x36, 0x53, 0xe7, 0x33, 0x76, 0xf6, 0x59, 0x5b, 0x2b, 0x23,
|
||||||
0x31, 0xf1, 0x2a, 0x82, 0x29, 0xcb, 0x69, 0x81, 0x46, 0xda, 0x75, 0xf9, 0x4e, 0x46, 0xbb, 0xcd,
|
0xe2, 0x55, 0x04, 0x53, 0x96, 0xd3, 0x02, 0x8d, 0xb4, 0xeb, 0xf2, 0x9d, 0x8c, 0x75, 0x9b, 0xa9,
|
||||||
0x54, 0x64, 0x65, 0x25, 0x79, 0x91, 0x91, 0x7b, 0x38, 0x68, 0x8f, 0x5b, 0x27, 0x98, 0x1a, 0x5d,
|
0xb8, 0xca, 0x4a, 0xf2, 0x22, 0xe3, 0xf6, 0x70, 0xc8, 0x1e, 0xb7, 0x4e, 0x30, 0x35, 0xba, 0x62,
|
||||||
0x31, 0xb3, 0x44, 0xdd, 0x74, 0xb6, 0x3a, 0xd9, 0x71, 0x8d, 0x0e, 0xa8, 0xc5, 0x93, 0x46, 0x06,
|
0x66, 0x89, 0xba, 0xe9, 0x6c, 0x75, 0xb2, 0xe3, 0x1a, 0x1d, 0x50, 0x8b, 0x26, 0x8d, 0xfc, 0x1d,
|
||||||
0x8f, 0xec, 0xf8, 0xb0, 0x0f, 0x6b, 0x59, 0xaa, 0xbb, 0x89, 0x7d, 0x73, 0x38, 0x17, 0x4f, 0x27,
|
0xd9, 0xf1, 0x61, 0x1f, 0xb6, 0xb2, 0x54, 0x77, 0x13, 0xfb, 0xe6, 0x70, 0x26, 0x9e, 0x4e, 0xf6,
|
||||||
0x7b, 0xaf, 0x91, 0x9d, 0xc5, 0x7d, 0x49, 0x34, 0xf1, 0xdb, 0xef, 0xb5, 0x88, 0xd0, 0xd9, 0xb1,
|
0x5e, 0x23, 0x3b, 0x8b, 0xfb, 0x92, 0x68, 0xe2, 0xb7, 0xdf, 0x6b, 0xf1, 0xa0, 0xb3, 0x63, 0xe5,
|
||||||
0xf2, 0x51, 0x7b, 0xa8, 0x08, 0x99, 0x36, 0x62, 0x95, 0x88, 0xc2, 0x68, 0xaa, 0x47, 0xba, 0x9e,
|
0xa1, 0xf6, 0x50, 0x11, 0x32, 0x6d, 0xc4, 0x2a, 0x11, 0x85, 0xd1, 0x54, 0x8f, 0x73, 0x3d, 0x35,
|
||||||
0x1a, 0x8f, 0x91, 0xc5, 0x45, 0x7f, 0x9c, 0x9b, 0x8f, 0x2b, 0x95, 0x7a, 0xae, 0x55, 0x0a, 0xb2,
|
0x1e, 0x23, 0x87, 0x8b, 0xfe, 0x38, 0x37, 0x1f, 0x57, 0x2a, 0xf5, 0x5c, 0xab, 0x14, 0x64, 0xe5,
|
||||||
0xf2, 0x7e, 0xe3, 0xc0, 0xc6, 0x85, 0x1e, 0x02, 0x32, 0x57, 0x41, 0x8b, 0x13, 0xb6, 0x38, 0xe2,
|
0xfd, 0xc6, 0x61, 0x8d, 0x0b, 0x3d, 0x00, 0x64, 0xae, 0x42, 0x16, 0x27, 0x6c, 0x4c, 0xc4, 0x11,
|
||||||
0x18, 0xd1, 0x3e, 0xd1, 0x62, 0x92, 0x5f, 0x38, 0x1c, 0x28, 0xbd, 0x3b, 0x6b, 0xd3, 0x1f, 0x8b,
|
0xa2, 0x7d, 0xa2, 0xc5, 0x24, 0xbf, 0x70, 0x38, 0x50, 0x7a, 0x77, 0xd6, 0xa6, 0x3f, 0x16, 0x55,
|
||||||
0xab, 0xad, 0x22, 0x67, 0x1b, 0x69, 0x4e, 0x38, 0x4e, 0xb1, 0x26, 0x30, 0xb1, 0x16, 0xd1, 0x8a,
|
0x5b, 0xc5, 0xcd, 0x36, 0x92, 0x9c, 0x70, 0x94, 0x62, 0x4d, 0x60, 0x62, 0x2d, 0xa2, 0x15, 0x07,
|
||||||
0xc3, 0xe5, 0x73, 0x5a, 0xa3, 0x88, 0xc8, 0x9a, 0xfb, 0x5f, 0x16, 0x1d, 0xfb, 0xc1, 0x76, 0xc6,
|
0xcb, 0xe7, 0xa4, 0x46, 0x11, 0x91, 0x35, 0xf7, 0xbf, 0x2c, 0x3a, 0xf6, 0x83, 0xed, 0x8c, 0x77,
|
||||||
0xbb, 0xfd, 0xcf, 0xee, 0xea, 0xf4, 0x63, 0x52, 0x04, 0xf7, 0x52, 0xf5, 0x4d, 0x5c, 0xd3, 0xec,
|
0xfb, 0x9f, 0xdd, 0xd5, 0xe9, 0xc7, 0xa4, 0x08, 0xee, 0xa5, 0xea, 0x9b, 0xb8, 0xa6, 0xd9, 0x0d,
|
||||||
0x86, 0x48, 0x9f, 0xa5, 0x85, 0xe9, 0xe9, 0x9d, 0x8a, 0xee, 0x3c, 0xdf, 0xd7, 0x7a, 0x14, 0xa3,
|
0x91, 0x3e, 0x4b, 0x0b, 0xd3, 0xd3, 0x3b, 0x15, 0xdd, 0x79, 0xbe, 0xaf, 0xf5, 0x28, 0x46, 0x69,
|
||||||
0xb4, 0x9d, 0x2f, 0x9d, 0x9e, 0x0c, 0x5f, 0xca, 0x4a, 0xd0, 0x0c, 0x01, 0xb0, 0xa6, 0x21, 0xd1,
|
0x3b, 0x5f, 0x3a, 0x3d, 0x19, 0xbc, 0x94, 0x95, 0xa0, 0x19, 0xc2, 0x5f, 0x4d, 0x43, 0xa2, 0xf3,
|
||||||
0xf9, 0x44, 0xd0, 0xa5, 0xf3, 0x68, 0xf1, 0x11, 0x40, 0xcb, 0x9a, 0x54, 0xc9, 0x5a, 0x3b, 0xeb,
|
0x89, 0xa0, 0x4b, 0xe7, 0xd1, 0xe2, 0x23, 0x80, 0x96, 0x35, 0xa9, 0x92, 0xb5, 0x76, 0xd6, 0x45,
|
||||||
0xa2, 0x97, 0x22, 0x5c, 0x62, 0xd1, 0xcb, 0x00, 0x8e, 0x7e, 0x76, 0x4c, 0x5b, 0x49, 0xc7, 0xe8,
|
0x2f, 0x45, 0xb0, 0xc4, 0xa2, 0x97, 0x01, 0x1c, 0xfd, 0xec, 0x98, 0xb6, 0x92, 0x8e, 0xd1, 0x7b,
|
||||||
0xbd, 0xb4, 0xc5, 0xac, 0x7a, 0xfe, 0x23, 0x2e, 0x37, 0x2b, 0x29, 0x43, 0x9d, 0xc2, 0x93, 0xad,
|
0x69, 0x89, 0x59, 0xf5, 0xfc, 0x47, 0x5c, 0x6e, 0x56, 0x52, 0x06, 0x3a, 0x85, 0x1f, 0x5b, 0xef,
|
||||||
0xf7, 0x47, 0x4c, 0x24, 0xb4, 0x1e, 0xe2, 0x5a, 0x46, 0x62, 0xc6, 0xb1, 0x10, 0x07, 0x22, 0x3b,
|
0x8f, 0x98, 0x48, 0x68, 0x3d, 0xc0, 0xb5, 0x8c, 0xc3, 0x8c, 0x63, 0x21, 0x0e, 0x44, 0x76, 0xfc,
|
||||||
0x7e, 0xec, 0x44, 0x50, 0x8f, 0xe9, 0x44, 0x04, 0x48, 0x3c, 0xcb, 0x8e, 0xcf, 0xfd, 0xc2, 0x35,
|
0xd8, 0x89, 0xa0, 0x1e, 0xd3, 0x89, 0x08, 0x8f, 0x78, 0x96, 0x1d, 0x9f, 0xfb, 0x85, 0x6b, 0x84,
|
||||||
0x02, 0x7b, 0x52, 0x91, 0x18, 0x5c, 0xb3, 0x38, 0x6d, 0x16, 0xdd, 0x36, 0x8b, 0x38, 0x4e, 0xd9,
|
0xf5, 0xa4, 0x22, 0x31, 0xb8, 0x66, 0x71, 0xda, 0x2c, 0xba, 0x6d, 0x16, 0x71, 0x94, 0xb2, 0xa1,
|
||||||
0x50, 0xeb, 0xe0, 0x81, 0xb0, 0xd2, 0x7b, 0x17, 0x41, 0xc7, 0xed, 0x4d, 0xab, 0x06, 0xdb, 0x88,
|
0xd6, 0xc1, 0x03, 0x61, 0xa5, 0xf7, 0x2e, 0x42, 0x8e, 0xdb, 0x9b, 0x56, 0x0d, 0xb6, 0x11, 0xa1,
|
||||||
0x50, 0x46, 0x8e, 0x4e, 0xc2, 0xbb, 0xf8, 0x23, 0x9f, 0xd6, 0xb9, 0xda, 0xb9, 0x9e, 0xbd, 0x76,
|
0x8c, 0x1b, 0x9d, 0x84, 0x77, 0xf1, 0x47, 0x3e, 0xad, 0x73, 0xb5, 0x73, 0x3d, 0x7b, 0xed, 0x32,
|
||||||
0x19, 0x24, 0x55, 0xf4, 0x52, 0xee, 0x08, 0x20, 0xca, 0xa5, 0x6c, 0xcd, 0x1b, 0x1b, 0xcf, 0x68,
|
0x48, 0xaa, 0xd8, 0xa5, 0xdc, 0x11, 0x40, 0x94, 0x4b, 0xd9, 0x96, 0x37, 0x36, 0x9e, 0xd1, 0x22,
|
||||||
0x91, 0x50, 0xe6, 0x38, 0x2d, 0x31, 0x8f, 0x75, 0xbe, 0xd6, 0xa0, 0xd9, 0x4f, 0x1a, 0xc8, 0x3a,
|
0xa1, 0xcc, 0x71, 0x5a, 0x22, 0x1e, 0xeb, 0x7c, 0xad, 0x41, 0xb3, 0x9f, 0x34, 0x90, 0x75, 0x46,
|
||||||
0xa3, 0x52, 0x1d, 0x5b, 0x9b, 0xb3, 0x0d, 0xcf, 0x9b, 0xad, 0x1b, 0x5c, 0x9a, 0xb2, 0x11, 0x83,
|
0xa5, 0x3a, 0xb6, 0x36, 0x67, 0x1b, 0x9e, 0x37, 0x5b, 0x37, 0xb8, 0x34, 0x65, 0xfe, 0x05, 0x9f,
|
||||||
0xd7, 0x3f, 0x92, 0xfb, 0x86, 0xa3, 0x8d, 0x49, 0x72, 0x9e, 0xeb, 0xa8, 0x90, 0xae, 0x58, 0xc0,
|
0x7f, 0xa4, 0xf6, 0x0d, 0x47, 0x1b, 0x53, 0xe4, 0x3c, 0xd7, 0x4d, 0x21, 0x5d, 0xb1, 0x80, 0x19,
|
||||||
0x8c, 0x64, 0x93, 0x39, 0x7c, 0x83, 0x4b, 0x67, 0xa2, 0xd0, 0xb1, 0x5d, 0xad, 0xe2, 0x32, 0x58,
|
0xa9, 0x26, 0x73, 0x78, 0x06, 0x97, 0xae, 0x44, 0xa1, 0x63, 0xbb, 0x5a, 0xc5, 0x65, 0xb0, 0xba,
|
||||||
0x5d, 0x42, 0x53, 0x83, 0x24, 0x91, 0x7a, 0xb9, 0x54, 0x7c, 0x1d, 0x20, 0x49, 0xe5, 0xa8, 0x10,
|
0x84, 0xa6, 0x06, 0x29, 0x22, 0xf5, 0x72, 0xa9, 0xf8, 0x3a, 0x40, 0x8a, 0xca, 0x51, 0x21, 0x6c,
|
||||||
0x06, 0x69, 0xb5, 0xb6, 0x5f, 0x6c, 0x68, 0x5b, 0xaf, 0xab, 0x9a, 0x1f, 0x88, 0xe6, 0xf5, 0x47,
|
0xcd, 0x6a, 0x6d, 0xbf, 0xd8, 0xd0, 0xb6, 0x5e, 0x57, 0x35, 0x3f, 0x10, 0xcd, 0xeb, 0x8f, 0x64,
|
||||||
0xb2, 0x87, 0x17, 0x48, 0x52, 0x29, 0xb3, 0xf3, 0x88, 0x6c, 0xa7, 0xc0, 0xf2, 0xb5, 0x1e, 0x4d,
|
0x0f, 0x2f, 0x90, 0xa2, 0x52, 0xe6, 0xe6, 0x11, 0xb9, 0x4e, 0x81, 0xe5, 0x6b, 0x3d, 0x9a, 0x76,
|
||||||
0x3b, 0x21, 0xc7, 0x35, 0x0d, 0xda, 0xdb, 0x6c, 0xe7, 0x1e, 0x33, 0x7f, 0xdf, 0x60, 0xc5, 0xee,
|
0x42, 0x8e, 0x6b, 0x9a, 0xb3, 0xb7, 0x99, 0xc5, 0x3d, 0x66, 0xfc, 0xbe, 0xc1, 0x86, 0xdd, 0xad,
|
||||||
0xd6, 0x9c, 0x67, 0x85, 0xa7, 0x16, 0x1d, 0x9d, 0x2b, 0x44, 0x60, 0x2b, 0x7d, 0x9d, 0x8f, 0xa4,
|
0xb9, 0xce, 0x0a, 0x3f, 0x2d, 0x3a, 0x3a, 0x57, 0x88, 0xbf, 0x56, 0x7a, 0x3a, 0x1f, 0x49, 0x4b,
|
||||||
0xad, 0xab, 0xbd, 0xe2, 0x34, 0xd6, 0xb8, 0x28, 0xe8, 0x7a, 0xbd, 0xa2, 0xdb, 0x95, 0x78, 0x4f,
|
0x57, 0x7b, 0xc5, 0x49, 0xac, 0x71, 0x51, 0xd0, 0xf5, 0x7a, 0x45, 0xb7, 0x2b, 0xf1, 0x9e, 0xee,
|
||||||
0xf7, 0x76, 0xc8, 0x91, 0x53, 0x7b, 0x46, 0x92, 0x89, 0x32, 0x76, 0xa2, 0xf4, 0xca, 0xec, 0xbe,
|
0xed, 0x90, 0xe3, 0xa6, 0xf6, 0x8c, 0x14, 0x13, 0x65, 0xe4, 0x44, 0xe9, 0x93, 0xd9, 0x7d, 0xe1,
|
||||||
0xf0, 0x9c, 0xd1, 0x3c, 0x7d, 0x08, 0x7b, 0x57, 0x7a, 0xb5, 0xfd, 0x97, 0xb5, 0x7a, 0xce, 0x9a,
|
0x39, 0xa3, 0x79, 0xfa, 0x10, 0xf6, 0xae, 0xf4, 0x6a, 0xfb, 0x2f, 0x6b, 0xf5, 0x9c, 0x35, 0xcd,
|
||||||
0xe6, 0x14, 0x87, 0x1d, 0x2e, 0x0c, 0xa6, 0x08, 0x9c, 0x78, 0xc5, 0xb9, 0x6e, 0xaf, 0x9c, 0x43,
|
0x29, 0x0e, 0x3b, 0x5c, 0x18, 0x4c, 0x11, 0x36, 0xf1, 0x8a, 0x33, 0xdd, 0x5e, 0x39, 0x87, 0x68,
|
||||||
0x34, 0x21, 0x06, 0x47, 0x85, 0xeb, 0xfa, 0xfa, 0xc1, 0x6d, 0x49, 0xe5, 0x33, 0xf2, 0x1a, 0x46,
|
0x42, 0x0c, 0x8e, 0x0a, 0xd7, 0xf5, 0xf5, 0x83, 0xd3, 0x92, 0xca, 0x66, 0xe4, 0x35, 0x4c, 0xc8,
|
||||||
0xe4, 0x3c, 0x5d, 0x49, 0x3d, 0xe8, 0x6f, 0xae, 0x2e, 0xa7, 0xae, 0xb2, 0xd0, 0xe7, 0xe5, 0xfa,
|
0x79, 0xba, 0x92, 0x7a, 0xd0, 0xdf, 0x5c, 0x5d, 0x4e, 0x5d, 0x65, 0x9f, 0xcf, 0xcb, 0xf5, 0x2b,
|
||||||
0x15, 0x84, 0x67, 0x69, 0xb6, 0xba, 0x32, 0x56, 0xb5, 0x70, 0xfb, 0x8e, 0xdb, 0x31, 0xaa, 0xff,
|
0x08, 0xcf, 0xd2, 0x22, 0x75, 0x65, 0xac, 0x6a, 0xe1, 0xf6, 0x1d, 0xb7, 0x63, 0x54, 0xff, 0x1b,
|
||||||
0x0d, 0x61, 0xee, 0x55, 0xed, 0xcb, 0x5a, 0xed, 0x41, 0xbd, 0xf6, 0x5b, 0xbd, 0xf6, 0xb4, 0x56,
|
0x82, 0xdc, 0xab, 0xda, 0x97, 0xb5, 0xda, 0x83, 0x7a, 0xed, 0xb7, 0x7a, 0xed, 0x69, 0xad, 0xf6,
|
||||||
0x7b, 0xbf, 0x31, 0x68, 0x91, 0x55, 0xb4, 0x39, 0xe8, 0xab, 0xf0, 0xfe, 0x94, 0x8d, 0xe6, 0x46,
|
0x7e, 0x63, 0xd0, 0x22, 0xa7, 0x68, 0x73, 0xd0, 0x57, 0xe1, 0xfd, 0x29, 0x1b, 0xcd, 0x8d, 0xd0,
|
||||||
0x68, 0x27, 0xbf, 0x99, 0x0a, 0x13, 0x3a, 0x15, 0x0e, 0xb3, 0x30, 0xe0, 0x62, 0x54, 0x30, 0x76,
|
0x4e, 0x7e, 0x33, 0x15, 0x26, 0x74, 0x2a, 0x18, 0x66, 0x61, 0xc0, 0xc5, 0xa8, 0x60, 0xec, 0x18,
|
||||||
0x0c, 0xbb, 0x3e, 0x5c, 0xc8, 0x4e, 0x65, 0xcd, 0x97, 0x8e, 0x04, 0x29, 0x6a, 0x6b, 0x56, 0xd9,
|
0x76, 0x7d, 0x38, 0x90, 0x9d, 0xca, 0x9a, 0x2f, 0x1d, 0x09, 0x52, 0xd4, 0xd6, 0xac, 0x32, 0xc1,
|
||||||
0xe9, 0x56, 0x65, 0xc9, 0x62, 0xb3, 0xcd, 0x9a, 0x02, 0xfe, 0x7d, 0x47, 0x93, 0xef, 0xd0, 0x4b,
|
0xad, 0xca, 0x92, 0xc5, 0x66, 0x9b, 0x35, 0x05, 0xfc, 0xfb, 0x8e, 0x26, 0xdf, 0xa1, 0x97, 0x58,
|
||||||
0xac, 0xdb, 0x51, 0x12, 0xb1, 0xe7, 0x36, 0x02, 0x8f, 0x9e, 0xfe, 0x3e, 0x41, 0x15, 0x92, 0x13,
|
0xb7, 0xa3, 0x24, 0x62, 0xcf, 0x6d, 0x04, 0xfe, 0x3c, 0xfd, 0x7d, 0x82, 0x2a, 0xa4, 0x26, 0xea,
|
||||||
0xf5, 0xae, 0xc3, 0x8f, 0x47, 0x9c, 0xf1, 0x06, 0x16, 0xe5, 0x3c, 0xff, 0xaa, 0x87, 0xb2, 0x48,
|
0x5d, 0x87, 0x1f, 0x8f, 0x38, 0xdf, 0x0d, 0xec, 0xc9, 0x79, 0xfe, 0x55, 0x0f, 0x65, 0x91, 0x9e,
|
||||||
0xcf, 0x8a, 0xa0, 0x8f, 0x7f, 0xa4, 0xcf, 0x5b, 0x4b, 0x80, 0xa2, 0x2d, 0xd1, 0x4b, 0xc7, 0xa5,
|
0x13, 0x41, 0x1f, 0xff, 0x48, 0x9f, 0xb7, 0x96, 0xfe, 0x44, 0x5b, 0xa2, 0x97, 0x8e, 0x4b, 0x73,
|
||||||
0xb9, 0xf3, 0x2d, 0x5f, 0x07, 0x20, 0xfb, 0x2b, 0x84, 0x3a, 0xac, 0xaa, 0x7a, 0x2e, 0x2d, 0x52,
|
0xe7, 0x5b, 0xbe, 0x0e, 0x40, 0xf6, 0x57, 0x08, 0x74, 0x58, 0x55, 0xf5, 0x5c, 0x5a, 0xa4, 0x2a,
|
||||||
0x95, 0xb0, 0xa0, 0x59, 0x7d, 0xb1, 0x08, 0x02, 0x24, 0x3b, 0x5d, 0x0b, 0xcf, 0x31, 0xbd, 0x73,
|
0x5d, 0x41, 0xb3, 0xfa, 0x62, 0x11, 0x04, 0x48, 0x75, 0xba, 0x16, 0x7e, 0x63, 0x7a, 0xe7, 0x4e,
|
||||||
0xa7, 0x32, 0x90, 0x15, 0x83, 0xf1, 0x34, 0xe8, 0x1c, 0xd4, 0xe6, 0xa4, 0xc3, 0xa6, 0x09, 0x89,
|
0x65, 0xfb, 0x2a, 0x06, 0xe3, 0x69, 0xd0, 0x39, 0xa8, 0xcd, 0x49, 0x87, 0x4d, 0x13, 0x12, 0xa5,
|
||||||
0x52, 0xc2, 0x54, 0x87, 0xb8, 0x52, 0xf0, 0x64, 0x82, 0x96, 0x5c, 0x84, 0xfa, 0x40, 0xa5, 0xdf,
|
0x84, 0xa9, 0x0e, 0x71, 0xa5, 0xe0, 0xc9, 0x04, 0x2d, 0xb9, 0x08, 0xf5, 0x81, 0x4a, 0xaf, 0xe1,
|
||||||
0x70, 0x08, 0x97, 0xe1, 0x02, 0x1f, 0xf9, 0xda, 0xb9, 0xd8, 0x70, 0x58, 0xca, 0x42, 0x43, 0xe6,
|
0x10, 0x0e, 0xc3, 0x05, 0x3e, 0xf2, 0xb5, 0x73, 0xb1, 0xe1, 0xb0, 0x94, 0x85, 0x86, 0xcc, 0xab,
|
||||||
0x55, 0x47, 0xc8, 0x7d, 0xce, 0x52, 0x62, 0x66, 0x23, 0xf3, 0xfd, 0x47, 0x11, 0xd8, 0xf6, 0x76,
|
0x8e, 0x90, 0xfb, 0x9c, 0xa3, 0xc4, 0xcc, 0x45, 0xe6, 0xfb, 0x8f, 0x22, 0xb0, 0xed, 0xed, 0xda,
|
||||||
0x6d, 0x58, 0xf0, 0xd8, 0x4d, 0xc2, 0x98, 0x36, 0x30, 0xbf, 0xb5, 0x5d, 0x9b, 0xfe, 0xb1, 0xaf,
|
0xb0, 0xe0, 0xaf, 0x9b, 0x84, 0x31, 0x6d, 0x60, 0x7e, 0x6b, 0xbb, 0x36, 0xfd, 0x63, 0x4f, 0xe7,
|
||||||
0xf3, 0xa3, 0x8d, 0xd4, 0x4f, 0xae, 0x00, 0x66, 0x77, 0xc0, 0x69, 0x4d, 0xcc, 0xf5, 0x6e, 0x43,
|
0x47, 0x1b, 0xa9, 0x9f, 0x5c, 0x01, 0xcc, 0xee, 0x80, 0x93, 0x9a, 0x98, 0xeb, 0xdd, 0x86, 0x2e,
|
||||||
0x97, 0xca, 0xbd, 0xbd, 0x7e, 0xfe, 0x13, 0x29, 0x6f, 0xa3, 0x92, 0xe1, 0xd9, 0x59, 0x4e, 0x87,
|
0x95, 0x73, 0x7b, 0xfd, 0xfc, 0x27, 0x52, 0xde, 0x46, 0x25, 0xc3, 0xb3, 0xb3, 0x9c, 0x0e, 0x7d,
|
||||||
0x3e, 0xa7, 0xa3, 0x9c, 0xd3, 0x01, 0xd5, 0x9b, 0x3c, 0x77, 0xcf, 0xf0, 0xff, 0xf9, 0x7a, 0x8d,
|
0x4e, 0x47, 0x39, 0xa7, 0x03, 0xaa, 0x37, 0x79, 0xee, 0x9e, 0xe1, 0xff, 0xf3, 0xf5, 0x1a, 0xf3,
|
||||||
0xf9, 0xa3, 0x68, 0x62, 0xbe, 0x48, 0x4f, 0x1f, 0x7b, 0x97, 0x5e, 0x1c, 0x0e, 0xc4, 0x8b, 0xec,
|
0x47, 0xd1, 0xc4, 0x7c, 0x91, 0x9e, 0x3e, 0xf6, 0x2e, 0xbd, 0x38, 0x1c, 0x88, 0x17, 0xd9, 0x01,
|
||||||
0x02, 0x59, 0x7b, 0xf5, 0xb1, 0xb7, 0xe9, 0xd5, 0xcd, 0x28, 0x3c, 0xf9, 0x52, 0x7e, 0x32, 0xa9,
|
0xb2, 0xf6, 0xea, 0x63, 0x6f, 0xd3, 0xab, 0x9b, 0x51, 0x78, 0xf2, 0xa5, 0xfc, 0x64, 0x52, 0x71,
|
||||||
0x38, 0x01, 0xac, 0xcb, 0xd5, 0x4c, 0xc7, 0xf9, 0x48, 0x44, 0xf5, 0xb7, 0x9f, 0x08, 0x2c, 0x65,
|
0x02, 0x58, 0x97, 0xab, 0x99, 0x8e, 0xf3, 0x91, 0x86, 0xea, 0x6f, 0x3f, 0x11, 0x58, 0xca, 0x1c,
|
||||||
0x96, 0x2f, 0xfc, 0xee, 0x94, 0x79, 0x25, 0x65, 0x32, 0x49, 0x24, 0xbe, 0x7c, 0x53, 0xa6, 0x98,
|
0x5f, 0xf8, 0xdd, 0x29, 0xb3, 0x4a, 0xca, 0x54, 0x92, 0x48, 0x7b, 0xf9, 0xa6, 0x4c, 0x30, 0xb9,
|
||||||
0xdc, 0x83, 0x97, 0xc7, 0xde, 0x5d, 0x74, 0x4d, 0xdc, 0xee, 0x5a, 0x72, 0x90, 0x2b, 0xea, 0xd7,
|
0x07, 0x1f, 0x8f, 0xbd, 0xbb, 0xe8, 0x9a, 0xb8, 0xdd, 0xb5, 0xe4, 0x20, 0x57, 0xd4, 0xaf, 0x91,
|
||||||
0xc8, 0xc5, 0xa4, 0x4c, 0x9d, 0x3a, 0x9d, 0xab, 0x59, 0xd7, 0xef, 0xbf, 0x72, 0xc6, 0xfb, 0x9c,
|
0x89, 0x49, 0x99, 0x3a, 0x75, 0x3a, 0x57, 0xb3, 0xae, 0xdf, 0x7f, 0xe5, 0x8c, 0xf7, 0x39, 0x51,
|
||||||
0xaa, 0x07, 0xbd, 0x3b, 0xee, 0xd5, 0x6c, 0x3c, 0x50, 0x3f, 0xf7, 0x3d, 0x9c, 0xd5, 0x83, 0x03,
|
0x0f, 0x7a, 0x77, 0xdc, 0xab, 0xd9, 0x78, 0xa0, 0x7e, 0xee, 0x7b, 0x38, 0xab, 0x07, 0x07, 0xbe,
|
||||||
0xdf, 0xbf, 0x9a, 0x71, 0x49, 0xd7, 0xdf, 0x47, 0x89, 0xf7, 0x4a, 0x2b, 0xa1, 0x06, 0x14, 0xca,
|
0x7f, 0x35, 0xe3, 0x92, 0xae, 0xbf, 0x8f, 0x12, 0xef, 0x95, 0x56, 0x42, 0x0d, 0x28, 0x94, 0x85,
|
||||||
0x42, 0xd2, 0x33, 0x85, 0x6c, 0x78, 0x6f, 0xfd, 0x8b, 0xab, 0x1c, 0x89, 0x1b, 0xaf, 0x66, 0x6b,
|
0x94, 0x67, 0x0a, 0xd9, 0xf0, 0xde, 0xfa, 0x17, 0x57, 0x39, 0xd2, 0x36, 0x5e, 0xcd, 0xd6, 0xc8,
|
||||||
0xe4, 0x37, 0xf5, 0xbe, 0x71, 0xad, 0x17, 0xde, 0x37, 0x70, 0xde, 0x74, 0xdc, 0xd7, 0x7d, 0xe9,
|
0x6e, 0xea, 0x7d, 0xe3, 0x5a, 0x2f, 0xbc, 0x6f, 0xe0, 0xba, 0xe9, 0xb8, 0xaf, 0xfb, 0xd2, 0xc5,
|
||||||
0xe4, 0x43, 0x28, 0x8a, 0xe3, 0x16, 0x54, 0xce, 0x23, 0xc9, 0xe2, 0x57, 0xe6, 0xba, 0x84, 0x77,
|
0x87, 0x50, 0x14, 0x47, 0x2d, 0xa8, 0x5c, 0x47, 0x92, 0xc5, 0xaf, 0xcc, 0x75, 0x09, 0xdf, 0x0e,
|
||||||
0x07, 0x9e, 0x1b, 0x67, 0x93, 0xa9, 0x19, 0x8e, 0x79, 0x54, 0xa6, 0xe8, 0x31, 0x3a, 0x15, 0xbe,
|
0x3c, 0x37, 0xce, 0x26, 0x53, 0x33, 0x1c, 0xf1, 0xa8, 0x4c, 0xd0, 0x63, 0x74, 0x2a, 0x3c, 0xa7,
|
||||||
0xd3, 0x6e, 0xa8, 0x53, 0xc6, 0x47, 0x69, 0x42, 0x54, 0xfd, 0xd2, 0xfa, 0x35, 0x9c, 0xa6, 0x69,
|
0xdd, 0x50, 0xa7, 0x8c, 0x8f, 0xd2, 0x84, 0xa8, 0xfa, 0xa5, 0xf5, 0x6b, 0x38, 0x4d, 0xd3, 0xc2,
|
||||||
0x61, 0x0b, 0xbb, 0x5b, 0xd1, 0x33, 0x1d, 0xbe, 0x46, 0x1e, 0x35, 0x91, 0xb4, 0x51, 0xaa, 0x9c,
|
0x16, 0x76, 0xb7, 0xa2, 0x67, 0x3a, 0x7c, 0x8d, 0x2c, 0x6a, 0x22, 0x65, 0xa3, 0x54, 0x39, 0xa9,
|
||||||
0xd4, 0x20, 0x4f, 0x8d, 0x51, 0xae, 0x10, 0xfd, 0xc9, 0x44, 0x1a, 0x32, 0x12, 0xd3, 0x48, 0x8d,
|
0x41, 0x9e, 0x1a, 0xa3, 0x5c, 0x21, 0xf6, 0x93, 0x89, 0x34, 0x64, 0x1c, 0xa6, 0x91, 0x1a, 0xf5,
|
||||||
0xfa, 0xd4, 0xf9, 0xec, 0xf1, 0x89, 0x2e, 0xab, 0xe1, 0x9d, 0xb2, 0x2f, 0x94, 0xea, 0xdd, 0x6d,
|
0xa9, 0xf3, 0xd9, 0xe3, 0x13, 0x5d, 0x56, 0xc3, 0x3b, 0x65, 0x4f, 0x28, 0xd5, 0xbb, 0xdb, 0x68,
|
||||||
0x34, 0xb4, 0x58, 0xd4, 0x1a, 0xe2, 0x95, 0x2b, 0x25, 0xb5, 0x2a, 0xfd, 0x8e, 0x90, 0xf3, 0x3f,
|
0x68, 0xb1, 0xa8, 0x35, 0xc4, 0x2b, 0x57, 0x4a, 0x6a, 0x55, 0xf2, 0x1d, 0x21, 0xe7, 0x7f, 0x90,
|
||||||
0xc8, 0x10, 0x7c, 0x42, 0xf8, 0xaa, 0x8c, 0x3b, 0x58, 0x20, 0x4f, 0x64, 0xbf, 0xa6, 0x05, 0x40,
|
0x01, 0xf8, 0x84, 0xf0, 0x55, 0x19, 0x77, 0xb0, 0x40, 0x9e, 0xc8, 0x7e, 0x4d, 0x0b, 0x80, 0xc4,
|
||||||
0x6a, 0xa4, 0x50, 0x6a, 0x01, 0xc2, 0xba, 0x16, 0x40, 0x08, 0x6e, 0x1f, 0xd5, 0x01, 0x34, 0xf3,
|
0x48, 0xa1, 0xd4, 0x02, 0x84, 0x75, 0x2d, 0x80, 0x10, 0xdc, 0x3e, 0xaa, 0x03, 0x68, 0x66, 0x21,
|
||||||
0x10, 0x36, 0xa2, 0x6a, 0x88, 0x95, 0x79, 0x32, 0x63, 0x24, 0xb5, 0x72, 0x2f, 0x56, 0x34, 0x74,
|
0x6c, 0xc4, 0xd4, 0x10, 0x2b, 0xf3, 0x64, 0xbe, 0x48, 0x6a, 0xe5, 0x5e, 0xac, 0x68, 0xe8, 0xe0,
|
||||||
0x70, 0x63, 0xd0, 0x17, 0x22, 0x7c, 0xcc, 0x4c, 0x91, 0xdb, 0xdb, 0x1c, 0xf2, 0xd8, 0xf7, 0x95,
|
0xc6, 0xa0, 0x2f, 0x44, 0xf8, 0x98, 0x79, 0x22, 0xb7, 0xb7, 0x39, 0xe0, 0xb1, 0xef, 0x2b, 0x37,
|
||||||
0x2f, 0x01, 0x07, 0x40, 0xd6, 0x79, 0x26, 0xbd, 0x67, 0xf8, 0xdf, 0xe8, 0x49, 0x70, 0x8c, 0x67,
|
0x01, 0x0e, 0x7f, 0xac, 0xf3, 0x4c, 0x7a, 0xcf, 0x70, 0xad, 0xd1, 0x53, 0xe0, 0x18, 0xcf, 0x1e,
|
||||||
0x0f, 0x6b, 0xc4, 0x36, 0x36, 0x86, 0xee, 0xb9, 0x66, 0x8e, 0xc4, 0x8d, 0x61, 0xde, 0x31, 0xd2,
|
0xd6, 0x88, 0x6c, 0x6c, 0x0c, 0xdd, 0x73, 0xcd, 0x0c, 0x89, 0x1b, 0x83, 0xbc, 0x63, 0xa4, 0xf5,
|
||||||
0x7a, 0xa4, 0xf7, 0x87, 0x6c, 0xa8, 0xb7, 0xef, 0xd2, 0xc0, 0x86, 0xfa, 0x28, 0x45, 0xd6, 0x44,
|
0x38, 0xef, 0x0f, 0xd9, 0x50, 0x6f, 0xdf, 0xa5, 0x81, 0x0d, 0xf5, 0x51, 0x8a, 0x9c, 0x89, 0x26,
|
||||||
0x93, 0x00, 0x74, 0xcc, 0xc4, 0x62, 0xc6, 0x60, 0xd8, 0xa5, 0xea, 0xd9, 0x39, 0x4a, 0xee, 0x27,
|
0x01, 0xe8, 0x98, 0x69, 0xc5, 0x8c, 0xc1, 0xb0, 0x43, 0xd5, 0xb3, 0x33, 0x94, 0xdc, 0x4f, 0xc0,
|
||||||
0xe0, 0x5f, 0x7c, 0xba, 0x53, 0xcd, 0x50, 0x48, 0x7f, 0xc2, 0x9e, 0xff, 0x0b, 0x0c, 0xf9, 0x73,
|
0xbf, 0xf8, 0x74, 0xa7, 0x9a, 0x81, 0x90, 0xfe, 0x84, 0x3d, 0xff, 0x17, 0x18, 0xf2, 0xe7, 0x08,
|
||||||
0x04, 0x4b, 0xd2, 0x17, 0xb9, 0x99, 0x0b, 0x4a, 0x5f, 0xa2, 0x9c, 0xb6, 0xc7, 0x0d, 0x0f, 0xf3,
|
0x95, 0xa4, 0x2f, 0x72, 0x33, 0x13, 0x94, 0xbe, 0x44, 0x39, 0x6d, 0x8f, 0x1b, 0x1e, 0xe6, 0xbd,
|
||||||
0xde, 0x72, 0xb2, 0x21, 0x99, 0x5c, 0x63, 0x51, 0xba, 0x7d, 0x5a, 0x16, 0x42, 0x29, 0x44, 0x9d,
|
0xe5, 0x64, 0x43, 0x2a, 0xb9, 0xc6, 0xa2, 0x74, 0xfb, 0xb4, 0x2c, 0x84, 0x52, 0x88, 0x3a, 0x1d,
|
||||||
0x0e, 0x8b, 0xce, 0x97, 0x19, 0x7d, 0xd7, 0x92, 0x82, 0xac, 0x4d, 0xa5, 0x04, 0x82, 0x32, 0xb3,
|
0x16, 0x9d, 0x2f, 0x33, 0xfa, 0xae, 0xa5, 0x04, 0x59, 0x9b, 0x4a, 0x09, 0x84, 0x64, 0x66, 0x7f,
|
||||||
0xd3, 0x89, 0x10, 0xf8, 0xb2, 0xa7, 0x40, 0x12, 0xde, 0x2b, 0xe7, 0xee, 0xd3, 0x08, 0x39, 0xfc,
|
0x12, 0x21, 0xf0, 0x65, 0x4f, 0x81, 0x24, 0xbc, 0x57, 0xae, 0xdd, 0xa7, 0x11, 0x32, 0xf8, 0x5d,
|
||||||
0x2e, 0xeb, 0xce, 0xac, 0xf6, 0x96, 0xaf, 0x02, 0x14, 0xd4, 0x35, 0x78, 0x85, 0xee, 0xa5, 0x5d,
|
0xd6, 0x5d, 0x59, 0xed, 0x2d, 0x5f, 0x85, 0x27, 0xa8, 0x6b, 0xf0, 0x0a, 0xdd, 0x47, 0xbb, 0x70,
|
||||||
0x38, 0x2d, 0xa1, 0x72, 0xf4, 0xd8, 0x38, 0x11, 0xcc, 0x3a, 0x0f, 0xcb, 0x10, 0x65, 0x91, 0x0a,
|
0x5a, 0x02, 0xe5, 0xe8, 0x91, 0x71, 0x22, 0x98, 0x75, 0x1e, 0x96, 0x01, 0xca, 0x22, 0x15, 0xa0,
|
||||||
0x51, 0x96, 0xf8, 0xf9, 0x59, 0x74, 0x8e, 0x70, 0x2e, 0xad, 0x91, 0x70, 0x38, 0x12, 0x86, 0x14,
|
0x2c, 0xf1, 0xf3, 0xb3, 0xe8, 0x1c, 0xc1, 0x5c, 0x5a, 0xe3, 0xe0, 0x70, 0x1c, 0x0c, 0x29, 0x20,
|
||||||
0x10, 0x7c, 0xa0, 0xd1, 0x12, 0xf1, 0xf9, 0x5b, 0x96, 0x85, 0xab, 0x23, 0x62, 0x73, 0x3b, 0xce,
|
0xf8, 0x40, 0xa3, 0x25, 0xe2, 0xf3, 0xb7, 0x2c, 0x0b, 0x57, 0x47, 0xc4, 0xe6, 0x76, 0x9c, 0x51,
|
||||||
0x28, 0xa9, 0x8d, 0x37, 0x2d, 0x25, 0x0f, 0x72, 0xd0, 0x66, 0x7d, 0x48, 0x3f, 0xd8, 0x7a, 0x45,
|
0x52, 0x1b, 0x6f, 0x5a, 0x4a, 0x1e, 0xe4, 0xa0, 0xcd, 0xfa, 0x90, 0x7e, 0xb0, 0xf5, 0x8a, 0xf0,
|
||||||
0xf8, 0xfa, 0xad, 0xcd, 0xdc, 0x7a, 0x89, 0x08, 0xb5, 0xd0, 0x16, 0xa7, 0x6e, 0xa4, 0xfc, 0x27,
|
0xf4, 0x5b, 0x9b, 0x99, 0xf5, 0x12, 0x11, 0x68, 0xa1, 0x2d, 0x4a, 0xdd, 0x48, 0xf9, 0x4f, 0xa8,
|
||||||
0x54, 0xfe, 0x26, 0x73, 0xd5, 0x4a, 0x5a, 0xdf, 0x46, 0x3a, 0xdc, 0x45, 0x3a, 0xbb, 0x01, 0x1f,
|
0xec, 0x4d, 0xe6, 0xaa, 0x95, 0xb4, 0xbe, 0x8d, 0x64, 0xb8, 0x8b, 0x74, 0x76, 0x03, 0x3e, 0xb8,
|
||||||
0x5c, 0x70, 0x23, 0xd8, 0x46, 0x4e, 0x99, 0xd9, 0x81, 0x9b, 0x8e, 0xf8, 0x26, 0x52, 0xa9, 0xda,
|
0xe0, 0x46, 0xb0, 0x8d, 0x9c, 0x30, 0xb3, 0x03, 0x0f, 0x1c, 0xf1, 0x4d, 0x24, 0x52, 0xb5, 0xf5,
|
||||||
0xfa, 0x06, 0x29, 0xfd, 0xb0, 0xb9, 0xac, 0x6c, 0x57, 0xda, 0x15, 0xaa, 0x3d, 0xb8, 0xf4, 0x18,
|
0x0d, 0x52, 0xfa, 0x61, 0x73, 0x59, 0xd9, 0xae, 0xb4, 0x2b, 0x54, 0x7b, 0xf0, 0xd6, 0x31, 0x74,
|
||||||
0x3a, 0x2a, 0xed, 0x47, 0x95, 0xd6, 0xb0, 0x74, 0x72, 0xac, 0x1e, 0xb6, 0xa9, 0x5e, 0x39, 0x18,
|
0x54, 0xda, 0x8f, 0x2a, 0xa9, 0x61, 0xe9, 0xe2, 0x58, 0x3d, 0x6c, 0x53, 0xbd, 0x72, 0x28, 0x64,
|
||||||
0x32, 0x5a, 0x6e, 0x3a, 0x78, 0xea, 0x2f, 0xae, 0x52, 0x18, 0x0e, 0x75, 0xfa, 0xaf, 0x10, 0x64,
|
0xb4, 0xdc, 0x74, 0xef, 0xd4, 0x5f, 0x5c, 0xa5, 0x30, 0x1c, 0xea, 0xf4, 0x5f, 0x21, 0xc4, 0x06,
|
||||||
0x03, 0x76, 0xbf, 0xb2, 0x40, 0xfc, 0x74, 0xc3, 0x31, 0xc8, 0x2d, 0xb9, 0x8f, 0xe1, 0x2e, 0xfd,
|
0xec, 0x7e, 0x65, 0x81, 0xf8, 0xe9, 0x86, 0x63, 0x90, 0x5b, 0x72, 0x1f, 0xc3, 0x5d, 0xfa, 0xa1,
|
||||||
0xd0, 0xa5, 0x6e, 0x09, 0x3c, 0xf5, 0x9b, 0xae, 0xf0, 0x5a, 0x07, 0x9f, 0x3e, 0x25, 0x5b, 0xbe,
|
0x4b, 0xdd, 0x12, 0xf8, 0xe9, 0x37, 0x1d, 0xe1, 0xb5, 0x0e, 0x3e, 0x7d, 0x4a, 0xb6, 0x7c, 0xc3,
|
||||||
0xe1, 0x77, 0x38, 0xd1, 0x23, 0x03, 0x0c, 0x0d, 0xf2, 0x1e, 0xa2, 0x40, 0x2d, 0xfb, 0x23, 0x32,
|
0xa5, 0x70, 0xa2, 0xc7, 0x05, 0x18, 0x1a, 0xe4, 0x3d, 0x44, 0x81, 0x5a, 0xee, 0x47, 0xe4, 0x63,
|
||||||
0x32, 0x56, 0x97, 0x86, 0x50, 0xde, 0x27, 0xca, 0x91, 0x49, 0xa5, 0x76, 0x4b, 0x9c, 0x51, 0x35,
|
0xac, 0x2e, 0x0d, 0xa1, 0xbc, 0x4f, 0x94, 0x8f, 0x92, 0x4a, 0xec, 0x96, 0x38, 0xa3, 0x6a, 0x34,
|
||||||
0x1a, 0x4d, 0x40, 0xe7, 0xa7, 0x2e, 0xc2, 0x39, 0x34, 0xe5, 0x54, 0xd2, 0xb7, 0x5b, 0xbc, 0x50,
|
0x9a, 0x80, 0xce, 0x4f, 0x5d, 0x04, 0x73, 0x68, 0xca, 0xa9, 0xa4, 0x67, 0xb7, 0x78, 0xa1, 0x26,
|
||||||
0x13, 0x1a, 0xe2, 0x1e, 0x73, 0x85, 0x3a, 0x3c, 0x21, 0xda, 0x84, 0x06, 0x23, 0x62, 0x70, 0x48,
|
0x34, 0xc4, 0x3d, 0xe6, 0x0a, 0x75, 0x78, 0x42, 0xb4, 0x09, 0x0d, 0x46, 0x44, 0xe0, 0x90, 0xb0,
|
||||||
0x58, 0x58, 0x1b, 0xfa, 0xfe, 0x2f, 0x89, 0x2d, 0xa0, 0x71, 0x6e, 0x09, 0x03, 0x11, 0x67, 0xd9,
|
0xb0, 0x36, 0xf4, 0xfd, 0x5f, 0x12, 0x59, 0x40, 0xe3, 0xdc, 0x12, 0x06, 0x22, 0xce, 0xb1, 0xb9,
|
||||||
0x5c, 0xe5, 0xa5, 0x55, 0xa0, 0xa6, 0x08, 0x98, 0xc6, 0x37, 0xab, 0x8e, 0xd3, 0xe6, 0xea, 0xd6,
|
0xca, 0x4b, 0xab, 0x40, 0x4d, 0x11, 0x30, 0x8d, 0x6f, 0x56, 0x1d, 0xa7, 0xcd, 0x8b, 0xad, 0xf9,
|
||||||
0x7c, 0xa2, 0x0b, 0xd4, 0xc5, 0xd3, 0xb5, 0x88, 0xbe, 0xf4, 0x5f, 0x47, 0x4d, 0x55, 0x4a, 0x0f,
|
0x44, 0x17, 0xa8, 0x8b, 0xa7, 0x6b, 0x11, 0x7b, 0xe9, 0xbf, 0x8e, 0x9a, 0xaa, 0x94, 0x1e, 0xa2,
|
||||||
0xf1, 0x6a, 0x82, 0x28, 0x81, 0xf7, 0xaf, 0xfb, 0xde, 0x3f, 0xe0, 0xd8, 0x4c, 0x77, 0x32, 0xe3,
|
0xd5, 0x04, 0x51, 0x02, 0xdf, 0x5f, 0xf7, 0xbd, 0x7f, 0xc0, 0x91, 0x99, 0xee, 0x64, 0xbe, 0x4f,
|
||||||
0xa7, 0xef, 0xb9, 0xf7, 0x9e, 0x70, 0x55, 0x12, 0xd3, 0x3b, 0xe5, 0xd0, 0xeb, 0x62, 0x75, 0x34,
|
0xdf, 0x73, 0xef, 0x3d, 0xe1, 0xaa, 0x24, 0xa6, 0x77, 0xca, 0x81, 0xd7, 0xc5, 0xea, 0x68, 0x94,
|
||||||
0xca, 0xe2, 0x26, 0x11, 0x9e, 0x58, 0xa5, 0xef, 0x6c, 0x4f, 0xd8, 0xc2, 0xcc, 0x3f, 0x70, 0xb6,
|
0xc5, 0x4d, 0x22, 0x3c, 0xb1, 0x4a, 0xcf, 0xd9, 0x9e, 0xb0, 0x85, 0x99, 0x7f, 0xe0, 0x5c, 0xb1,
|
||||||
0xd8, 0x7c, 0x52, 0x2f, 0x38, 0xf3, 0xce, 0x87, 0xa1, 0xee, 0x20, 0x9b, 0x1f, 0xaf, 0x52, 0x8e,
|
0xf9, 0xa4, 0x5e, 0x70, 0xe6, 0x9d, 0x0f, 0x43, 0xdd, 0x3d, 0x36, 0x3f, 0x5e, 0xa5, 0x1c, 0x6b,
|
||||||
0x36, 0x81, 0x56, 0xaa, 0xf4, 0xc7, 0xcd, 0xe0, 0x5a, 0x40, 0x64, 0x88, 0xa3, 0xa5, 0xe7, 0x34,
|
0x02, 0xad, 0x54, 0xc9, 0x8f, 0x9b, 0xa1, 0xb5, 0x80, 0xc8, 0x10, 0x45, 0x4b, 0xcf, 0x68, 0x40,
|
||||||
0xa0, 0x77, 0x4b, 0x91, 0x23, 0x91, 0x05, 0xca, 0x5d, 0x53, 0xbf, 0xdd, 0x67, 0xd7, 0x65, 0xde,
|
0xef, 0x96, 0x22, 0x47, 0x22, 0x0b, 0x94, 0x27, 0xa6, 0x7e, 0xbb, 0xcf, 0xae, 0xcb, 0xac, 0x7f,
|
||||||
0x3f, 0xce, 0x8e, 0xea, 0x94, 0x2e, 0x52, 0x32, 0xd4, 0x4a, 0xa9, 0xdd, 0xe1, 0xe4, 0x11, 0x46,
|
0x9c, 0x1b, 0xd5, 0x29, 0x5d, 0xa4, 0x64, 0xa0, 0x95, 0x52, 0xbb, 0xc3, 0xa9, 0x23, 0x8c, 0xe8,
|
||||||
0xfc, 0x15, 0xb9, 0xe1, 0x55, 0x15, 0x3a, 0xff, 0x72, 0xd5, 0xf2, 0x4e, 0x69, 0xdf, 0xe4, 0x7c,
|
0x2b, 0x72, 0xc3, 0xab, 0x2a, 0x74, 0xfe, 0xe5, 0xaa, 0xe5, 0x9d, 0xd2, 0xbe, 0xc9, 0xf9, 0xf4,
|
||||||
0xfa, 0xa4, 0x4f, 0xa3, 0xa8, 0xfd, 0xce, 0x91, 0xc4, 0x9a, 0x16, 0x53, 0x2d, 0x15, 0xb5, 0x86,
|
0x49, 0x9f, 0x46, 0x51, 0xfb, 0x9d, 0x23, 0x85, 0x35, 0x2d, 0xa6, 0x5a, 0x2a, 0x6a, 0x0d, 0xd1,
|
||||||
0x78, 0x36, 0xff, 0x28, 0x17, 0xf6, 0xd1, 0xa4, 0xb2, 0x2a, 0xa8, 0x90, 0x73, 0x26, 0x36, 0xe6,
|
0x6c, 0xfe, 0x51, 0x2e, 0xec, 0xa3, 0x29, 0x65, 0x55, 0x48, 0x21, 0xe7, 0x4c, 0x6c, 0xcc, 0xb9,
|
||||||
0x5c, 0x82, 0xdb, 0x87, 0x34, 0x7b, 0x22, 0xb1, 0x6b, 0x47, 0x6d, 0x97, 0xe7, 0x18, 0x41, 0xc4,
|
0x04, 0xb7, 0x0f, 0x69, 0xf6, 0x44, 0x5a, 0xd7, 0x8e, 0xda, 0x2e, 0xcf, 0x31, 0x42, 0x88, 0xb1,
|
||||||
0x58, 0x2d, 0x26, 0x96, 0x44, 0xd4, 0xd8, 0xde, 0xae, 0x2d, 0x4d, 0x73, 0xa4, 0x7e, 0xb1, 0x7b,
|
0x5a, 0x4c, 0x2c, 0x89, 0xa8, 0xb1, 0xbd, 0x5d, 0x5b, 0x9a, 0xe6, 0x48, 0xfd, 0x62, 0xf7, 0xde,
|
||||||
0xef, 0xa9, 0x0c, 0xa0, 0x7c, 0x15, 0xe6, 0x70, 0xc8, 0xeb, 0x76, 0x92, 0x6f, 0xf3, 0xbd, 0xbb,
|
0x53, 0xf9, 0x3f, 0xf9, 0x2a, 0xcc, 0xe1, 0x90, 0xd7, 0xed, 0x24, 0xdf, 0xe6, 0x7b, 0x77, 0x55,
|
||||||
0x2a, 0xf5, 0xc1, 0xa0, 0xcc, 0xc3, 0x24, 0x46, 0x3b, 0xf6, 0xe8, 0xe4, 0x1f, 0x72, 0x60, 0x14,
|
0xe2, 0x83, 0x41, 0x99, 0x85, 0x49, 0x8c, 0x76, 0xec, 0xd1, 0xc9, 0x3f, 0xe4, 0xb0, 0x28, 0xa2,
|
||||||
0x51, 0x70, 0xb8, 0x4f, 0x05, 0x1c, 0x29, 0x25, 0x1d, 0xf7, 0xfa, 0x83, 0xed, 0xed, 0x2f, 0x9d,
|
0xe0, 0x70, 0x9f, 0x0a, 0x38, 0x4e, 0x4a, 0x3a, 0xee, 0xf5, 0x07, 0xdb, 0xdb, 0x5f, 0x3a, 0x79,
|
||||||
0x3c, 0xa1, 0x08, 0xb1, 0x7c, 0xd4, 0xf4, 0x93, 0xf9, 0x6b, 0x77, 0x21, 0xe8, 0x4d, 0xfd, 0xfe,
|
0x42, 0x11, 0x62, 0xf9, 0xa8, 0xe9, 0x27, 0xb3, 0xd7, 0xee, 0x42, 0xd0, 0x9b, 0xfa, 0xfd, 0xdd,
|
||||||
0x6e, 0x5a, 0x4f, 0x64, 0x2b, 0xf3, 0xdb, 0x6e, 0xce, 0x81, 0xbb, 0x40, 0x8a, 0x86, 0xe7, 0xae,
|
0xb4, 0x9e, 0xc6, 0x56, 0x66, 0xb7, 0xdd, 0x9c, 0x01, 0x77, 0x81, 0x04, 0x0d, 0xcf, 0x5d, 0xe9,
|
||||||
0x74, 0x9f, 0x1a, 0x92, 0xc7, 0x66, 0x6d, 0x26, 0x85, 0x55, 0xbe, 0x1b, 0x2a, 0xb7, 0xa9, 0xa2,
|
0x3e, 0x35, 0x24, 0x8f, 0xcd, 0xda, 0x4c, 0x09, 0xab, 0x7c, 0x37, 0x54, 0x66, 0x53, 0x45, 0x57,
|
||||||
0xab, 0x92, 0xf9, 0x8c, 0xe5, 0x2d, 0x77, 0xe3, 0xef, 0x5e, 0x7f, 0xf7, 0xe9, 0xd3, 0xdd, 0xf8,
|
0x25, 0xf3, 0x19, 0xcb, 0x5b, 0xee, 0xc6, 0xdf, 0xbd, 0xfe, 0xee, 0xd3, 0xa7, 0xbb, 0xf1, 0x8b,
|
||||||
0xc5, 0xfe, 0xeb, 0xed, 0xed, 0xbb, 0xc3, 0xef, 0x06, 0x06, 0x9f, 0xcd, 0xde, 0x2c, 0x0f, 0x77,
|
0xfd, 0xd7, 0xdb, 0xdb, 0x77, 0x87, 0xdf, 0x0d, 0x0c, 0x3e, 0x9b, 0xbd, 0x59, 0x1e, 0xee, 0x54,
|
||||||
0x2a, 0xab, 0x3a, 0xa3, 0xc3, 0xdf, 0x21, 0x1e, 0xfc, 0x33, 0x01, 0x39, 0x46, 0x1a, 0x3b, 0x40,
|
0x4e, 0x75, 0x46, 0x87, 0xbf, 0x43, 0x3c, 0xf8, 0x67, 0xc2, 0x71, 0x8c, 0x34, 0x76, 0x80, 0x08,
|
||||||
0x84, 0xb2, 0xad, 0xf6, 0xfb, 0xa7, 0x10, 0x66, 0x8f, 0xa3, 0x9c, 0x98, 0x68, 0xac, 0x00, 0xa7,
|
0x65, 0x5b, 0xed, 0xf7, 0x4f, 0x21, 0xcc, 0x1e, 0x47, 0x39, 0x31, 0xd1, 0x58, 0x01, 0x4e, 0xc0,
|
||||||
0xe0, 0xe8, 0xda, 0xd9, 0x3d, 0xe2, 0x26, 0xc8, 0xb2, 0xe9, 0x95, 0xf2, 0x03, 0x49, 0x8b, 0xda,
|
0xd1, 0xb5, 0xb3, 0x7b, 0x44, 0x4d, 0x90, 0x65, 0xd3, 0x2b, 0xe5, 0x07, 0x92, 0x16, 0xb5, 0xf7,
|
||||||
0x7b, 0xb2, 0x26, 0x3c, 0x72, 0x20, 0x47, 0xda, 0xf5, 0x0f, 0xaa, 0xd7, 0x8a, 0xac, 0x6a, 0xca,
|
0x64, 0x4d, 0x78, 0xe4, 0x40, 0x8e, 0xb4, 0xeb, 0x1f, 0x54, 0xaf, 0x15, 0x59, 0xd5, 0x94, 0x91,
|
||||||
0x48, 0x70, 0xdd, 0x74, 0x5f, 0x13, 0xe5, 0x22, 0x82, 0x03, 0xe7, 0xda, 0xe2, 0x82, 0x37, 0xbe,
|
0xde, 0xba, 0xe9, 0xbe, 0x26, 0xca, 0x45, 0xfc, 0x06, 0xce, 0xb4, 0xc5, 0x05, 0x6f, 0x7c, 0x09,
|
||||||
0x04, 0xd5, 0x37, 0x1b, 0x92, 0x18, 0x21, 0x7b, 0xb6, 0x2b, 0xab, 0x38, 0xf2, 0x8b, 0x5f, 0xfe,
|
0xaa, 0x6f, 0x36, 0xa4, 0x30, 0x42, 0xee, 0x6c, 0x57, 0x56, 0x71, 0xe4, 0x17, 0xbf, 0xfc, 0x7d,
|
||||||
0xbe, 0x3b, 0xec, 0x73, 0x7e, 0xd4, 0x2d, 0x95, 0x65, 0x79, 0x8b, 0x25, 0x01, 0xb2, 0x14, 0x9b,
|
0x77, 0xd8, 0xe7, 0xec, 0xa8, 0x5b, 0x2a, 0xc7, 0xf2, 0x16, 0x4b, 0x02, 0x64, 0x29, 0x36, 0x45,
|
||||||
0x22, 0xbe, 0x63, 0x23, 0x7c, 0xad, 0x50, 0xfc, 0xc0, 0x39, 0x56, 0x19, 0x97, 0x39, 0x81, 0x91,
|
0x7c, 0xc7, 0x46, 0xf8, 0x5a, 0xa1, 0xf8, 0x81, 0x73, 0xac, 0xf2, 0x2d, 0x73, 0xfa, 0x22, 0xd9,
|
||||||
0x6c, 0x6f, 0x22, 0xbb, 0xd9, 0xea, 0x0f, 0x65, 0x4f, 0x88, 0x59, 0x53, 0x8e, 0xb9, 0xea, 0xbe,
|
0xde, 0x44, 0x76, 0xb3, 0xd5, 0x1f, 0xca, 0x9e, 0x10, 0xb1, 0xa6, 0x1c, 0x73, 0xd5, 0x7d, 0x33,
|
||||||
0x99, 0x73, 0x5d, 0x8f, 0xeb, 0x82, 0xbc, 0xdf, 0x9a, 0x27, 0x8d, 0x78, 0xab, 0x25, 0xf8, 0x4a,
|
0xe3, 0xba, 0x1e, 0xd5, 0x05, 0x59, 0xbf, 0x35, 0x4f, 0x1a, 0xf1, 0x56, 0x4b, 0xe8, 0x95, 0xb4,
|
||||||
0x5a, 0x31, 0xae, 0x57, 0xbc, 0xe2, 0x7e, 0x99, 0xf6, 0xb9, 0xca, 0xb4, 0x35, 0x5b, 0x52, 0xbd,
|
0x62, 0x5c, 0xaf, 0x78, 0xc5, 0xfd, 0x32, 0xe9, 0x73, 0x95, 0x67, 0x6b, 0xb6, 0xa4, 0x7a, 0x13,
|
||||||
0x89, 0xed, 0x81, 0x4e, 0xbe, 0x29, 0x52, 0xfb, 0x33, 0x76, 0xae, 0x3c, 0x09, 0x42, 0xfe, 0xac,
|
0xdb, 0x03, 0x9d, 0x7c, 0x53, 0xa4, 0xf6, 0x67, 0xec, 0x5c, 0x79, 0x12, 0x84, 0xfc, 0x59, 0x8d,
|
||||||
0xc6, 0x01, 0x96, 0x98, 0x5a, 0x3b, 0xc0, 0x1f, 0xf6, 0x49, 0x26, 0x68, 0xd4, 0xb6, 0xad, 0x4c,
|
0x03, 0x2c, 0x31, 0xb5, 0x76, 0x80, 0x3f, 0xec, 0x6e, 0x4c, 0xd0, 0xa8, 0x6d, 0x5b, 0x99, 0x62,
|
||||||
0x32, 0xa6, 0xdd, 0x05, 0xdb, 0xdb, 0x76, 0xca, 0x85, 0x10, 0xf7, 0x10, 0xd1, 0x9e, 0x2e, 0x50,
|
0x4c, 0xbb, 0x0b, 0xb6, 0xb7, 0xed, 0x94, 0x0b, 0x21, 0xee, 0x21, 0xa2, 0x3d, 0x5d, 0xa0, 0x6c,
|
||||||
0xb6, 0x65, 0xba, 0xbd, 0xeb, 0xe6, 0x3e, 0xcb, 0x90, 0x90, 0xef, 0xf7, 0x61, 0x98, 0x11, 0x79,
|
0xcb, 0xf4, 0x68, 0xd7, 0xcd, 0x7d, 0x96, 0x21, 0x21, 0xdf, 0xef, 0xc3, 0x30, 0x23, 0xf2, 0xa8,
|
||||||
0xd4, 0xeb, 0xf5, 0x44, 0x44, 0xb3, 0x2d, 0x25, 0xc2, 0x2f, 0x39, 0xd4, 0x91, 0xb8, 0xd4, 0x10,
|
0xd7, 0xeb, 0x89, 0x78, 0x66, 0x5b, 0x4a, 0x84, 0x5f, 0x72, 0xa8, 0x23, 0x71, 0xa9, 0x21, 0x84,
|
||||||
0xc4, 0x43, 0xc5, 0xcd, 0xa4, 0x7a, 0xda, 0x08, 0xb6, 0xb7, 0xcb, 0x1f, 0xb9, 0x53, 0x25, 0xdb,
|
0x87, 0x8a, 0x9a, 0x49, 0xf5, 0xb4, 0x11, 0x6c, 0x6f, 0x97, 0x3f, 0x72, 0xa7, 0x4a, 0xb5, 0x23,
|
||||||
0x11, 0xa9, 0x73, 0x73, 0xa7, 0x7a, 0x48, 0xf7, 0x89, 0x33, 0xe1, 0x6b, 0xe5, 0xd3, 0x27, 0x93,
|
0x12, 0xe7, 0xe6, 0x4e, 0xf5, 0x90, 0xee, 0x13, 0x67, 0xc2, 0xd7, 0xca, 0xa7, 0x4f, 0x26, 0xa9,
|
||||||
0xd4, 0x27, 0x36, 0x84, 0x4a, 0x87, 0x0f, 0x90, 0xa5, 0x68, 0xc3, 0xa2, 0x32, 0x97, 0xdf, 0x72,
|
0x4f, 0x6c, 0x08, 0x95, 0x0e, 0x1f, 0x20, 0x4b, 0xd1, 0x86, 0x45, 0x65, 0x2e, 0xbf, 0xe5, 0x0c,
|
||||||
0x86, 0xad, 0xf5, 0xf1, 0x6c, 0x5d, 0xf2, 0xfa, 0x8d, 0xf9, 0xac, 0x65, 0x72, 0xf8, 0x4d, 0xd8,
|
0x5b, 0xeb, 0xe3, 0xd9, 0xba, 0xe4, 0xf5, 0x1b, 0xf3, 0x59, 0xcb, 0xd4, 0xf0, 0x9b, 0xb0, 0x4d,
|
||||||
0x26, 0xb1, 0x5d, 0x3a, 0x2e, 0xf2, 0x94, 0x37, 0x53, 0xb0, 0x13, 0xe5, 0x44, 0xef, 0x0b, 0xef,
|
0x62, 0xbb, 0x74, 0x5c, 0xe4, 0x29, 0x6f, 0x26, 0x60, 0x27, 0xca, 0x89, 0xde, 0x17, 0xde, 0x6d,
|
||||||
0x36, 0x95, 0xb9, 0xbb, 0x59, 0x6b, 0x99, 0x42, 0xab, 0x9a, 0xde, 0x51, 0x63, 0x38, 0xee, 0x9b,
|
0x2a, 0x6f, 0x77, 0xb3, 0xd6, 0x32, 0x85, 0x56, 0x35, 0xbd, 0xa3, 0xc6, 0x70, 0xdc, 0x37, 0x57,
|
||||||
0x2b, 0xea, 0xf9, 0xdf, 0x1f, 0xaf, 0xc9, 0x4d, 0x12, 0x6f, 0x63, 0xbb, 0xb8, 0x3d, 0x9e, 0xa8,
|
0xd4, 0xb3, 0xbf, 0x3f, 0x5e, 0x93, 0x9b, 0x24, 0xde, 0xc6, 0x76, 0x71, 0x7b, 0x3c, 0x51, 0xef,
|
||||||
0x77, 0x93, 0x3d, 0x55, 0xad, 0x4a, 0x25, 0xaf, 0xea, 0xfd, 0xaf, 0xc3, 0x3d, 0xc2, 0xe7, 0x51,
|
0x26, 0x7b, 0xaa, 0x5a, 0x95, 0x48, 0x5e, 0xd5, 0xfb, 0x5f, 0x87, 0x7b, 0x84, 0xcf, 0xa3, 0xac,
|
||||||
0x56, 0x8c, 0xad, 0xc3, 0x3d, 0xf8, 0x61, 0xe3, 0xef, 0x55, 0xb1, 0x8c, 0xc7, 0xd6, 0x7f, 0x03,
|
0x18, 0x5b, 0x87, 0x7b, 0xf0, 0xc3, 0xc6, 0xdf, 0xab, 0x62, 0x19, 0x8f, 0xad, 0xff, 0x06, 0x9d,
|
||||||
0x85, 0xba, 0x35, 0xc8, 0xe5, 0x89, 0x01, 0x00
|
0xe0, 0x6a, 0xd1, 0xe3, 0x89, 0x01, 0x00
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* JSON API (De)serialization
|
* JSON API (De)serialization
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist)
|
void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||||
{
|
{
|
||||||
byte id = elem["id"] | it;
|
byte id = elem["id"] | it;
|
||||||
if (id < strip.getMaxSegments())
|
if (id < strip.getMaxSegments())
|
||||||
@ -127,15 +127,18 @@ void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist)
|
|||||||
|
|
||||||
//temporary, strip object gets updated via colorUpdated()
|
//temporary, strip object gets updated via colorUpdated()
|
||||||
if (id == strip.getMainSegmentId()) {
|
if (id == strip.getMainSegmentId()) {
|
||||||
// it may be a good idea to also stop playlist if effect has changed
|
byte effectPrev = effectCurrent;
|
||||||
if (!fromPlaylist && !elem["fx"].isNull()) unloadPlaylist();
|
effectCurrent = elem[F("fx")] | effectCurrent;
|
||||||
effectCurrent = elem["fx"] | effectCurrent;
|
if (!presetId && effectCurrent != effectPrev) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||||
effectSpeed = elem[F("sx")] | effectSpeed;
|
effectSpeed = elem[F("sx")] | effectSpeed;
|
||||||
effectIntensity = elem[F("ix")] | effectIntensity;
|
effectIntensity = elem[F("ix")] | effectIntensity;
|
||||||
effectPalette = elem["pal"] | effectPalette;
|
effectPalette = elem["pal"] | effectPalette;
|
||||||
} else { //permanent
|
} else { //permanent
|
||||||
byte fx = elem["fx"] | seg.mode;
|
byte fx = elem[F("fx")] | seg.mode;
|
||||||
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
|
if (fx != seg.mode && fx < strip.getModeCount()) {
|
||||||
|
strip.setMode(id, fx);
|
||||||
|
if (!presetId) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||||
|
}
|
||||||
seg.speed = elem[F("sx")] | seg.speed;
|
seg.speed = elem[F("sx")] | seg.speed;
|
||||||
seg.intensity = elem[F("ix")] | seg.intensity;
|
seg.intensity = elem[F("ix")] | seg.intensity;
|
||||||
seg.palette = elem["pal"] | seg.palette;
|
seg.palette = elem["pal"] | seg.palette;
|
||||||
@ -190,7 +193,7 @@ void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool deserializeState(JsonObject root, bool fromPlaylist)
|
bool deserializeState(JsonObject root, byte presetId)
|
||||||
{
|
{
|
||||||
strip.applyToAllSelected = false;
|
strip.applyToAllSelected = false;
|
||||||
bool stateResponse = root[F("v")] | false;
|
bool stateResponse = root[F("v")] | false;
|
||||||
@ -202,12 +205,15 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
|||||||
|
|
||||||
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||||
|
|
||||||
int tr = root[F("transition")] | -1;
|
int tr = -1;
|
||||||
if (tr >= 0)
|
if (!presetId || currentPlaylist < 0) { //do not apply transition time from preset if playlist active, as it would override playlist transition times
|
||||||
{
|
tr = root[F("transition")] | -1;
|
||||||
transitionDelay = tr;
|
if (tr >= 0)
|
||||||
transitionDelay *= 100;
|
{
|
||||||
transitionDelayTemp = transitionDelay;
|
transitionDelay = tr;
|
||||||
|
transitionDelay *= 100;
|
||||||
|
transitionDelayTemp = transitionDelay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr = root[F("tt")] | -1;
|
tr = root[F("tt")] | -1;
|
||||||
@ -244,14 +250,7 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
|||||||
|
|
||||||
unsigned long timein = root[F("time")] | UINT32_MAX; //backup time source if NTP not synced
|
unsigned long timein = root[F("time")] | UINT32_MAX; //backup time source if NTP not synced
|
||||||
if (timein != UINT32_MAX) {
|
if (timein != UINT32_MAX) {
|
||||||
time_t prev = now();
|
setTimeFromAPI(timein);
|
||||||
if (millis() - ntpLastSyncTime > 50000000L) {
|
|
||||||
setTime(timein);
|
|
||||||
if (abs(now() - prev) > 60L) {
|
|
||||||
updateLocalTime();
|
|
||||||
calculateSunriseAndSunset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (presetsModifiedTime == 0) presetsModifiedTime = timein;
|
if (presetsModifiedTime == 0) presetsModifiedTime = timein;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,24 +285,30 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
|||||||
{
|
{
|
||||||
if (lowestActive == 99) lowestActive = s;
|
if (lowestActive == 99) lowestActive = s;
|
||||||
if (sg.isSelected()) {
|
if (sg.isSelected()) {
|
||||||
deserializeSegment(segVar, s, fromPlaylist);
|
deserializeSegment(segVar, s, presetId);
|
||||||
didSet = true;
|
didSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!didSet && lowestActive < strip.getMaxSegments()) deserializeSegment(segVar, lowestActive, fromPlaylist);
|
if (!didSet && lowestActive < strip.getMaxSegments()) deserializeSegment(segVar, lowestActive, presetId);
|
||||||
} else { //set only the segment with the specified ID
|
} else { //set only the segment with the specified ID
|
||||||
deserializeSegment(segVar, id, fromPlaylist);
|
deserializeSegment(segVar, it, presetId);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JsonArray segs = segVar.as<JsonArray>();
|
JsonArray segs = segVar.as<JsonArray>();
|
||||||
for (JsonObject elem : segs)
|
for (JsonObject elem : segs)
|
||||||
{
|
{
|
||||||
deserializeSegment(elem, it, fromPlaylist);
|
deserializeSegment(elem, it, presetId);
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_CRONIXIE
|
||||||
|
if (root["nx"].is<const char*>()) {
|
||||||
|
strncpy(cronixieDisplay, root["nx"], 6);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
usermods.readFromJsonState(root);
|
usermods.readFromJsonState(root);
|
||||||
|
|
||||||
int8_t ledmap = root[F("ledmap")] | -1;
|
int8_t ledmap = root[F("ledmap")] | -1;
|
||||||
@ -320,7 +325,11 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
|||||||
deletePreset(ps);
|
deletePreset(ps);
|
||||||
}
|
}
|
||||||
ps = root["ps"] | -1; //load preset (clears state request!)
|
ps = root["ps"] | -1; //load preset (clears state request!)
|
||||||
if (ps >= 0) {applyPreset(ps); return stateResponse;}
|
if (ps >= 0) {
|
||||||
|
if (!presetId) unloadPlaylist(); //stop playlist if preset changed manually
|
||||||
|
applyPreset(ps);
|
||||||
|
return stateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
//HTTP API commands
|
//HTTP API commands
|
||||||
const char* httpwin = root["win"];
|
const char* httpwin = root["win"];
|
||||||
@ -333,7 +342,7 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
|||||||
|
|
||||||
JsonObject playlist = root[F("playlist")];
|
JsonObject playlist = root[F("playlist")];
|
||||||
if (!playlist.isNull()) {
|
if (!playlist.isNull()) {
|
||||||
loadPlaylist(playlist);
|
loadPlaylist(playlist, presetId);
|
||||||
noNotification = true; //do not notify both for this request and the first playlist entry
|
noNotification = true; //do not notify both for this request and the first playlist entry
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,7 +358,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
|||||||
root[F("start")] = seg.start;
|
root[F("start")] = seg.start;
|
||||||
root["stop"] = seg.stop;
|
root["stop"] = seg.stop;
|
||||||
}
|
}
|
||||||
if (!forPreset) root[F("len")] = seg.stop - seg.start;
|
if (!forPreset) root[F("len")] = seg.stop - seg.start;
|
||||||
root[F("grp")] = seg.grouping;
|
root[F("grp")] = seg.grouping;
|
||||||
root[F("spc")] = seg.spacing;
|
root[F("spc")] = seg.spacing;
|
||||||
root["on"] = seg.getOption(SEG_OPTION_ON);
|
root["on"] = seg.getOption(SEG_OPTION_ON);
|
||||||
|
107
wled00/ntp.cpp
107
wled00/ntp.cpp
@ -16,6 +16,9 @@
|
|||||||
/*
|
/*
|
||||||
* Acquires time from NTP server
|
* Acquires time from NTP server
|
||||||
*/
|
*/
|
||||||
|
//#define WLED_DEBUG_NTP
|
||||||
|
#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day
|
||||||
|
|
||||||
Timezone* tz;
|
Timezone* tz;
|
||||||
|
|
||||||
#define TZ_UTC 0
|
#define TZ_UTC 0
|
||||||
@ -144,9 +147,28 @@ void updateTimezone() {
|
|||||||
tz = new Timezone(tcrDaylight, tcrStandard);
|
tz = new Timezone(tcrDaylight, tcrStandard);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleTime() {
|
||||||
|
handleNetworkTime();
|
||||||
|
|
||||||
|
toki.millisecond();
|
||||||
|
toki.setTick();
|
||||||
|
|
||||||
|
if (toki.isTick()) //true only in the first loop after a new second started
|
||||||
|
{
|
||||||
|
#ifdef WLED_DEBUG_NTP
|
||||||
|
Serial.print(F("TICK! "));
|
||||||
|
toki.printTime(toki.getTime());
|
||||||
|
#endif
|
||||||
|
updateLocalTime();
|
||||||
|
checkTimers();
|
||||||
|
checkCountdown();
|
||||||
|
handleOverlays();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleNetworkTime()
|
void handleNetworkTime()
|
||||||
{
|
{
|
||||||
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WLED_CONNECTED)
|
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED)
|
||||||
{
|
{
|
||||||
if (millis() - ntpPacketSentTime > 10000)
|
if (millis() - ntpPacketSentTime > 10000)
|
||||||
{
|
{
|
||||||
@ -193,35 +215,52 @@ void sendNTPPacket()
|
|||||||
bool checkNTPResponse()
|
bool checkNTPResponse()
|
||||||
{
|
{
|
||||||
int cb = ntpUdp.parsePacket();
|
int cb = ntpUdp.parsePacket();
|
||||||
if (cb) {
|
if (!cb) return false;
|
||||||
DEBUG_PRINT(F("NTP recv, l="));
|
|
||||||
DEBUG_PRINTLN(cb);
|
|
||||||
byte pbuf[NTP_PACKET_SIZE];
|
|
||||||
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
|
|
||||||
|
|
||||||
unsigned long highWord = word(pbuf[40], pbuf[41]);
|
uint32_t ntpPacketReceivedTime = millis();
|
||||||
unsigned long lowWord = word(pbuf[42], pbuf[43]);
|
DEBUG_PRINT(F("NTP recv, l="));
|
||||||
if (highWord == 0 && lowWord == 0) return false;
|
DEBUG_PRINTLN(cb);
|
||||||
|
byte pbuf[NTP_PACKET_SIZE];
|
||||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||||
|
|
||||||
DEBUG_PRINT(F("Unix time = "));
|
Toki::Time arrived = toki.fromNTP(pbuf + 32);
|
||||||
unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
|
Toki::Time departed = toki.fromNTP(pbuf + 40);
|
||||||
setTime(epoch);
|
if (departed.sec == 0) return false;
|
||||||
DEBUG_PRINTLN(epoch);
|
//basic half roundtrip estimation
|
||||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
uint32_t serverDelay = toki.msDifference(arrived, departed);
|
||||||
// if time changed re-calculate sunrise/sunset
|
uint32_t offset = (ntpPacketReceivedTime - ntpPacketSentTime - serverDelay) >> 1;
|
||||||
updateLocalTime();
|
#ifdef WLED_DEBUG_NTP
|
||||||
calculateSunriseAndSunset();
|
//the time the packet departed the NTP server
|
||||||
return true;
|
toki.printTime(departed);
|
||||||
}
|
#endif
|
||||||
return false;
|
|
||||||
|
toki.adjust(departed, offset);
|
||||||
|
toki.setTime(departed, TOKI_TS_NTP);
|
||||||
|
|
||||||
|
#ifdef WLED_DEBUG_NTP
|
||||||
|
Serial.print("Arrived: ");
|
||||||
|
toki.printTime(arrived);
|
||||||
|
Serial.print("Time: ");
|
||||||
|
toki.printTime(departed);
|
||||||
|
Serial.print("Roundtrip: ");
|
||||||
|
Serial.println(ntpPacketReceivedTime - ntpPacketSentTime);
|
||||||
|
Serial.print("Offset: ");
|
||||||
|
Serial.println(offset);
|
||||||
|
Serial.print("Serverdelay: ");
|
||||||
|
Serial.println(serverDelay);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (countdownTime - toki.second() > 0) countdownOverTriggered = false;
|
||||||
|
// if time changed re-calculate sunrise/sunset
|
||||||
|
updateLocalTime();
|
||||||
|
calculateSunriseAndSunset();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateLocalTime()
|
void updateLocalTime()
|
||||||
{
|
{
|
||||||
if (currentTimezone != tzCurrent) updateTimezone();
|
if (currentTimezone != tzCurrent) updateTimezone();
|
||||||
unsigned long tmc = now()+ utcOffsetSecs;
|
unsigned long tmc = toki.second()+ utcOffsetSecs;
|
||||||
localTime = tz->toLocal(tmc);
|
localTime = tz->toLocal(tmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,13 +284,13 @@ void setCountdown()
|
|||||||
{
|
{
|
||||||
if (currentTimezone != tzCurrent) updateTimezone();
|
if (currentTimezone != tzCurrent) updateTimezone();
|
||||||
countdownTime = tz->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear));
|
countdownTime = tz->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear));
|
||||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
if (countdownTime - toki.second() > 0) countdownOverTriggered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns true if countdown just over
|
//returns true if countdown just over
|
||||||
bool checkCountdown()
|
bool checkCountdown()
|
||||||
{
|
{
|
||||||
unsigned long n = now();
|
unsigned long n = toki.second();
|
||||||
if (countdownMode) localTime = countdownTime - n + utcOffsetSecs;
|
if (countdownMode) localTime = countdownTime - n + utcOffsetSecs;
|
||||||
if (n > countdownTime) {
|
if (n > countdownTime) {
|
||||||
if (countdownMode) localTime = n - countdownTime + utcOffsetSecs;
|
if (countdownMode) localTime = n - countdownTime + utcOffsetSecs;
|
||||||
@ -410,3 +449,19 @@ void calculateSunriseAndSunset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//time from JSON and HTTP API
|
||||||
|
void setTimeFromAPI(uint32_t timein) {
|
||||||
|
if (timein == 0 || timein == UINT32_MAX) return;
|
||||||
|
uint32_t prev = toki.second();
|
||||||
|
//only apply if more accurate or there is a significant difference to the "more accurate" time source
|
||||||
|
uint32_t diff = (timein > prev) ? timein - prev : prev - timein;
|
||||||
|
if (toki.getTimeSource() > TOKI_TS_JSON && diff < 60U) return;
|
||||||
|
|
||||||
|
toki.setTime(timein, TOKI_NO_MS_ACCURACY, TOKI_TS_JSON);
|
||||||
|
if (diff >= 60U) {
|
||||||
|
updateLocalTime();
|
||||||
|
calculateSunriseAndSunset();
|
||||||
|
}
|
||||||
|
if (presetsModifiedTime == 0) presetsModifiedTime = timein;
|
||||||
|
}
|
@ -6,29 +6,24 @@
|
|||||||
|
|
||||||
void initCronixie()
|
void initCronixie()
|
||||||
{
|
{
|
||||||
if (overlayCurrent == 3 && !cronixieInit)
|
if (overlayCurrent == 3 && dP[0] == 255) //if dP[0] is 255, cronixie is not yet init'ed
|
||||||
{
|
{
|
||||||
setCronixie();
|
setCronixie();
|
||||||
strip.getSegment(0).grouping = 10; //10 LEDs per digit
|
strip.getSegment(0).grouping = 10; //10 LEDs per digit
|
||||||
cronixieInit = true;
|
} else if (dP[0] < 255 && overlayCurrent != 3)
|
||||||
} else if (cronixieInit && overlayCurrent != 3)
|
|
||||||
{
|
{
|
||||||
strip.getSegment(0).grouping = 1;
|
strip.getSegment(0).grouping = 1;
|
||||||
cronixieInit = false;
|
dP[0] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void handleOverlays()
|
void handleOverlays()
|
||||||
{
|
{
|
||||||
if (millis() - overlayRefreshedTime > overlayRefreshMs)
|
initCronixie();
|
||||||
{
|
if (overlayCurrent == 3) {
|
||||||
initCronixie();
|
_overlayCronixie();//Diamex cronixie clock kit
|
||||||
updateLocalTime();
|
strip.trigger();
|
||||||
checkTimers();
|
|
||||||
checkCountdown();
|
|
||||||
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
|
|
||||||
overlayRefreshedTime = millis();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,15 +68,14 @@ void _overlayAnalogClock()
|
|||||||
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
||||||
strip.setPixelColor(minutePixel, 0x00FF00);
|
strip.setPixelColor(minutePixel, 0x00FF00);
|
||||||
strip.setPixelColor(hourPixel, 0x0000FF);
|
strip.setPixelColor(hourPixel, 0x0000FF);
|
||||||
overlayRefreshMs = 998;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _overlayAnalogCountdown()
|
void _overlayAnalogCountdown()
|
||||||
{
|
{
|
||||||
if ((unsigned long)now() < countdownTime)
|
if ((unsigned long)toki.second() < countdownTime)
|
||||||
{
|
{
|
||||||
long diff = countdownTime - now();
|
long diff = countdownTime - toki.second();
|
||||||
double pval = 60;
|
double pval = 60;
|
||||||
if (diff > 31557600L) //display in years if more than 365 days
|
if (diff > 31557600L) //display in years if more than 365 days
|
||||||
{
|
{
|
||||||
@ -115,7 +109,6 @@ void _overlayAnalogCountdown()
|
|||||||
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,8 +212,6 @@ void setCronixie()
|
|||||||
|
|
||||||
DEBUG_PRINT("cset ");
|
DEBUG_PRINT("cset ");
|
||||||
DEBUG_PRINTLN(cronixieDisplay);
|
DEBUG_PRINTLN(cronixieDisplay);
|
||||||
|
|
||||||
overlayRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
@ -241,8 +232,8 @@ void setCronixie()
|
|||||||
case 'a': dP[i] = 58; i++; break;
|
case 'a': dP[i] = 58; i++; break;
|
||||||
case 'm': dP[i] = 74 + getSameCodeLength('m',i,cronixieDisplay); i = i+dP[i]-74; break;
|
case 'm': dP[i] = 74 + getSameCodeLength('m',i,cronixieDisplay); i = i+dP[i]-74; break;
|
||||||
case 'M': dP[i] = 24 + getSameCodeLength('M',i,cronixieDisplay); i = i+dP[i]-24; break;
|
case 'M': dP[i] = 24 + getSameCodeLength('M',i,cronixieDisplay); i = i+dP[i]-24; break;
|
||||||
case 's': dP[i] = 80 + getSameCodeLength('s',i,cronixieDisplay); i = i+dP[i]-80; overlayRefreshMs = 497; break; //refresh more often bc. of secs
|
case 's': dP[i] = 80 + getSameCodeLength('s',i,cronixieDisplay); i = i+dP[i]-80; break; //refresh more often bc. of secs
|
||||||
case 'S': dP[i] = 30 + getSameCodeLength('S',i,cronixieDisplay); i = i+dP[i]-30; overlayRefreshMs = 497; break;
|
case 'S': dP[i] = 30 + getSameCodeLength('S',i,cronixieDisplay); i = i+dP[i]-30; break;
|
||||||
case 'Y': dP[i] = 36 + getSameCodeLength('Y',i,cronixieDisplay); i = i+dP[i]-36; break;
|
case 'Y': dP[i] = 36 + getSameCodeLength('Y',i,cronixieDisplay); i = i+dP[i]-36; break;
|
||||||
case 'y': dP[i] = 86 + getSameCodeLength('y',i,cronixieDisplay); i = i+dP[i]-86; break;
|
case 'y': dP[i] = 86 + getSameCodeLength('y',i,cronixieDisplay); i = i+dP[i]-86; break;
|
||||||
case 'I': dP[i] = 39 + getSameCodeLength('I',i,cronixieDisplay); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M.
|
case 'I': dP[i] = 39 + getSameCodeLength('I',i,cronixieDisplay); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M.
|
||||||
|
@ -5,18 +5,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct PlaylistEntry {
|
typedef struct PlaylistEntry {
|
||||||
uint8_t preset;
|
uint8_t preset; //ID of the preset to apply
|
||||||
uint16_t dur;
|
uint16_t dur; //Duration of the entry (in tenths of seconds)
|
||||||
uint16_t tr;
|
uint16_t tr; //Duration of the transition TO this entry (in tenths of seconds)
|
||||||
} ple;
|
} ple;
|
||||||
|
|
||||||
bool playlistEndless = false;
|
byte playlistRepeat = 1; //how many times to repeat the playlist (0 = infinitely)
|
||||||
int8_t playlistRepeat = 1;
|
byte playlistEndPreset = 0; //what preset to apply after playlist end (0 = stay on last preset)
|
||||||
byte playlistEndPreset = 0;
|
byte playlistOptions = 0; //bit 0: shuffle playlist after each iteration. bits 1-7 TBD
|
||||||
|
|
||||||
PlaylistEntry *playlistEntries = nullptr;
|
PlaylistEntry *playlistEntries = nullptr;
|
||||||
byte playlistLen;
|
byte playlistLen; //number of playlist entries
|
||||||
int8_t playlistIndex = -1;
|
int8_t playlistIndex = -1;
|
||||||
uint16_t playlistEntryDur = 0;
|
uint16_t playlistEntryDur = 0; //duration of the current entry in tenths of seconds
|
||||||
|
|
||||||
|
//values we need to keep about the parent playlist while inside sub-playlist
|
||||||
|
//int8_t parentPlaylistIndex = -1;
|
||||||
|
//byte parentPlaylistRepeat = 0;
|
||||||
|
//byte parentPlaylistPresetId = 0; //for re-loading
|
||||||
|
|
||||||
|
|
||||||
void shufflePlaylist() {
|
void shufflePlaylist() {
|
||||||
@ -42,12 +48,12 @@ void unloadPlaylist() {
|
|||||||
playlistEntries = nullptr;
|
playlistEntries = nullptr;
|
||||||
}
|
}
|
||||||
currentPlaylist = playlistIndex = -1;
|
currentPlaylist = playlistIndex = -1;
|
||||||
playlistLen = playlistEntryDur = 0;
|
playlistLen = playlistEntryDur = playlistOptions = 0;
|
||||||
DEBUG_PRINTLN(F("Playlist unloaded."));
|
DEBUG_PRINTLN(F("Playlist unloaded."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void loadPlaylist(JsonObject playlistObj) {
|
void loadPlaylist(JsonObject playlistObj, byte presetId) {
|
||||||
unloadPlaylist();
|
unloadPlaylist();
|
||||||
|
|
||||||
JsonArray presets = playlistObj["ps"];
|
JsonArray presets = playlistObj["ps"];
|
||||||
@ -68,12 +74,12 @@ void loadPlaylist(JsonObject playlistObj) {
|
|||||||
it = 0;
|
it = 0;
|
||||||
JsonArray durations = playlistObj["dur"];
|
JsonArray durations = playlistObj["dur"];
|
||||||
if (durations.isNull()) {
|
if (durations.isNull()) {
|
||||||
playlistEntries[0].dur = playlistObj["dur"] | 100;
|
playlistEntries[0].dur = playlistObj["dur"] | 100; //10 seconds as fallback
|
||||||
it = 1;
|
it = 1;
|
||||||
} else {
|
} else {
|
||||||
for (int dur : durations) {
|
for (int dur : durations) {
|
||||||
if (it >= playlistLen) break;
|
if (it >= playlistLen) break;
|
||||||
playlistEntries[it].dur = (dur > 0) ? dur : presetCycleTime;
|
playlistEntries[it].dur = (dur > 1) ? dur : 100;
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,12 +99,19 @@ void loadPlaylist(JsonObject playlistObj) {
|
|||||||
}
|
}
|
||||||
for (int i = it; i < playlistLen; i++) playlistEntries[i].tr = playlistEntries[it -1].tr;
|
for (int i = it; i < playlistLen; i++) playlistEntries[i].tr = playlistEntries[it -1].tr;
|
||||||
|
|
||||||
playlistRepeat = playlistObj[F("repeat")] | 0;
|
int rep = playlistObj[F("repeat")];
|
||||||
|
bool shuffle = false;
|
||||||
|
if (rep < 0) { //support negative values as infinite + shuffle
|
||||||
|
rep = 0; shuffle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
playlistRepeat = rep;
|
||||||
|
if (playlistRepeat > 0) playlistRepeat++; //add one extra repetition immediately since it will be deducted on first start
|
||||||
playlistEndPreset = playlistObj[F("end")] | 0;
|
playlistEndPreset = playlistObj[F("end")] | 0;
|
||||||
|
shuffle = shuffle || playlistObj["r"];
|
||||||
|
if (shuffle) playlistOptions += PL_OPTION_SHUFFLE;
|
||||||
|
|
||||||
if (playlistRepeat <= 0) playlistRepeat--; // make it endless (-2 == endless & random)
|
currentPlaylist = presetId;
|
||||||
|
|
||||||
currentPlaylist = 0; //TODO here we need the preset ID where the playlist is saved
|
|
||||||
DEBUG_PRINTLN(F("Playlist loaded."));
|
DEBUG_PRINTLN(F("Playlist loaded."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,21 +125,21 @@ void handlePlaylist() {
|
|||||||
|
|
||||||
++playlistIndex %= playlistLen; // -1 at 1st run (limit to playlistLen)
|
++playlistIndex %= playlistLen; // -1 at 1st run (limit to playlistLen)
|
||||||
|
|
||||||
if (!playlistRepeat && !playlistIndex) { //stop if repeat == 0 and restart of playlist
|
|
||||||
unloadPlaylist();
|
|
||||||
if (playlistEndPreset) applyPreset(playlistEndPreset);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// playlist roll-over
|
// playlist roll-over
|
||||||
if (!playlistIndex) {
|
if (!playlistIndex) {
|
||||||
// playlistRepeat < 0 => endless loop
|
if (playlistRepeat == 1) { //stop if all repetitions are done
|
||||||
if (playlistRepeat > 0) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
|
unloadPlaylist();
|
||||||
if (playlistRepeat < -1) shufflePlaylist(); // shuffle playlist and start over
|
if (playlistEndPreset) applyPreset(playlistEndPreset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
|
||||||
|
// playlistRepeat == 0: endless loop
|
||||||
|
if (playlistOptions & PL_OPTION_SHUFFLE) shufflePlaylist(); // shuffle playlist and start over
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonTransitionOnce = true;
|
jsonTransitionOnce = true;
|
||||||
transitionDelayTemp = playlistEntries[playlistIndex].tr * 100;
|
transitionDelayTemp = playlistEntries[playlistIndex].tr * 100;
|
||||||
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
||||||
applyPreset(playlistEntries[playlistIndex].preset, true);
|
applyPreset(playlistEntries[playlistIndex].preset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,80 +1,82 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Methods to handle saving and loading presets to/from the filesystem
|
* Methods to handle saving and loading presets to/from the filesystem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool applyPreset(byte index, bool fromPlaylist)
|
bool applyPreset(byte index)
|
||||||
{
|
{
|
||||||
if (index == 0) return false;
|
if (index == 0) return false;
|
||||||
if (fileDoc) { // from POST "/json" handler (wled_server.cpp)
|
if (fileDoc) {
|
||||||
errorFlag = readObjectFromFileUsingId("/presets.json", index, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
errorFlag = readObjectFromFileUsingId("/presets.json", index, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||||
JsonObject fdo = fileDoc->as<JsonObject>();
|
JsonObject fdo = fileDoc->as<JsonObject>();
|
||||||
if (fdo["ps"] == index) fdo.remove("ps"); //remove load request for same presets to prevent recursive crash
|
if (fdo["ps"] == index) fdo.remove("ps"); //remove load request for same presets to prevent recursive crash
|
||||||
#ifdef WLED_DEBUG_FS
|
#ifdef WLED_DEBUG_FS
|
||||||
serializeJson(*fileDoc, Serial);
|
serializeJson(*fileDoc, Serial);
|
||||||
#endif
|
#endif
|
||||||
deserializeState(fdo, fromPlaylist);
|
deserializeState(fdo, index);
|
||||||
} else {
|
} else {
|
||||||
DEBUGFS_PRINTLN(F("Make read buf"));
|
DEBUGFS_PRINTLN(F("Make read buf"));
|
||||||
DynamicJsonDocument fDoc(JSON_BUFFER_SIZE);
|
DynamicJsonDocument fDoc(JSON_BUFFER_SIZE);
|
||||||
errorFlag = readObjectFromFileUsingId("/presets.json", index, &fDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
errorFlag = readObjectFromFileUsingId("/presets.json", index, &fDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||||
JsonObject fdo = fDoc.as<JsonObject>();
|
JsonObject fdo = fDoc.as<JsonObject>();
|
||||||
if (fdo["ps"] == index) fdo.remove("ps");
|
if (fdo["ps"] == index) fdo.remove("ps");
|
||||||
#ifdef WLED_DEBUG_FS
|
#ifdef WLED_DEBUG_FS
|
||||||
serializeJson(fDoc, Serial);
|
serializeJson(fDoc, Serial);
|
||||||
#endif
|
#endif
|
||||||
deserializeState(fdo, fromPlaylist);
|
deserializeState(fdo, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errorFlag) {
|
if (!errorFlag) {
|
||||||
currentPreset = index;
|
currentPreset = index;
|
||||||
isPreset = true;
|
isPreset = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
//persist=false is not currently honored
|
||||||
{
|
void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
||||||
if (index == 0 || index > 250) return;
|
{
|
||||||
bool docAlloc = (fileDoc != nullptr);
|
if (index == 0 || index > 250) return;
|
||||||
JsonObject sObj = saveobj;
|
bool docAlloc = (fileDoc != nullptr);
|
||||||
|
JsonObject sObj = saveobj;
|
||||||
if (!docAlloc) {
|
|
||||||
DEBUGFS_PRINTLN(F("Allocating saving buffer"));
|
if (!docAlloc) {
|
||||||
DynamicJsonDocument lDoc(JSON_BUFFER_SIZE);
|
DEBUGFS_PRINTLN(F("Allocating saving buffer"));
|
||||||
sObj = lDoc.to<JsonObject>();
|
DynamicJsonDocument lDoc(JSON_BUFFER_SIZE);
|
||||||
if (pname) sObj["n"] = pname;
|
sObj = lDoc.to<JsonObject>();
|
||||||
DEBUGFS_PRINTLN(F("Save current state"));
|
if (pname) sObj["n"] = pname;
|
||||||
serializeState(sObj, true);
|
DEBUGFS_PRINTLN(F("Save current state"));
|
||||||
currentPreset = index;
|
serializeState(sObj, true);
|
||||||
|
currentPreset = index;
|
||||||
writeObjectToFileUsingId("/presets.json", index, &lDoc);
|
|
||||||
} else { //from JSON API
|
writeObjectToFileUsingId("/presets.json", index, &lDoc);
|
||||||
DEBUGFS_PRINTLN(F("Reuse recv buffer"));
|
} else { //from JSON API
|
||||||
sObj.remove(F("psave"));
|
DEBUGFS_PRINTLN(F("Reuse recv buffer"));
|
||||||
sObj.remove(F("v"));
|
sObj.remove(F("psave"));
|
||||||
if (!sObj["o"]) {
|
sObj.remove(F("v"));
|
||||||
DEBUGFS_PRINTLN(F("Save current state"));
|
|
||||||
serializeState(sObj, true, sObj["ib"], sObj["sb"]);
|
if (!sObj["o"]) {
|
||||||
currentPreset = index;
|
DEBUGFS_PRINTLN(F("Save current state"));
|
||||||
}
|
serializeState(sObj, true, sObj["ib"], sObj["sb"]);
|
||||||
sObj.remove("o");
|
currentPreset = index;
|
||||||
sObj.remove("ib");
|
}
|
||||||
sObj.remove("sb");
|
sObj.remove("o");
|
||||||
sObj.remove(F("error"));
|
sObj.remove("ib");
|
||||||
sObj.remove(F("time"));
|
sObj.remove("sb");
|
||||||
|
sObj.remove(F("error"));
|
||||||
writeObjectToFileUsingId("/presets.json", index, fileDoc);
|
sObj.remove(F("time"));
|
||||||
}
|
|
||||||
presetsModifiedTime = now(); //unix time
|
writeObjectToFileUsingId("/presets.json", index, fileDoc);
|
||||||
updateFSInfo();
|
}
|
||||||
}
|
presetsModifiedTime = toki.second(); //unix time
|
||||||
|
updateFSInfo();
|
||||||
void deletePreset(byte index) {
|
}
|
||||||
StaticJsonDocument<24> empty;
|
|
||||||
writeObjectToFileUsingId("/presets.json", index, &empty);
|
void deletePreset(byte index) {
|
||||||
presetsModifiedTime = now(); //unix time
|
StaticJsonDocument<24> empty;
|
||||||
updateFSInfo();
|
writeObjectToFileUsingId("/presets.json", index, &empty);
|
||||||
|
presetsModifiedTime = toki.second(); //unix time
|
||||||
|
updateFSInfo();
|
||||||
}
|
}
|
@ -78,9 +78,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
|
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
|
||||||
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
|
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
|
||||||
#endif
|
|
||||||
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++)
|
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++)
|
||||||
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s]))
|
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s]))
|
||||||
pinManager.deallocatePin(btnPin[s]);
|
pinManager.deallocatePin(btnPin[s]);
|
||||||
@ -127,7 +125,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
ledCount = request->arg(F("LC")).toInt();
|
ledCount = request->arg(F("LC")).toInt();
|
||||||
|
|
||||||
// upate other pins
|
// upate other pins
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
|
||||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||||
irPin = hw_ir_pin;
|
irPin = hw_ir_pin;
|
||||||
@ -135,7 +132,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
irPin = -1;
|
irPin = -1;
|
||||||
}
|
}
|
||||||
irEnabled = request->arg(F("IT")).toInt();
|
irEnabled = request->arg(F("IT")).toInt();
|
||||||
#endif
|
|
||||||
|
|
||||||
int hw_rly_pin = request->arg(F("RL")).toInt();
|
int hw_rly_pin = request->arg(F("RL")).toInt();
|
||||||
if (pinManager.allocatePin(hw_rly_pin,true)) {
|
if (pinManager.allocatePin(hw_rly_pin,true)) {
|
||||||
@ -202,8 +198,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
//SYNC
|
//SYNC
|
||||||
if (subPage == 4)
|
if (subPage == 4)
|
||||||
{
|
{
|
||||||
//buttonType = request->arg(F("BT")).toInt();
|
|
||||||
//irEnabled = request->arg(F("IR")).toInt();
|
|
||||||
int t = request->arg(F("UP")).toInt();
|
int t = request->arg(F("UP")).toInt();
|
||||||
if (t > 0) udpPort = t;
|
if (t > 0) udpPort = t;
|
||||||
t = request->arg(F("U2")).toInt();
|
t = request->arg(F("U2")).toInt();
|
||||||
@ -814,14 +808,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
//set time (unix timestamp)
|
//set time (unix timestamp)
|
||||||
pos = req.indexOf(F("ST="));
|
pos = req.indexOf(F("ST="));
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
setTime(getNumVal(&req, pos));
|
setTimeFromAPI(getNumVal(&req, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
//set countdown goal (unix timestamp)
|
//set countdown goal (unix timestamp)
|
||||||
pos = req.indexOf(F("CT="));
|
pos = req.indexOf(F("CT="));
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
countdownTime = getNumVal(&req, pos);
|
countdownTime = getNumVal(&req, pos);
|
||||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
if (countdownTime - toki.second() > 0) countdownOverTriggered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = req.indexOf(F("LO="));
|
pos = req.indexOf(F("LO="));
|
||||||
@ -841,7 +835,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
|
|
||||||
pos = req.indexOf(F("NX=")); //sets digits to code
|
pos = req.indexOf(F("NX=")); //sets digits to code
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6);
|
strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 7);
|
||||||
setCronixie();
|
setCronixie();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,7 +843,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
if (pos > 0) //sets backlight
|
if (pos > 0) //sets backlight
|
||||||
{
|
{
|
||||||
cronixieBacklight = (req.charAt(pos+3) != '0');
|
cronixieBacklight = (req.charAt(pos+3) != '0');
|
||||||
overlayRefreshedTime = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
218
wled00/src/dependencies/time/DS1307RTC.cpp
Normal file
218
wled00/src/dependencies/time/DS1307RTC.cpp
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* DS1307RTC.h - library for DS1307 RTC
|
||||||
|
|
||||||
|
Copyright (c) Michael Margolis 2009
|
||||||
|
This library is intended to be uses with Arduino Time library functions
|
||||||
|
|
||||||
|
The library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
30 Dec 2009 - Initial release
|
||||||
|
5 Sep 2011 updated for Arduino 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
|
||||||
|
#include <TinyWireM.h>
|
||||||
|
#define Wire TinyWireM
|
||||||
|
#else
|
||||||
|
#include <Wire.h>
|
||||||
|
#endif
|
||||||
|
#include "DS1307RTC.h"
|
||||||
|
|
||||||
|
#define DS1307_CTRL_ID 0x68
|
||||||
|
|
||||||
|
DS1307RTC::DS1307RTC()
|
||||||
|
{
|
||||||
|
Wire.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
time_t DS1307RTC::get() // Aquire data from buffer and convert to time_t
|
||||||
|
{
|
||||||
|
tmElements_t tm;
|
||||||
|
if (read(tm) == false) return 0;
|
||||||
|
return(makeTime(tm));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DS1307RTC::set(time_t t)
|
||||||
|
{
|
||||||
|
tmElements_t tm;
|
||||||
|
breakTime(t, tm);
|
||||||
|
return write(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aquire data from the RTC chip in BCD format
|
||||||
|
bool DS1307RTC::read(tmElements_t &tm)
|
||||||
|
{
|
||||||
|
uint8_t sec;
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x00);
|
||||||
|
#else
|
||||||
|
Wire.send(0x00);
|
||||||
|
#endif
|
||||||
|
if (Wire.endTransmission() != 0) {
|
||||||
|
exists = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exists = true;
|
||||||
|
|
||||||
|
// request the 7 data fields (secs, min, hr, dow, date, mth, yr)
|
||||||
|
Wire.requestFrom(DS1307_CTRL_ID, tmNbrFields);
|
||||||
|
if (Wire.available() < tmNbrFields) return false;
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
sec = Wire.read();
|
||||||
|
tm.Second = bcd2dec(sec & 0x7f);
|
||||||
|
tm.Minute = bcd2dec(Wire.read() );
|
||||||
|
tm.Hour = bcd2dec(Wire.read() & 0x3f); // mask assumes 24hr clock
|
||||||
|
tm.Wday = bcd2dec(Wire.read() );
|
||||||
|
tm.Day = bcd2dec(Wire.read() );
|
||||||
|
tm.Month = bcd2dec(Wire.read() );
|
||||||
|
tm.Year = y2kYearToTm((bcd2dec(Wire.read())));
|
||||||
|
#else
|
||||||
|
sec = Wire.receive();
|
||||||
|
tm.Second = bcd2dec(sec & 0x7f);
|
||||||
|
tm.Minute = bcd2dec(Wire.receive() );
|
||||||
|
tm.Hour = bcd2dec(Wire.receive() & 0x3f); // mask assumes 24hr clock
|
||||||
|
tm.Wday = bcd2dec(Wire.receive() );
|
||||||
|
tm.Day = bcd2dec(Wire.receive() );
|
||||||
|
tm.Month = bcd2dec(Wire.receive() );
|
||||||
|
tm.Year = y2kYearToTm((bcd2dec(Wire.receive())));
|
||||||
|
#endif
|
||||||
|
if (sec & 0x80) return false; // clock is halted
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DS1307RTC::write(tmElements_t &tm)
|
||||||
|
{
|
||||||
|
// To eliminate any potential race conditions,
|
||||||
|
// stop the clock before writing the values,
|
||||||
|
// then restart it after.
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x00); // reset register pointer
|
||||||
|
Wire.write((uint8_t)0x80); // Stop the clock. The seconds will be written last
|
||||||
|
Wire.write(dec2bcd(tm.Minute));
|
||||||
|
Wire.write(dec2bcd(tm.Hour)); // sets 24 hour format
|
||||||
|
Wire.write(dec2bcd(tm.Wday));
|
||||||
|
Wire.write(dec2bcd(tm.Day));
|
||||||
|
Wire.write(dec2bcd(tm.Month));
|
||||||
|
Wire.write(dec2bcd(tmYearToY2k(tm.Year)));
|
||||||
|
#else
|
||||||
|
Wire.send(0x00); // reset register pointer
|
||||||
|
Wire.send(0x80); // Stop the clock. The seconds will be written last
|
||||||
|
Wire.send(dec2bcd(tm.Minute));
|
||||||
|
Wire.send(dec2bcd(tm.Hour)); // sets 24 hour format
|
||||||
|
Wire.send(dec2bcd(tm.Wday));
|
||||||
|
Wire.send(dec2bcd(tm.Day));
|
||||||
|
Wire.send(dec2bcd(tm.Month));
|
||||||
|
Wire.send(dec2bcd(tmYearToY2k(tm.Year)));
|
||||||
|
#endif
|
||||||
|
if (Wire.endTransmission() != 0) {
|
||||||
|
exists = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exists = true;
|
||||||
|
|
||||||
|
// Now go back and set the seconds, starting the clock back up as a side effect
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x00); // reset register pointer
|
||||||
|
Wire.write(dec2bcd(tm.Second)); // write the seconds, with the stop bit clear to restart
|
||||||
|
#else
|
||||||
|
Wire.send(0x00); // reset register pointer
|
||||||
|
Wire.send(dec2bcd(tm.Second)); // write the seconds, with the stop bit clear to restart
|
||||||
|
#endif
|
||||||
|
if (Wire.endTransmission() != 0) {
|
||||||
|
exists = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
exists = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char DS1307RTC::isRunning()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x00);
|
||||||
|
#else
|
||||||
|
Wire.send(0x00);
|
||||||
|
#endif
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
// Just fetch the seconds register and check the top bit
|
||||||
|
Wire.requestFrom(DS1307_CTRL_ID, 1);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
return !(Wire.read() & 0x80);
|
||||||
|
#else
|
||||||
|
return !(Wire.receive() & 0x80);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void DS1307RTC::setCalibration(char calValue)
|
||||||
|
{
|
||||||
|
unsigned char calReg = abs(calValue) & 0x1f;
|
||||||
|
if (calValue >= 0) calReg |= 0x20; // S bit is positive to speed up the clock
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x07); // Point to calibration register
|
||||||
|
Wire.write(calReg);
|
||||||
|
#else
|
||||||
|
Wire.send(0x07); // Point to calibration register
|
||||||
|
Wire.send(calReg);
|
||||||
|
#endif
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
char DS1307RTC::getCalibration()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(DS1307_CTRL_ID);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
Wire.write((uint8_t)0x07);
|
||||||
|
#else
|
||||||
|
Wire.send(0x07);
|
||||||
|
#endif
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
Wire.requestFrom(DS1307_CTRL_ID, 1);
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
unsigned char calReg = Wire.read();
|
||||||
|
#else
|
||||||
|
unsigned char calReg = Wire.receive();
|
||||||
|
#endif
|
||||||
|
char out = calReg & 0x1f;
|
||||||
|
if (!(calReg & 0x20)) out = -out; // S bit clear means a negative value
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE FUNCTIONS
|
||||||
|
|
||||||
|
// Convert Decimal to Binary Coded Decimal (BCD)
|
||||||
|
uint8_t DS1307RTC::dec2bcd(uint8_t num)
|
||||||
|
{
|
||||||
|
return ((num/10 * 16) + (num % 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert Binary Coded Decimal (BCD) to Decimal
|
||||||
|
uint8_t DS1307RTC::bcd2dec(uint8_t num)
|
||||||
|
{
|
||||||
|
return ((num/16 * 10) + (num % 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DS1307RTC::exists = false;
|
||||||
|
|
||||||
|
DS1307RTC RTC = DS1307RTC(); // create an instance for the user
|
||||||
|
|
40
wled00/src/dependencies/time/DS1307RTC.h
Normal file
40
wled00/src/dependencies/time/DS1307RTC.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* DS1307RTC.h - library for DS1307 RTC
|
||||||
|
* This library is intended to be uses with Arduino Time library functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DS1307RTC_h
|
||||||
|
#define DS1307RTC_h
|
||||||
|
|
||||||
|
#include "TimeLib.h"
|
||||||
|
|
||||||
|
// library interface description
|
||||||
|
class DS1307RTC
|
||||||
|
{
|
||||||
|
// user-accessible "public" interface
|
||||||
|
public:
|
||||||
|
DS1307RTC();
|
||||||
|
static time_t get();
|
||||||
|
static bool set(time_t t);
|
||||||
|
static bool read(tmElements_t &tm);
|
||||||
|
static bool write(tmElements_t &tm);
|
||||||
|
static bool chipPresent() { return exists; }
|
||||||
|
static unsigned char isRunning();
|
||||||
|
static void setCalibration(char calValue);
|
||||||
|
static char getCalibration();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool exists;
|
||||||
|
static uint8_t dec2bcd(uint8_t num);
|
||||||
|
static uint8_t bcd2dec(uint8_t num);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef RTC
|
||||||
|
#undef RTC // workaround for Arduino Due, which defines "RTC"...
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern DS1307RTC RTC;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
|||||||
Readme file for Arduino Time Library
|
Readme file for Arduino Time Library
|
||||||
|
|
||||||
|
! MODIFIED DISTRIBUTION FOR WLED
|
||||||
|
All timekeeping functions are removed, only conversion functions used.
|
||||||
|
Please see https://github.com/PaulStoffregen/Time for the full, original library
|
||||||
|
|
||||||
Time is a library that provides timekeeping functionality for Arduino.
|
Time is a library that provides timekeeping functionality for Arduino.
|
||||||
|
|
||||||
The code is derived from the Playground DateTime library but is updated
|
The code is derived from the Playground DateTime library but is updated
|
||||||
@ -14,26 +18,10 @@ for time synchronization.
|
|||||||
|
|
||||||
The functions available in the library include:
|
The functions available in the library include:
|
||||||
|
|
||||||
hour(); // the hour now (0-23)
|
The time and date functions take a parameter for the time. This prevents
|
||||||
minute(); // the minute now (0-59)
|
|
||||||
second(); // the second now (0-59)
|
|
||||||
day(); // the day now (1-31)
|
|
||||||
weekday(); // day of the week (1-7), Sunday is day 1
|
|
||||||
month(); // the month now (1-12)
|
|
||||||
year(); // the full four digit year: (2009, 2010 etc)
|
|
||||||
|
|
||||||
there are also functions to return the hour in 12 hour format
|
|
||||||
hourFormat12(); // the hour now in 12 hour format
|
|
||||||
isAM(); // returns true if time now is AM
|
|
||||||
isPM(); // returns true if time now is PM
|
|
||||||
|
|
||||||
now(); // returns the current time as seconds since Jan 1 1970
|
|
||||||
|
|
||||||
The time and date functions can take an optional parameter for the time. This prevents
|
|
||||||
errors if the time rolls over between elements. For example, if a new minute begins
|
errors if the time rolls over between elements. For example, if a new minute begins
|
||||||
between getting the minute and second, the values will be inconsistent. Using the
|
between getting the minute and second, the values will be inconsistent. Using the
|
||||||
following functions eliminates this probglem
|
following functions eliminates this problem
|
||||||
time_t t = now(); // store the current time in time variable t
|
|
||||||
hour(t); // returns the hour for the given time t
|
hour(t); // returns the hour for the given time t
|
||||||
minute(t); // returns the minute for the given time t
|
minute(t); // returns the minute for the given time t
|
||||||
second(t); // returns the second for the given time t
|
second(t); // returns the second for the given time t
|
||||||
@ -43,25 +31,6 @@ following functions eliminates this probglem
|
|||||||
year(t); // the year for the given time t
|
year(t); // the year for the given time t
|
||||||
|
|
||||||
|
|
||||||
Functions for managing the timer services are:
|
|
||||||
|
|
||||||
setTime(t); // set the system time to the give time t
|
|
||||||
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr
|
|
||||||
// (2010 or 10 sets year to 2010)
|
|
||||||
adjustTime(adjustment); // adjust system time by adding the adjustment value
|
|
||||||
timeStatus(); // indicates if time has been set and recently synchronized
|
|
||||||
// returns one of the following enumerations:
|
|
||||||
timeNotSet // the time has never been set, the clock started at Jan 1 1970
|
|
||||||
timeNeedsSync // the time had been set but a sync attempt did not succeed
|
|
||||||
timeSet // the time is set and is synced
|
|
||||||
|
|
||||||
Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but
|
|
||||||
the returned time may have drifted if the status is timeNeedsSync.
|
|
||||||
|
|
||||||
setSyncProvider(getTimeFunction); // set the external time provider
|
|
||||||
setSyncInterval(interval); // set the number of seconds between re-sync
|
|
||||||
|
|
||||||
|
|
||||||
There are many convenience macros in the time.h file for time constants and conversion
|
There are many convenience macros in the time.h file for time constants and conversion
|
||||||
of time units.
|
of time units.
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
examples, add error checking and messages to RTC examples,
|
examples, add error checking and messages to RTC examples,
|
||||||
add examples to DS1307RTC library.
|
add examples to DS1307RTC library.
|
||||||
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
|
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
|
||||||
|
2.0 25 May 2021 - removed timing code, only used for conversion between unix and time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if ARDUINO >= 100
|
#if ARDUINO >= 100
|
||||||
@ -37,7 +38,6 @@
|
|||||||
|
|
||||||
static tmElements_t tm; // a cache of time elements
|
static tmElements_t tm; // a cache of time elements
|
||||||
static time_t cacheTime; // the time the cache was updated
|
static time_t cacheTime; // the time the cache was updated
|
||||||
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
|
|
||||||
|
|
||||||
void refreshCache(time_t t) {
|
void refreshCache(time_t t) {
|
||||||
if (t != cacheTime) {
|
if (t != cacheTime) {
|
||||||
@ -46,19 +46,11 @@ void refreshCache(time_t t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hour() { // the hour now
|
|
||||||
return hour(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int hour(time_t t) { // the hour for the given time
|
int hour(time_t t) { // the hour for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Hour;
|
return tm.Hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hourFormat12() { // the hour now in 12 hour format
|
|
||||||
return hourFormat12(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
if( tm.Hour == 0 )
|
if( tm.Hour == 0 )
|
||||||
@ -69,71 +61,39 @@ int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
|
|||||||
return tm.Hour ;
|
return tm.Hour ;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isAM() { // returns true if time now is AM
|
|
||||||
return !isPM(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t isAM(time_t t) { // returns true if given time is AM
|
uint8_t isAM(time_t t) { // returns true if given time is AM
|
||||||
return !isPM(t);
|
return !isPM(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t isPM() { // returns true if PM
|
|
||||||
return isPM(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t isPM(time_t t) { // returns true if PM
|
uint8_t isPM(time_t t) { // returns true if PM
|
||||||
return (hour(t) >= 12);
|
return (hour(t) >= 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
int minute() {
|
|
||||||
return minute(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int minute(time_t t) { // the minute for the given time
|
int minute(time_t t) { // the minute for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Minute;
|
return tm.Minute;
|
||||||
}
|
}
|
||||||
|
|
||||||
int second() {
|
|
||||||
return second(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int second(time_t t) { // the second for the given time
|
int second(time_t t) { // the second for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Second;
|
return tm.Second;
|
||||||
}
|
}
|
||||||
|
|
||||||
int day(){
|
|
||||||
return(day(now()));
|
|
||||||
}
|
|
||||||
|
|
||||||
int day(time_t t) { // the day for the given time (0-6)
|
int day(time_t t) { // the day for the given time (0-6)
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Day;
|
return tm.Day;
|
||||||
}
|
}
|
||||||
|
|
||||||
int weekday() { // Sunday is day 1
|
|
||||||
return weekday(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int weekday(time_t t) {
|
int weekday(time_t t) {
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Wday;
|
return tm.Wday;
|
||||||
}
|
}
|
||||||
|
|
||||||
int month(){
|
|
||||||
return month(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int month(time_t t) { // the month for the given time
|
int month(time_t t) { // the month for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tm.Month;
|
return tm.Month;
|
||||||
}
|
}
|
||||||
|
|
||||||
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
|
|
||||||
return year(now());
|
|
||||||
}
|
|
||||||
|
|
||||||
int year(time_t t) { // the year for the given time
|
int year(time_t t) { // the year for the given time
|
||||||
refreshCache(t);
|
refreshCache(t);
|
||||||
return tmYearToCalendar(tm.Year);
|
return tmYearToCalendar(tm.Year);
|
||||||
@ -231,57 +191,6 @@ time_t makeTime(tmElements_t &tm){
|
|||||||
seconds+= tm.Second;
|
seconds+= tm.Second;
|
||||||
return (time_t)seconds;
|
return (time_t)seconds;
|
||||||
}
|
}
|
||||||
/*=====================================================*/
|
|
||||||
/* Low level system time functions */
|
|
||||||
|
|
||||||
static uint32_t sysTime = 0;
|
|
||||||
static uint32_t prevMillis = 0;
|
|
||||||
static uint32_t nextSyncTime = 0;
|
|
||||||
static timeStatus_t Status = timeNotSet;
|
|
||||||
|
|
||||||
getExternalTime getTimePtr; // pointer to external sync function
|
|
||||||
//setExternalTime setTimePtr; // not used in this version
|
|
||||||
|
|
||||||
#ifdef TIME_DRIFT_INFO // define this to get drift data
|
|
||||||
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
time_t now() {
|
|
||||||
// calculate number of seconds passed since last call to now()
|
|
||||||
while (millis() - prevMillis >= 1000) {
|
|
||||||
// millis() and prevMillis are both unsigned ints thus the subtraction will always be the absolute value of the difference
|
|
||||||
sysTime++;
|
|
||||||
prevMillis += 1000;
|
|
||||||
#ifdef TIME_DRIFT_INFO
|
|
||||||
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (nextSyncTime <= sysTime) {
|
|
||||||
if (getTimePtr != 0) {
|
|
||||||
time_t t = getTimePtr();
|
|
||||||
if (t != 0) {
|
|
||||||
setTime(t);
|
|
||||||
} else {
|
|
||||||
nextSyncTime = sysTime + syncInterval;
|
|
||||||
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (time_t)sysTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime(time_t t) {
|
|
||||||
#ifdef TIME_DRIFT_INFO
|
|
||||||
if(sysUnsyncedTime == 0)
|
|
||||||
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sysTime = (uint32_t)t;
|
|
||||||
nextSyncTime = (uint32_t)t + syncInterval;
|
|
||||||
Status = timeSet;
|
|
||||||
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||||
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
||||||
@ -297,29 +206,4 @@ time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
|||||||
tm.Minute = min;
|
tm.Minute = min;
|
||||||
tm.Second = sec;
|
tm.Second = sec;
|
||||||
return makeTime(tm);
|
return makeTime(tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
|
||||||
setTime(getUnixTime(hr,min,sec,dy,mnth,yr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void adjustTime(long adjustment) {
|
|
||||||
sysTime += adjustment;
|
|
||||||
}
|
|
||||||
|
|
||||||
// indicates if time has been set and recently synchronized
|
|
||||||
timeStatus_t timeStatus() {
|
|
||||||
now(); // required to actually update the status
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSyncProvider( getExternalTime getTimeFunction){
|
|
||||||
getTimePtr = getTimeFunction;
|
|
||||||
nextSyncTime = sysTime;
|
|
||||||
now(); // this will sync the clock
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
|
|
||||||
syncInterval = (uint32_t)interval;
|
|
||||||
nextSyncTime = sysTime + syncInterval;
|
|
||||||
}
|
|
@ -31,8 +31,6 @@ typedef unsigned long time_t;
|
|||||||
// but at least this hack lets us define C++ functions as intended. Hopefully
|
// but at least this hack lets us define C++ functions as intended. Hopefully
|
||||||
// nothing too terrible will result from overriding the C library header?!
|
// nothing too terrible will result from overriding the C library header?!
|
||||||
extern "C++" {
|
extern "C++" {
|
||||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
|
||||||
} timeStatus_t ;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
||||||
@ -95,33 +93,19 @@ typedef time_t(*getExternalTime)();
|
|||||||
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
|
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
/* time and date functions */
|
/* time and date functions */
|
||||||
int hour(); // the hour now
|
|
||||||
int hour(time_t t); // the hour for the given time
|
int hour(time_t t); // the hour for the given time
|
||||||
int hourFormat12(); // the hour now in 12 hour format
|
|
||||||
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
||||||
uint8_t isAM(); // returns true if time now is AM
|
|
||||||
uint8_t isAM(time_t t); // returns true the given time is AM
|
uint8_t isAM(time_t t); // returns true the given time is AM
|
||||||
uint8_t isPM(); // returns true if time now is PM
|
|
||||||
uint8_t isPM(time_t t); // returns true the given time is PM
|
uint8_t isPM(time_t t); // returns true the given time is PM
|
||||||
int minute(); // the minute now
|
|
||||||
int minute(time_t t); // the minute for the given time
|
int minute(time_t t); // the minute for the given time
|
||||||
int second(); // the second now
|
|
||||||
int second(time_t t); // the second for the given time
|
int second(time_t t); // the second for the given time
|
||||||
int day(); // the day now
|
|
||||||
int day(time_t t); // the day for the given time
|
int day(time_t t); // the day for the given time
|
||||||
int weekday(); // the weekday now (Sunday is day 1)
|
|
||||||
int weekday(time_t t); // the weekday for the given time
|
int weekday(time_t t); // the weekday for the given time
|
||||||
int month(); // the month now (Jan is month 1)
|
|
||||||
int month(time_t t); // the month for the given time
|
int month(time_t t); // the month for the given time
|
||||||
int year(); // the full four digit year: (2009, 2010 etc)
|
|
||||||
int year(time_t t); // the year for the given time
|
int year(time_t t); // the year for the given time
|
||||||
|
|
||||||
time_t now(); // return the current time as seconds since Jan 1 1970
|
|
||||||
void setTime(time_t t);
|
|
||||||
void setTime(int hr,int min,int sec,int day, int month, int yr);
|
|
||||||
time_t getUnixTime(int hr,int min,int sec,int day, int month, int yr); //added by Aircoookie to get epoch time
|
time_t getUnixTime(int hr,int min,int sec,int day, int month, int yr); //added by Aircoookie to get epoch time
|
||||||
void adjustTime(long adjustment);
|
|
||||||
|
|
||||||
/* date strings */
|
/* date strings */
|
||||||
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
||||||
@ -129,13 +113,8 @@ char* monthStr(uint8_t month);
|
|||||||
char* dayStr(uint8_t day);
|
char* dayStr(uint8_t day);
|
||||||
char* monthShortStr(uint8_t month);
|
char* monthShortStr(uint8_t month);
|
||||||
char* dayShortStr(uint8_t day);
|
char* dayShortStr(uint8_t day);
|
||||||
|
|
||||||
/* time sync functions */
|
|
||||||
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
|
||||||
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
|
|
||||||
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
|
||||||
|
|
||||||
/* low level functions to convert to and from system time */
|
/* low level functions to convert to and from system time */
|
||||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||||
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
||||||
|
|
||||||
|
161
wled00/src/dependencies/toki/Toki.h
Normal file
161
wled00/src/dependencies/toki/Toki.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
Toki.h - Minimal millisecond accurate timekeeping.
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define YEARS_70 2208988800UL
|
||||||
|
|
||||||
|
#define TOKI_NO_MS_ACCURACY 1000
|
||||||
|
|
||||||
|
//Time source. Sub-100 is second accuracy, higher ms accuracy. Higher value generally means more accurate
|
||||||
|
#define TOKI_TS_NONE 0 //unsynced (e.g. just after boot)
|
||||||
|
#define TOKI_TS_UDP 5 //synced via UDP from an instance whose time source is unsynced
|
||||||
|
#define TOKI_TS_BAD 10 //synced from a time source less than about +- 2s accurate
|
||||||
|
#define TOKI_TS_UDP_SEC 20 //synced via UDP from an instance whose time source is set from RTC/JSON
|
||||||
|
#define TOKI_TS_SEC 40 //general second-accurate time source
|
||||||
|
#define TOKI_TS_RTC 60 //second-accurate real time clock
|
||||||
|
#define TOKI_TS_JSON 70 //synced second-accurate from a client via JSON-API
|
||||||
|
|
||||||
|
#define TOKI_TS_UDP_NTP 110 //synced via UDP from an instance whose time source is NTP
|
||||||
|
#define TOKI_TS_MS 120 //general better-than-second accuracy time source
|
||||||
|
#define TOKI_TS_NTP 150 //NTP time, simple round trip estimation. Depending on network, mostly +- 50ms accurate
|
||||||
|
#define TOKI_TS_NTP_P 170 //NTP time with multi-step sync, higher accuracy. Not implemented in WLED
|
||||||
|
|
||||||
|
class Toki {
|
||||||
|
typedef enum {
|
||||||
|
inactive, marked, active
|
||||||
|
} TickT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
uint32_t sec;
|
||||||
|
uint16_t ms;
|
||||||
|
} Time;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t fullSecondMillis = 0;
|
||||||
|
uint32_t unix = 0;
|
||||||
|
TickT tick = TickT::inactive;
|
||||||
|
uint8_t timeSrc = TOKI_TS_NONE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setTime(Time t, uint8_t timeSource = TOKI_TS_MS) {
|
||||||
|
fullSecondMillis = millis() - t.ms;
|
||||||
|
unix = t.sec;
|
||||||
|
timeSrc = timeSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTime(uint32_t sec, uint16_t ms=TOKI_NO_MS_ACCURACY, uint8_t timeSource = TOKI_TS_MS) {
|
||||||
|
if (ms >= TOKI_NO_MS_ACCURACY) {
|
||||||
|
ms = millisecond(); //just keep current ms if not provided
|
||||||
|
if (timeSource > 99) timeSource = TOKI_TS_SEC; //lies
|
||||||
|
}
|
||||||
|
Time t = {sec, ms};
|
||||||
|
setTime(t, timeSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
Time fromNTP(byte *timestamp) { //ntp timestamp is 8 bytes, 4 bytes second and 4 bytes sub-second fraction
|
||||||
|
unsigned long highWord = word(timestamp[0], timestamp[1]);
|
||||||
|
unsigned long lowWord = word(timestamp[2], timestamp[3]);
|
||||||
|
|
||||||
|
unsigned long unix = highWord << 16 | lowWord;
|
||||||
|
if (!unix) return {0,0};
|
||||||
|
unix -= YEARS_70; //NTP begins 1900, Unix 1970
|
||||||
|
|
||||||
|
unsigned long frac = word(timestamp[4], timestamp[5]); //65536ths of a second
|
||||||
|
frac = (frac*1000) >> 16; //convert to ms
|
||||||
|
return {unix, (uint16_t)frac};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t millisecond() {
|
||||||
|
uint32_t ms = millis() - fullSecondMillis;
|
||||||
|
while (ms > 999) {
|
||||||
|
ms -= 1000;
|
||||||
|
fullSecondMillis += 1000;
|
||||||
|
unix++;
|
||||||
|
if (tick == TickT::inactive) tick = TickT::marked; //marked, will be active on next loop
|
||||||
|
}
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t second() {
|
||||||
|
millisecond();
|
||||||
|
return unix;
|
||||||
|
}
|
||||||
|
|
||||||
|
//gets the absolute difference between two timestamps in milliseconds
|
||||||
|
uint32_t msDifference(const Time &t0, const Time &t1) {
|
||||||
|
bool t1BiggerSec = (t1.sec > t0.sec);
|
||||||
|
uint32_t secDiff = (t1BiggerSec) ? t1.sec - t0.sec : t0.sec - t1.sec;
|
||||||
|
uint32_t t0ms = t0.ms, t1ms = t1.ms;
|
||||||
|
if (t1BiggerSec) t1ms += secDiff*1000;
|
||||||
|
else t0ms += secDiff*1000;
|
||||||
|
uint32_t msDiff = (t1ms > t0ms) ? t1ms - t0ms : t0ms - t1ms;
|
||||||
|
return msDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return true if t1 is later than t0
|
||||||
|
bool isLater(const Time &t0, const Time &t1) {
|
||||||
|
if (t1.sec > t0.sec) return true;
|
||||||
|
if (t1.sec < t0.sec) return false;
|
||||||
|
if (t1.ms > t0.ms) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adjust(Time&t, int32_t offset) {
|
||||||
|
int32_t secs = offset /1000;
|
||||||
|
int32_t ms = offset - secs*1000;
|
||||||
|
t.sec += secs;
|
||||||
|
int32_t nms = t.ms + ms;
|
||||||
|
if (nms > 1000) {nms -= 1000; t.sec++;}
|
||||||
|
if (nms < 0) {nms += 1000; t.sec--;}
|
||||||
|
t.ms = nms;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time getTime() {
|
||||||
|
Time t;
|
||||||
|
t.ms = millisecond();
|
||||||
|
t.sec = unix;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getTimeSource() {
|
||||||
|
return timeSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTick() {
|
||||||
|
if (tick == TickT::marked) tick = TickT::active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetTick() {
|
||||||
|
if (tick == TickT::active) tick = TickT::inactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTick() {
|
||||||
|
return (tick == TickT::active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTime(const Time& t) {
|
||||||
|
Serial.printf_P(PSTR("%u,%03u\n"),t.sec,t.ms);
|
||||||
|
}
|
||||||
|
};
|
@ -4,8 +4,9 @@
|
|||||||
* UDP sync notifier / Realtime / Hyperion / TPM2.NET
|
* UDP sync notifier / Realtime / Hyperion / TPM2.NET
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WLEDPACKETSIZE 29
|
#define WLEDPACKETSIZE 36
|
||||||
#define UDP_IN_MAXSIZE 1472
|
#define UDP_IN_MAXSIZE 1472
|
||||||
|
#define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times
|
||||||
|
|
||||||
void notify(byte callMode, bool followUp)
|
void notify(byte callMode, bool followUp)
|
||||||
{
|
{
|
||||||
@ -37,8 +38,8 @@ void notify(byte callMode, bool followUp)
|
|||||||
//compatibilityVersionByte:
|
//compatibilityVersionByte:
|
||||||
//0: old 1: supports white 2: supports secondary color
|
//0: old 1: supports white 2: supports secondary color
|
||||||
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
|
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
|
||||||
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color
|
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
|
||||||
udpOut[11] = 7;
|
udpOut[11] = 8;
|
||||||
udpOut[12] = colSec[0];
|
udpOut[12] = colSec[0];
|
||||||
udpOut[13] = colSec[1];
|
udpOut[13] = colSec[1];
|
||||||
udpOut[14] = colSec[2];
|
udpOut[14] = colSec[2];
|
||||||
@ -59,6 +60,18 @@ void notify(byte callMode, bool followUp)
|
|||||||
udpOut[26] = (t >> 16) & 0xFF;
|
udpOut[26] = (t >> 16) & 0xFF;
|
||||||
udpOut[27] = (t >> 8) & 0xFF;
|
udpOut[27] = (t >> 8) & 0xFF;
|
||||||
udpOut[28] = (t >> 0) & 0xFF;
|
udpOut[28] = (t >> 0) & 0xFF;
|
||||||
|
|
||||||
|
//sync system time
|
||||||
|
udpOut[29] = toki.getTimeSource();
|
||||||
|
Toki::Time tm = toki.getTime();
|
||||||
|
uint32_t unix = tm.sec;
|
||||||
|
udpOut[30] = (unix >> 24) & 0xFF;
|
||||||
|
udpOut[31] = (unix >> 16) & 0xFF;
|
||||||
|
udpOut[32] = (unix >> 8) & 0xFF;
|
||||||
|
udpOut[33] = (unix >> 0) & 0xFF;
|
||||||
|
uint16_t ms = tm.ms;
|
||||||
|
udpOut[34] = (ms >> 8) & 0xFF;
|
||||||
|
udpOut[35] = (ms >> 0) & 0xFF;
|
||||||
|
|
||||||
IPAddress broadcastIp;
|
IPAddress broadcastIp;
|
||||||
broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP());
|
broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP());
|
||||||
@ -208,6 +221,9 @@ void handleNotifications()
|
|||||||
//ignore notification if received within a second after sending a notification ourselves
|
//ignore notification if received within a second after sending a notification ourselves
|
||||||
if (millis() - notificationSentTime < 1000) return;
|
if (millis() - notificationSentTime < 1000) return;
|
||||||
if (udpIn[1] > 199) return; //do not receive custom versions
|
if (udpIn[1] > 199) return; //do not receive custom versions
|
||||||
|
|
||||||
|
//compatibilityVersionByte:
|
||||||
|
byte version = udpIn[11];
|
||||||
|
|
||||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||||
//apply colors from notification
|
//apply colors from notification
|
||||||
@ -216,40 +232,66 @@ void handleNotifications()
|
|||||||
col[0] = udpIn[3];
|
col[0] = udpIn[3];
|
||||||
col[1] = udpIn[4];
|
col[1] = udpIn[4];
|
||||||
col[2] = udpIn[5];
|
col[2] = udpIn[5];
|
||||||
if (udpIn[11] > 0) //sending module's white val is intended
|
if (version > 0) //sending module's white val is intended
|
||||||
{
|
{
|
||||||
col[3] = udpIn[10];
|
col[3] = udpIn[10];
|
||||||
if (udpIn[11] > 1)
|
if (version > 1)
|
||||||
{
|
{
|
||||||
colSec[0] = udpIn[12];
|
colSec[0] = udpIn[12];
|
||||||
colSec[1] = udpIn[13];
|
colSec[1] = udpIn[13];
|
||||||
colSec[2] = udpIn[14];
|
colSec[2] = udpIn[14];
|
||||||
colSec[3] = udpIn[15];
|
colSec[3] = udpIn[15];
|
||||||
}
|
}
|
||||||
if (udpIn[11] > 5)
|
if (version > 6)
|
||||||
{
|
|
||||||
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
|
|
||||||
t += 2;
|
|
||||||
t -= millis();
|
|
||||||
strip.timebase = t;
|
|
||||||
}
|
|
||||||
if (udpIn[11] > 6)
|
|
||||||
{
|
{
|
||||||
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool timebaseUpdated = false;
|
||||||
//apply effects from notification
|
//apply effects from notification
|
||||||
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
|
if (version < 200 && (receiveNotificationEffects || !someSel))
|
||||||
{
|
{
|
||||||
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
|
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
|
||||||
effectSpeed = udpIn[9];
|
effectSpeed = udpIn[9];
|
||||||
if (udpIn[11] > 2) effectIntensity = udpIn[16];
|
if (version > 2) effectIntensity = udpIn[16];
|
||||||
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
|
if (version > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
|
||||||
|
if (version > 5)
|
||||||
|
{
|
||||||
|
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
|
||||||
|
t += PRESUMED_NETWORK_DELAY; //adjust trivially for network delay
|
||||||
|
t -= millis();
|
||||||
|
strip.timebase = t;
|
||||||
|
timebaseUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//adjust system time, but only if sender is more accurate than self
|
||||||
|
if (version > 7)
|
||||||
|
{
|
||||||
|
Toki::Time tm;
|
||||||
|
tm.sec = (udpIn[30] << 24) | (udpIn[31] << 16) | (udpIn[32] << 8) | (udpIn[33]);
|
||||||
|
tm.ms = (udpIn[34] << 8) | (udpIn[35]);
|
||||||
|
if (udpIn[29] > toki.getTimeSource()) { //if sender's time source is more accurate
|
||||||
|
toki.adjust(tm, PRESUMED_NETWORK_DELAY); //adjust trivially for network delay
|
||||||
|
uint8_t ts = TOKI_TS_UDP;
|
||||||
|
if (udpIn[29] > 99) ts = TOKI_TS_UDP_NTP;
|
||||||
|
else if (udpIn[29] >= TOKI_TS_SEC) ts = TOKI_TS_UDP_SEC;
|
||||||
|
toki.setTime(tm, ts);
|
||||||
|
} else if (timebaseUpdated && toki.getTimeSource() > 99) { //if we both have good times, get a more accurate timebase
|
||||||
|
Toki::Time myTime = toki.getTime();
|
||||||
|
uint32_t diff = toki.msDifference(tm, myTime);
|
||||||
|
strip.timebase -= PRESUMED_NETWORK_DELAY; //no need to presume, use difference between NTP times at send and receive points
|
||||||
|
if (toki.isLater(tm, myTime)) {
|
||||||
|
strip.timebase += diff;
|
||||||
|
} else {
|
||||||
|
strip.timebase -= diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (udpIn[11] > 3)
|
if (version > 3)
|
||||||
{
|
{
|
||||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
#include "../usermods/Temperature/usermod_temperature.h"
|
#include "../usermods/Temperature/usermod_temperature.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||||
|
#include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
//#include "usermod_v2_empty.h"
|
//#include "usermod_v2_empty.h"
|
||||||
|
|
||||||
#ifdef USERMOD_BUZZER
|
#ifdef USERMOD_BUZZER
|
||||||
@ -61,6 +65,14 @@
|
|||||||
#include "../usermods/multi_relay/usermod_multi_relay.h"
|
#include "../usermods/multi_relay/usermod_multi_relay.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_RTC
|
||||||
|
#include "../usermods/RTC/usermod_rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_ELEKSTUBE_IPS
|
||||||
|
#include "../usermods/EleksTube_IPS/usermod_elekstube_ips.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void registerUsermods()
|
void registerUsermods()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -69,17 +81,21 @@ void registerUsermods()
|
|||||||
* \/ \/ \/
|
* \/ \/ \/
|
||||||
*/
|
*/
|
||||||
//usermods.add(new MyExampleUsermod());
|
//usermods.add(new MyExampleUsermod());
|
||||||
|
|
||||||
#ifdef USERMOD_DALLASTEMPERATURE
|
#ifdef USERMOD_DALLASTEMPERATURE
|
||||||
usermods.add(new UsermodTemperature());
|
usermods.add(new UsermodTemperature());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||||
|
usermods.add(new Usermod_SN_Photoresistor());
|
||||||
|
#endif
|
||||||
|
|
||||||
//usermods.add(new UsermodRenameMe());
|
//usermods.add(new UsermodRenameMe());
|
||||||
|
|
||||||
#ifdef USERMOD_BUZZER
|
#ifdef USERMOD_BUZZER
|
||||||
usermods.add(new BuzzerUsermod());
|
usermods.add(new BuzzerUsermod());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_BME280
|
#ifdef USERMOD_BME280
|
||||||
usermods.add(new UsermodBME280());
|
usermods.add(new UsermodBME280());
|
||||||
#endif
|
#endif
|
||||||
@ -118,4 +134,12 @@ void registerUsermods()
|
|||||||
#ifdef USERMOD_MULTI_RELAY
|
#ifdef USERMOD_MULTI_RELAY
|
||||||
usermods.add(new MultiRelay());
|
usermods.add(new MultiRelay());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_RTC
|
||||||
|
usermods.add(new RTCUsermod());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_ELEKSTUBE_IPS
|
||||||
|
usermods.add(new ElekstubeIPSUsermod());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
1404
wled00/wled.cpp
1404
wled00/wled.cpp
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2106151
|
#define VERSION 2106152
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -90,6 +90,7 @@
|
|||||||
#include <SPIFFSEditor.h>
|
#include <SPIFFSEditor.h>
|
||||||
#include "src/dependencies/time/TimeLib.h"
|
#include "src/dependencies/time/TimeLib.h"
|
||||||
#include "src/dependencies/timezone/Timezone.h"
|
#include "src/dependencies/timezone/Timezone.h"
|
||||||
|
#include "src/dependencies/toki/Toki.h"
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_ALEXA
|
#ifndef WLED_DISABLE_ALEXA
|
||||||
#define ESPALEXA_ASYNC
|
#define ESPALEXA_ASYNC
|
||||||
@ -118,7 +119,7 @@
|
|||||||
// The following is a construct to enable code to compile without it.
|
// The following is a construct to enable code to compile without it.
|
||||||
// There is a code thet will still not use PSRAM though:
|
// There is a code thet will still not use PSRAM though:
|
||||||
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||||
struct PSRAM_Allocator {
|
struct PSRAM_Allocator {
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size) {
|
||||||
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
||||||
@ -244,7 +245,12 @@ WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access poi
|
|||||||
WLED_GLOBAL IPAddress staticIP _INIT_N((( 0, 0, 0, 0))); // static IP of ESP
|
WLED_GLOBAL IPAddress staticIP _INIT_N((( 0, 0, 0, 0))); // static IP of ESP
|
||||||
WLED_GLOBAL IPAddress staticGateway _INIT_N((( 0, 0, 0, 0))); // gateway (router) IP
|
WLED_GLOBAL IPAddress staticGateway _INIT_N((( 0, 0, 0, 0))); // gateway (router) IP
|
||||||
WLED_GLOBAL IPAddress staticSubnet _INIT_N(((255, 255, 255, 0))); // most common subnet in home networks
|
WLED_GLOBAL IPAddress staticSubnet _INIT_N(((255, 255, 255, 0))); // most common subnet in home networks
|
||||||
WLED_GLOBAL bool noWifiSleep _INIT(false); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
||||||
|
#else
|
||||||
|
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
||||||
WLED_GLOBAL int ethernetType _INIT(WLED_ETH_DEFAULT); // ethernet board type
|
WLED_GLOBAL int ethernetType _INIT(WLED_ETH_DEFAULT); // ethernet board type
|
||||||
@ -350,7 +356,7 @@ WLED_GLOBAL bool useAMPM _INIT(false); // 12h/24h clock format
|
|||||||
WLED_GLOBAL byte currentTimezone _INIT(0); // Timezone ID. Refer to timezones array in wled10_ntp.ino
|
WLED_GLOBAL byte currentTimezone _INIT(0); // Timezone ID. Refer to timezones array in wled10_ntp.ino
|
||||||
WLED_GLOBAL int utcOffsetSecs _INIT(0); // Seconds to offset from UTC before timzone calculation
|
WLED_GLOBAL int utcOffsetSecs _INIT(0); // Seconds to offset from UTC before timzone calculation
|
||||||
|
|
||||||
WLED_GLOBAL byte overlayDefault _INIT(0); // 0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
|
WLED_GLOBAL byte overlayDefault _INIT(0); // 0: no overlay 1: analog clock 2: single-digit clock 3: cronixie
|
||||||
WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(ledCount - 1); // boundaries of overlay mode
|
WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(ledCount - 1); // boundaries of overlay mode
|
||||||
|
|
||||||
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
|
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
|
||||||
@ -472,13 +478,9 @@ WLED_GLOBAL bool hueStoreAllowed _INIT(false), hueNewKey _INIT(false);
|
|||||||
|
|
||||||
// overlays
|
// overlays
|
||||||
WLED_GLOBAL byte overlayCurrent _INIT(overlayDefault);
|
WLED_GLOBAL byte overlayCurrent _INIT(overlayDefault);
|
||||||
WLED_GLOBAL byte overlaySpeed _INIT(200);
|
|
||||||
WLED_GLOBAL unsigned long overlayRefreshMs _INIT(200);
|
|
||||||
WLED_GLOBAL unsigned long overlayRefreshedTime;
|
|
||||||
|
|
||||||
// cronixie
|
// cronixie
|
||||||
WLED_GLOBAL byte dP[] _INIT_N(({ 0, 0, 0, 0, 0, 0 }));
|
WLED_GLOBAL byte dP[] _INIT_N(({ 255, 255, 255, 255, 255, 255 }));
|
||||||
WLED_GLOBAL bool cronixieInit _INIT(false);
|
|
||||||
|
|
||||||
// countdown
|
// countdown
|
||||||
WLED_GLOBAL unsigned long countdownTime _INIT(1514764800L);
|
WLED_GLOBAL unsigned long countdownTime _INIT(1514764800L);
|
||||||
@ -541,6 +543,7 @@ WLED_GLOBAL float longitude _INIT(0.0);
|
|||||||
WLED_GLOBAL float latitude _INIT(0.0);
|
WLED_GLOBAL float latitude _INIT(0.0);
|
||||||
WLED_GLOBAL time_t sunrise _INIT(0);
|
WLED_GLOBAL time_t sunrise _INIT(0);
|
||||||
WLED_GLOBAL time_t sunset _INIT(0);
|
WLED_GLOBAL time_t sunset _INIT(0);
|
||||||
|
WLED_GLOBAL Toki toki _INIT(Toki());
|
||||||
|
|
||||||
// Temp buffer
|
// Temp buffer
|
||||||
WLED_GLOBAL char* obuf;
|
WLED_GLOBAL char* obuf;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <Arduino.h> //PI constant
|
#include <Arduino.h> //PI constant
|
||||||
|
|
||||||
|
//#define WLED_DEBUG_MATH
|
||||||
|
|
||||||
#define modd(x, y) ((x) - (int)((x) / (y)) * (y))
|
#define modd(x, y) ((x) - (int)((x) / (y)) * (y))
|
||||||
|
|
||||||
float cos_t(float x)
|
float cos_t(float x)
|
||||||
@ -24,38 +26,58 @@ float cos_t(float x)
|
|||||||
}
|
}
|
||||||
float xx = x * x;
|
float xx = x * x;
|
||||||
|
|
||||||
return sign * (1 - ((xx) / (2)) + ((xx * xx) / (24)) - ((xx * xx * xx) / (720)) + ((xx * xx * xx * xx) / (40320)) - ((xx * xx * xx * xx * xx) / (3628800)) + ((xx * xx * xx * xx * xx * xx) / (479001600)));
|
float res = sign * (1 - ((xx) / (2)) + ((xx * xx) / (24)) - ((xx * xx * xx) / (720)) + ((xx * xx * xx * xx) / (40320)) - ((xx * xx * xx * xx * xx) / (3628800)) + ((xx * xx * xx * xx * xx * xx) / (479001600)));
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("cos: %f,%f\n",res,cos(x));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
float sin_t(float x) {
|
float sin_t(float x) {
|
||||||
return cos_t(HALF_PI - x);
|
float res = cos_t(HALF_PI - x);
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("sin: %f,%f\n",res,sin(x));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
float tan_t(float x) {
|
float tan_t(float x) {
|
||||||
float c = cos_t(x);
|
float c = cos_t(x);
|
||||||
if (c==0.0) return 0;
|
if (c==0.0) return 0;
|
||||||
return sin_t(x) / c;
|
float res = sin_t(x) / c;
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("tan: %f,%f\n",res,tan(x));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://stackoverflow.com/questions/3380628
|
//https://stackoverflow.com/questions/3380628
|
||||||
// Absolute error <= 6.7e-5
|
// Absolute error <= 6.7e-5
|
||||||
float acos_t(float x) {
|
float acos_t(float x) {
|
||||||
float negate = float(x < 0);
|
float negate = float(x < 0);
|
||||||
x = std::abs(x);
|
float xabs = std::abs(x);
|
||||||
float ret = -0.0187293;
|
float ret = -0.0187293;
|
||||||
ret = ret * x;
|
ret = ret * xabs;
|
||||||
ret = ret + 0.0742610;
|
ret = ret + 0.0742610;
|
||||||
ret = ret * x;
|
ret = ret * xabs;
|
||||||
ret = ret - 0.2121144;
|
ret = ret - 0.2121144;
|
||||||
ret = ret * x;
|
ret = ret * xabs;
|
||||||
ret = ret + HALF_PI;
|
ret = ret + HALF_PI;
|
||||||
ret = ret * sqrt(1.0-x);
|
ret = ret * sqrt(1.0-xabs);
|
||||||
ret = ret - 2 * negate * ret;
|
ret = ret - 2 * negate * ret;
|
||||||
return negate * PI + ret;
|
float res = negate * PI + ret;
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("acos,%f,%f,%f\n",x,res,acos(x));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
float asin_t(float x) {
|
float asin_t(float x) {
|
||||||
return HALF_PI - acos_t(x);
|
float res = HALF_PI - acos_t(x);
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("asin,%f,%f,%f\n",x,res,asin(x));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -64,10 +86,35 @@ float asin_t(float x) {
|
|||||||
#define B -0.287434475393028
|
#define B -0.287434475393028
|
||||||
#define C ((HALF_PI/2) - A - B)
|
#define C ((HALF_PI/2) - A - B)
|
||||||
|
|
||||||
|
//polynominal factors for approximation between 1 and 5
|
||||||
|
#define C0 0.089494f
|
||||||
|
#define C1 0.974207f
|
||||||
|
#define C2 -0.326175f
|
||||||
|
#define C3 0.05375f
|
||||||
|
#define C4 -0.003445f
|
||||||
|
|
||||||
float atan_t(float x) {
|
float atan_t(float x) {
|
||||||
if (x>1) return atan(x);
|
bool neg = (x < 0);
|
||||||
float xx = x * x;
|
#ifdef WLED_DEBUG_MATH
|
||||||
return ((A*xx + B)*xx + C)*x;
|
float xinput = x;
|
||||||
|
#endif
|
||||||
|
x = std::abs(x);
|
||||||
|
float res;
|
||||||
|
if (x > 5.0f) { //atan(x) converges to pi/2 - (1/x) for large values
|
||||||
|
res = HALF_PI - (1.0f/x);
|
||||||
|
}
|
||||||
|
else if (x > 1.0f) { //1 < x < 5
|
||||||
|
float xx = x * x;
|
||||||
|
res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0;
|
||||||
|
} else { //this approximation is only for x <= 1
|
||||||
|
float xx = x * x;
|
||||||
|
res = ((A*xx + B)*xx + C)*x;
|
||||||
|
}
|
||||||
|
if (neg) res = -res;
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("atan,%f,%f,%f\n",xinput,res,atan(xinput));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//https://stackoverflow.com/a/42542593
|
//https://stackoverflow.com/a/42542593
|
||||||
@ -110,12 +157,19 @@ float floor_t(float x) {
|
|||||||
bool neg = x < 0;
|
bool neg = x < 0;
|
||||||
int val = x;
|
int val = x;
|
||||||
if (neg) val--;
|
if (neg) val--;
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("floor: %f,%f\n",val,floor(x));
|
||||||
|
#endif
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fmod_t(float num, float denom) {
|
float fmod_t(float num, float denom) {
|
||||||
int tquot = num / denom;
|
int tquot = num / denom;
|
||||||
return num - tquot * denom;
|
float res = num - tquot * denom;
|
||||||
|
#ifdef WLED_DEBUG_MATH
|
||||||
|
Serial.printf("fmod: %f,%f\n",res,fmod(num,denom));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -247,7 +247,10 @@ void initServer()
|
|||||||
//make API CORS compatible
|
//make API CORS compatible
|
||||||
if (request->method() == HTTP_OPTIONS)
|
if (request->method() == HTTP_OPTIONS)
|
||||||
{
|
{
|
||||||
request->send(200); return;
|
AsyncWebServerResponse *response = request->beginResponse(200);
|
||||||
|
response->addHeader(F("Access-Control-Max-Age"), F("7200"));
|
||||||
|
request->send(response);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handleSet(request, request->url())) return;
|
if(handleSet(request, request->url())) return;
|
||||||
|
@ -412,8 +412,6 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == 4)
|
if (subPage == 4)
|
||||||
{
|
{
|
||||||
//sappend('v',SET_F("BT"),buttonType);
|
|
||||||
//sappend('v',SET_F("IR"),irEnabled);
|
|
||||||
sappend('v',SET_F("UP"),udpPort);
|
sappend('v',SET_F("UP"),udpPort);
|
||||||
sappend('v',SET_F("U2"),udpPort2);
|
sappend('v',SET_F("U2"),udpPort2);
|
||||||
sappend('c',SET_F("RB"),receiveNotificationBrightness);
|
sappend('c',SET_F("RB"),receiveNotificationBrightness);
|
||||||
@ -531,9 +529,6 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('v',SET_F("A1"),macroAlexaOff);
|
sappend('v',SET_F("A1"),macroAlexaOff);
|
||||||
sappend('v',SET_F("MC"),macroCountdown);
|
sappend('v',SET_F("MC"),macroCountdown);
|
||||||
sappend('v',SET_F("MN"),macroNl);
|
sappend('v',SET_F("MN"),macroNl);
|
||||||
//sappend('v',SET_F("MP"),macroButton);
|
|
||||||
//sappend('v',SET_F("ML"),macroLongPress);
|
|
||||||
//sappend('v',SET_F("MD"),macroDoublePress);
|
|
||||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||||
oappend(SET_F("addRow("));
|
oappend(SET_F("addRow("));
|
||||||
oappend(itoa(i,tm,10)); oappend(",");
|
oappend(itoa(i,tm,10)); oappend(",");
|
||||||
|
Loading…
Reference in New Issue
Block a user