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
|
||||
|
||||
#### 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
|
||||
|
||||
- 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",
|
||||
"version": "0.12.0-b3",
|
||||
"version": "0.12.2-bl4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.12.2-bl3",
|
||||
"version": "0.12.2-bl4",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
|
@ -15,6 +15,7 @@
|
||||
default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth
|
||||
|
||||
# Single binaries (uncomment your board)
|
||||
; default_envs = elekstube_ips
|
||||
; default_envs = nodemcuv2
|
||||
; default_envs = esp01_1m_full
|
||||
; default_envs = esp07
|
||||
@ -47,7 +48,8 @@ extra_configs =
|
||||
# arduino core 2.7.0 = platformIO 2.5.0
|
||||
# ------------------------------------------------------------------------------
|
||||
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
|
||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||
@ -131,6 +133,8 @@ ldscript_4m1m = eagle.flash.4m1m.ld
|
||||
build_flags =
|
||||
-DESP8266
|
||||
-DFP_IN_IROM
|
||||
;-Wno-deprecated-declarations
|
||||
;-Wno-register
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||
; lwIP 2 - Higher Bandwidth no Features
|
||||
@ -418,3 +422,37 @@ platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_unflags = ${common.build_unflags}
|
||||
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
|
||||
- Blynk IoT
|
||||
- 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)
|
||||
- UDP realtime
|
||||
- Alexa voice control (including dimming and color)
|
||||
|
@ -44,7 +44,7 @@ starlette==0.14.2
|
||||
# via platformio
|
||||
tabulate==0.8.9
|
||||
# via platformio
|
||||
urllib3==1.26.4
|
||||
urllib3==1.26.5
|
||||
# via requests
|
||||
uvicorn==0.13.4
|
||||
# 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
|
||||
* Alternate between color1 and color2
|
||||
* 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 stateTime = SEGENV.aux1;
|
||||
uint32_t cycleTime = (255 - SEGMENT.speed)*20;
|
||||
uint32_t onTime = 0;
|
||||
uint32_t offTime = cycleTime;
|
||||
uint32_t onTime = FRAMETIME;
|
||||
if (!strobe) onTime += ((cycleTime * SEGMENT.intensity) >> 8);
|
||||
cycleTime += FRAMETIME*2;
|
||||
uint32_t it = now / cycleTime;
|
||||
uint32_t rem = now % cycleTime;
|
||||
|
||||
if (!strobe) {
|
||||
onTime = (cycleTime * SEGMENT.intensity) >> 8;
|
||||
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;
|
||||
stateTime += 20;
|
||||
SEGENV.step = it; //save previous iteration
|
||||
|
||||
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)
|
||||
{
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
|
@ -73,7 +73,7 @@
|
||||
#define SEGENV _segment_runtimes[_segment_index]
|
||||
#define SEGLEN _virtualSegmentLength
|
||||
#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))
|
||||
|
||||
// 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;
|
||||
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"
|
||||
CRGB fastled_col;
|
||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||
|
@ -46,7 +46,10 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
bri = briLast;
|
||||
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)
|
||||
{
|
||||
if (!macroAlexaOff)
|
||||
@ -57,7 +60,10 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
bri = 0;
|
||||
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)
|
||||
{
|
||||
bri = espalexaDevice->getValue();
|
||||
|
@ -160,7 +160,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
}
|
||||
CJSON(touchThreshold,hw[F("btn")][F("tt")]);
|
||||
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
|
||||
if (hw_ir_pin > -2) {
|
||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||
@ -169,7 +168,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
irPin = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
CJSON(irEnabled, hw["ir"]["type"]);
|
||||
|
||||
JsonObject relay = hw[F("relay")];
|
||||
|
@ -55,6 +55,9 @@
|
||||
#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h"
|
||||
#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h"
|
||||
#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h"
|
||||
#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h"
|
||||
#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h"
|
||||
#define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
@ -190,6 +193,9 @@
|
||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||
#define SEG_OPTION_TRANSITIONAL 7
|
||||
|
||||
//Playlist option byte
|
||||
#define PL_OPTION_SHUFFLE 0x01
|
||||
|
||||
// WLED Error modes
|
||||
#define ERR_NONE 0 // All good :)
|
||||
#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)
|
||||
#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
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
</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==">
|
||||
<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>
|
||||
<b>Akemi does not know where you are headed...</b><br><br>
|
||||
<button onclick="window.location.href='/sliders'">Back to controls</button>
|
||||
|
@ -1032,6 +1032,8 @@ function cmpP(a, b)
|
||||
function handleJson(s)
|
||||
{
|
||||
if (!s) return false;
|
||||
var e1 = gId('fxlist');
|
||||
var e2 = gId('selectPalette');
|
||||
|
||||
isOn = s.on;
|
||||
gId('sliderBri').value= s.bri;
|
||||
@ -1084,6 +1086,28 @@ function handleJson(s)
|
||||
selectedPal = i.pal;
|
||||
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);
|
||||
clearErrorToast();
|
||||
|
||||
@ -1097,9 +1121,6 @@ function requestJson(command, rinfo = true, verbose = true, callback = null)
|
||||
lastUpdate = new Date();
|
||||
if (!jsonTimeout) jsonTimeout = setTimeout(showErrorToast, 3000);
|
||||
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 type = command ? 'post':'get';
|
||||
|
@ -283,11 +283,11 @@ Color Order:
|
||||
<option value="4">BGR</option>
|
||||
<option value="5">GBR</option>
|
||||
</select><br>
|
||||
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:35px" onchange="UI()"/>
|
||||
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:35px" onchange="UI()"/>
|
||||
<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:40px" 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:40px" onchange="UI()"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:40px" onchange="UI()"/>
|
||||
<br>
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />
|
||||
<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 bt = "BT" + i;
|
||||
var be = "BE" + i;
|
||||
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" style="width:35px" value="${p}">`;
|
||||
c += `Button ${i} pin: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" style="width:40px" value="${p}">`;
|
||||
c += `<select name="${be}">`
|
||||
c += `<option value="0" ${t==0?"selected":""}>Disabled</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 id="btns"></div>
|
||||
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
|
||||
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()" style="width:35px"><select name="IT" 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="1">24-key RGB</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="toast"></div>
|
||||
<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">
|
||||
<h3>Defaults</h3>
|
||||
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>
|
||||
</div>
|
||||
<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>
|
||||
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>
|
||||
|
@ -76,11 +76,11 @@
|
||||
}
|
||||
}
|
||||
function addRow(i,p,l,d) {
|
||||
var t = gId("macros");
|
||||
var rCnt = t.rows.length;
|
||||
var tr = t.insertRow(rCnt);
|
||||
var t = gId("macros"); // table
|
||||
var rCnt = t.rows.length; // get the number of rows.
|
||||
var tr = t.insertRow(rCnt); // table row.
|
||||
|
||||
var td = document.createElement('td');
|
||||
var td = document.createElement('td'); // TABLE DEFINITION.
|
||||
td = tr.insertCell(0);
|
||||
td.innerHTML = `Button ${i}:`;
|
||||
td = tr.insertCell(1);
|
||||
@ -179,17 +179,7 @@
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>For analog button set <i>double</i> to:
|
||||
<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>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Macros#analog-button" target="_blank">Analog Button setup</a>
|
||||
<h3>Time-controlled presets</h3>
|
||||
<div style="display: inline-block">
|
||||
<table id="TMT">
|
||||
|
@ -31,11 +31,11 @@
|
||||
}
|
||||
|
||||
img {
|
||||
width: 999px;
|
||||
max-width: 85%;
|
||||
width: 950px;
|
||||
max-width: 82%;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
margin: 25px 0 -10px 0;
|
||||
margin: 4vh 0 0 0;
|
||||
animation: fi 1s;
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
</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==">
|
||||
<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">
|
||||
<h1>Welcome to WLED!</h1>
|
||||
<h3>Thank you for installing my application!</h3>
|
||||
|
@ -100,8 +100,8 @@ void handleIR();
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "FX.h"
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist = false);
|
||||
bool deserializeState(JsonObject root, bool fromPlaylist = false);
|
||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||
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 serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||
void serializeInfo(JsonObject root);
|
||||
@ -130,6 +130,7 @@ bool initMqtt();
|
||||
void publishMqtt();
|
||||
|
||||
//ntp.cpp
|
||||
void handleTime();
|
||||
void handleNetworkTime();
|
||||
void sendNTPPacket();
|
||||
bool checkNTPResponse();
|
||||
@ -140,6 +141,7 @@ void setCountdown();
|
||||
byte weekdayMondayFirst();
|
||||
void checkTimers();
|
||||
void calculateSunriseAndSunset();
|
||||
void setTimeFromAPI(uint32_t timein);
|
||||
|
||||
//overlay.cpp
|
||||
void initCronixie();
|
||||
@ -156,11 +158,11 @@ void _drawOverlayCronixie();
|
||||
//playlist.cpp
|
||||
void shufflePlaylist();
|
||||
void unloadPlaylist();
|
||||
void loadPlaylist(JsonObject playlistObject);
|
||||
void loadPlaylist(JsonObject playlistObject, byte presetId = 0);
|
||||
void handlePlaylist();
|
||||
|
||||
//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 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
|
||||
content="width=device-width" name="viewport"><meta name="theme-color"
|
||||
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=""
|
||||
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>
|
||||
Thank you for installing my application!</h3><b>Next steps:</b><br><br>
|
||||
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>
|
||||
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=""
|
||||
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>
|
||||
<button onclick='window.location.href="/sliders"'>Back to controls</button>
|
||||
</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!!
|
||||
const uint16_t PAGE_index_L = 33960;
|
||||
const uint16_t PAGE_index_L = 33959;
|
||||
const uint8_t PAGE_index[] PROGMEM = {
|
||||
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,
|
||||
@ -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,
|
||||
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,
|
||||
0x75, 0x2d, 0x46, 0x17, 0x3b, 0xa1, 0x4a, 0xe7, 0xa3, 0x50, 0xb2, 0xe1, 0x60, 0x7e, 0x11, 0x57,
|
||||
0x0f, 0x29, 0xc4, 0xdc, 0x3a, 0x82, 0x93, 0x0e, 0x10, 0x21, 0x14, 0xec, 0x1c, 0x76, 0x2f, 0xec,
|
||||
0x25, 0x31, 0x2a, 0x8a, 0x78, 0x78, 0xfc, 0x6b, 0x7e, 0xb3, 0x92, 0x51, 0xf1, 0xf8, 0x67, 0x21,
|
||||
0xaa, 0x72, 0x74, 0x3c, 0x2e, 0x58, 0xd0, 0xb7, 0x2a, 0x1c, 0x5f, 0xd8, 0xbb, 0x99, 0x67, 0x09,
|
||||
0xfb, 0xd2, 0xd6, 0xe2, 0xe2, 0xc1, 0x86, 0x49, 0x3a, 0x2b, 0x7f, 0xfc, 0xc0, 0x34, 0x23, 0x7b,
|
||||
0x9c, 0x0b, 0xe0, 0xa6, 0x87, 0xf1, 0xd8, 0xf7, 0xd4, 0xf3, 0x59, 0xae, 0x8d, 0x6d, 0x36, 0x4b,
|
||||
0x16, 0xbd, 0x65, 0x94, 0x94, 0x0f, 0xc3, 0xc6, 0xc3, 0xe0, 0xbe, 0x7c, 0x58, 0xd4, 0x1f, 0xc2,
|
||||
0x0a, 0x6b, 0xaf, 0x5f, 0x35, 0x5d, 0xe8, 0x35, 0x18, 0xb0, 0xd8, 0xf8, 0x85, 0xaa, 0x28, 0x83,
|
||||
0x73, 0x76, 0x7f, 0x6f, 0x31, 0x13, 0x2a, 0x49, 0x13, 0x91, 0x47, 0xa0, 0xc5, 0xf8, 0x87, 0x33,
|
||||
0x0a, 0xb0, 0xe9, 0x1d, 0xcc, 0x7d, 0x92, 0x73, 0x1c, 0x4c, 0xe7, 0xa1, 0xf0, 0x73, 0xc1, 0x88,
|
||||
0xac, 0xf3, 0x6e, 0x77, 0xad, 0x1b, 0x04, 0x15, 0x42, 0x64, 0x92, 0x54, 0x7b, 0x55, 0x72, 0xdf,
|
||||
0x7e, 0x82, 0xc8, 0x4c, 0xf2, 0xb0, 0xb6, 0xf8, 0xe8, 0x6b, 0x74, 0x52, 0x5a, 0xa5, 0xfd, 0x0b,
|
||||
0xc7, 0xa0, 0x9a, 0x76, 0x77, 0x05, 0x36, 0x62, 0xf1, 0x87, 0x1b, 0xd5, 0x44, 0x0b, 0xdc, 0xb0,
|
||||
0x10, 0x2b, 0xc4, 0xbe, 0xfa, 0x01, 0x91, 0x42, 0x50, 0xfd, 0xea, 0x73, 0x10, 0x0d, 0xf5, 0x6b,
|
||||
0x70, 0x5e, 0x5d, 0x54, 0x51, 0x55, 0xbc, 0x7f, 0x8e, 0xc4, 0xf3, 0x55, 0x1b, 0xa5, 0x78, 0x21,
|
||||
0xd0, 0x8a, 0x84, 0x68, 0x61, 0xc5, 0xa2, 0x05, 0x55, 0xda, 0xd6, 0xda, 0x78, 0x3c, 0x38, 0xd8,
|
||||
0x66, 0x69, 0x8f, 0x9b, 0x3e, 0x42, 0xe6, 0x41, 0xd8, 0x60, 0x77, 0xe3, 0xae, 0xed, 0xda, 0xdd,
|
||||
0x80, 0x3f, 0x57, 0xb0, 0x00, 0xab, 0x5a, 0x14, 0x31, 0x1f, 0xa9, 0x85, 0x8a, 0x00, 0x8f, 0x58,
|
||||
0x93, 0x54, 0x06, 0x25, 0x40, 0xd4, 0xc6, 0x32, 0xe2, 0x67, 0xf3, 0x52, 0x97, 0xb0, 0x21, 0xdb,
|
||||
0x41, 0xe5, 0x73, 0x77, 0x63, 0x2d, 0x82, 0xf4, 0x7b, 0xb7, 0xfd, 0xe2, 0x2f, 0x6b, 0x44, 0xf7,
|
||||
0x46, 0xd8, 0xc8, 0x84, 0x18, 0xad, 0x58, 0x8f, 0x2a, 0x99, 0xf4, 0x16, 0xf7, 0xae, 0x81, 0x34,
|
||||
0x35, 0xc1, 0xb9, 0xdb, 0xf0, 0xd1, 0x75, 0x09, 0x07, 0x68, 0x52, 0xc6, 0x2a, 0x12, 0x01, 0x3b,
|
||||
0x45, 0x03, 0x78, 0xe9, 0x23, 0x91, 0x16, 0xca, 0xcf, 0x74, 0x8e, 0x0e, 0x5e, 0x7b, 0xb6, 0x1e,
|
||||
0xb5, 0xb2, 0x0c, 0x50, 0xa3, 0x39, 0x7e, 0x7c, 0xfa, 0xd4, 0xd1, 0x7e, 0xe9, 0x4e, 0xcd, 0xa6,
|
||||
0x17, 0x8b, 0xbb, 0x1f, 0xee, 0x3b, 0xea, 0x96, 0x11, 0xc9, 0xc7, 0xfc, 0x8e, 0x79, 0x2b, 0xb6,
|
||||
0x52, 0x1e, 0x1b, 0xf5, 0x17, 0x9d, 0x62, 0x22, 0x55, 0x18, 0x79, 0x64, 0x0f, 0xc3, 0xf2, 0x07,
|
||||
0x68, 0x58, 0xc2, 0xb2, 0xe5, 0x23, 0x07, 0x72, 0x37, 0x7a, 0x9c, 0xa5, 0x39, 0xec, 0x54, 0xa0,
|
||||
0xdf, 0xe0, 0xa0, 0x1a, 0xc4, 0x0e, 0xfb, 0xb9, 0x0b, 0x6f, 0xe5, 0x5b, 0x7f, 0x80, 0x40, 0xab,
|
||||
0x34, 0x6c, 0xdd, 0x87, 0x18, 0x13, 0xed, 0x25, 0xe9, 0x5d, 0xc7, 0x81, 0x21, 0x2f, 0x1c, 0x8c,
|
||||
0x6b, 0xa6, 0xe9, 0x90, 0x64, 0x0b, 0x1d, 0x4b, 0x5c, 0xaa, 0x4f, 0x02, 0x17, 0xd1, 0x51, 0x42,
|
||||
0x44, 0xa3, 0x84, 0xc3, 0x35, 0xe4, 0x31, 0xbb, 0x90, 0x0a, 0x51, 0xc7, 0x88, 0xca, 0x11, 0x09,
|
||||
0xc5, 0x16, 0x8f, 0x6d, 0x64, 0xcd, 0xae, 0x00, 0x8a, 0x85, 0xff, 0xdb, 0x87, 0x1f, 0x77, 0x5f,
|
||||
0xd9, 0x6b, 0x17, 0xd1, 0xbf, 0x87, 0xe9, 0x17, 0xb8, 0x03, 0x41, 0xc7, 0x02, 0xe6, 0x46, 0xf7,
|
||||
0x43, 0xd7, 0x36, 0xc5, 0xd1, 0xf7, 0x4b, 0xac, 0x7d, 0x13, 0x7c, 0x9e, 0x09, 0x12, 0xde, 0x77,
|
||||
0x1e, 0x62, 0x1b, 0x0a, 0x64, 0x76, 0x33, 0x9b, 0x85, 0x79, 0xee, 0x80, 0xb6, 0x90, 0x92, 0x4c,
|
||||
0x49, 0xed, 0x84, 0x22, 0xc0, 0xc1, 0x44, 0xfe, 0x1d, 0x86, 0x8c, 0xcf, 0xb4, 0xdb, 0xa8, 0x28,
|
||||
0xc3, 0x2f, 0x6b, 0x9a, 0xa5, 0xf7, 0xa9, 0xa5, 0xd0, 0xaa, 0x54, 0x26, 0x55, 0xe1, 0x11, 0xfa,
|
||||
0x0e, 0x5f, 0x7a, 0x1d, 0xd1, 0x97, 0x23, 0xb4, 0x9a, 0xec, 0x5f, 0xce, 0x8e, 0x08, 0xf2, 0x7b,
|
||||
0xa5, 0xff, 0xac, 0x52, 0xde, 0xcb, 0x07, 0x42, 0x5c, 0xe4, 0x41, 0xd8, 0x53, 0x69, 0xb0, 0x38,
|
||||
0xb1, 0xa6, 0xb5, 0x28, 0x8d, 0x55, 0xb7, 0x0c, 0x81, 0x51, 0x9f, 0xa5, 0x4b, 0x30, 0xcf, 0x0e,
|
||||
0x93, 0xf4, 0xe6, 0xf2, 0xca, 0xca, 0xb3, 0x60, 0x16, 0xc2, 0xd3, 0x30, 0x87, 0x9f, 0xa7, 0x70,
|
||||
0x1c, 0xa8, 0xbd, 0xc2, 0xa2, 0xa7, 0x0f, 0x57, 0xa1, 0x3a, 0x82, 0xe1, 0xbc, 0xf4, 0xcd, 0x4c,
|
||||
0xc3, 0x9c, 0x3b, 0x0d, 0xef, 0x41, 0x27, 0x99, 0xaf, 0xbd, 0xc6, 0x6b, 0x6f, 0xb4, 0x91, 0x58,
|
||||
0x3c, 0x6c, 0xba, 0xc0, 0x73, 0x2b, 0x9d, 0xd1, 0x8d, 0x09, 0xdd, 0xe3, 0x5a, 0x5b, 0x2b, 0xde,
|
||||
0x3b, 0xa2, 0x61, 0xe4, 0xfc, 0xba, 0xf6, 0x10, 0x04, 0x0d, 0xbb, 0x35, 0x18, 0xe1, 0x44, 0xc4,
|
||||
0x7a, 0x09, 0xd7, 0x05, 0xfd, 0xf5, 0x65, 0x56, 0x7c, 0xa4, 0x31, 0xe6, 0x59, 0x9a, 0x20, 0xb7,
|
||||
0x20, 0x87, 0x27, 0xf9, 0x7c, 0x5d, 0x9c, 0x6a, 0xde, 0x88, 0x2f, 0x28, 0x22, 0x87, 0x80, 0x4d,
|
||||
0x2c, 0xd5, 0x4c, 0x0f, 0x69, 0x32, 0x14, 0x61, 0x7c, 0xf1, 0x09, 0x65, 0x51, 0x75, 0xc3, 0x56,
|
||||
0x08, 0xb9, 0xef, 0x7d, 0xdb, 0xbc, 0x8d, 0x11, 0x2a, 0x45, 0x47, 0x66, 0x1c, 0x1d, 0xf8, 0xf7,
|
||||
0xd3, 0x46, 0x87, 0xef, 0x63, 0x23, 0xdc, 0x41, 0x87, 0xa3, 0x05, 0xd3, 0x87, 0x33, 0xb9, 0x60,
|
||||
0x9f, 0x34, 0x19, 0xbe, 0xa2, 0x67, 0xfd, 0x13, 0xae, 0xb6, 0x22, 0xfc, 0x01, 0xbb, 0xba, 0x32,
|
||||
0x14, 0x7e, 0xfd, 0xc0, 0xb4, 0xcc, 0xd8, 0x9b, 0xd8, 0x69, 0x42, 0x87, 0x15, 0x06, 0x79, 0x6b,
|
||||
0x2e, 0x05, 0x45, 0x43, 0x85, 0xb7, 0x1c, 0xeb, 0x3c, 0x58, 0x30, 0x73, 0xce, 0x0f, 0x88, 0x12,
|
||||
0x5a, 0xc3, 0xf2, 0x87, 0x45, 0x98, 0x17, 0x43, 0x5b, 0xf4, 0x32, 0x0f, 0xb9, 0x1f, 0x18, 0x59,
|
||||
0x43, 0x0d, 0x6c, 0x84, 0x84, 0x49, 0xe2, 0x21, 0x16, 0x82, 0x06, 0xb5, 0xae, 0x05, 0x3a, 0x15,
|
||||
0x53, 0x00, 0x0b, 0x6c, 0x4e, 0xa2, 0x0a, 0x67, 0xac, 0xbe, 0x11, 0x57, 0xfb, 0x0b, 0xeb, 0x9c,
|
||||
0x79, 0x06, 0x70, 0xef, 0x65, 0x8f, 0xdb, 0x24, 0x2c, 0xee, 0xd2, 0xd5, 0xb5, 0x98, 0x11, 0x21,
|
||||
0x2d, 0x0b, 0xf5, 0x01, 0xa9, 0xec, 0xc3, 0x4b, 0x04, 0x67, 0x8f, 0x46, 0xff, 0x01, 0xdf, 0xc5,
|
||||
0xcc, 0xd9, 0xab, 0xf7, 0xe9, 0x76, 0xac, 0x38, 0x4d, 0x2e, 0xa9, 0x12, 0x5a, 0xeb, 0xd9, 0x2a,
|
||||
0x68, 0xd1, 0x03, 0x68, 0xb9, 0xe1, 0x03, 0x88, 0xb9, 0xa1, 0x1a, 0xd7, 0x7a, 0x3d, 0xd2, 0x5c,
|
||||
0x3c, 0x18, 0xbd, 0x32, 0xc5, 0xb7, 0x82, 0xc3, 0x47, 0x39, 0xf8, 0xc6, 0x5e, 0x36, 0xd6, 0x00,
|
||||
0x5e, 0x27, 0xb7, 0x10, 0x91, 0x10, 0xc1, 0xc4, 0x81, 0x9e, 0xf1, 0x29, 0xc9, 0x74, 0xf9, 0xa8,
|
||||
0x41, 0x67, 0xa3, 0x4a, 0x3d, 0x54, 0xa8, 0x18, 0xe9, 0x23, 0xca, 0xef, 0xb2, 0xb5, 0x51, 0xa3,
|
||||
0xf1, 0xd5, 0x4c, 0x34, 0x89, 0x34, 0xab, 0x53, 0x44, 0xec, 0x9d, 0xc6, 0x41, 0x72, 0x6d, 0x4a,
|
||||
0x2b, 0xea, 0x22, 0x10, 0x8c, 0x40, 0x93, 0x53, 0x88, 0x20, 0x3c, 0xf5, 0xc9, 0xb1, 0xbb, 0x08,
|
||||
0x26, 0xc6, 0x12, 0x0a, 0x15, 0x64, 0x47, 0x8a, 0x2b, 0xdc, 0x8e, 0x8a, 0x68, 0x2d, 0xfe, 0x12,
|
||||
0x9f, 0x5a, 0x7a, 0x16, 0xa9, 0x78, 0x75, 0x70, 0x19, 0x6a, 0xb2, 0x4a, 0xa2, 0xfe, 0xb3, 0x18,
|
||||
0x24, 0x7d, 0x0e, 0xc7, 0xb5, 0x29, 0x88, 0x46, 0xaa, 0x49, 0x34, 0x4e, 0x98, 0xb4, 0x2b, 0x10,
|
||||
0x35, 0xd5, 0xe8, 0xe5, 0xf8, 0x3a, 0x65, 0x10, 0x6e, 0xf9, 0x45, 0x0e, 0x5f, 0x4d, 0x4e, 0xf8,
|
||||
0x1d, 0x19, 0x22, 0x1b, 0x7d, 0x02, 0x5c, 0xed, 0xb3, 0x67, 0xa0, 0x44, 0x40, 0xfa, 0x2c, 0x64,
|
||||
0x4b, 0x6d, 0xd3, 0x58, 0x06, 0xd7, 0xa0, 0xdb, 0x4b, 0xac, 0xc4, 0xb6, 0x31, 0x86, 0xbd, 0x94,
|
||||
0xf7, 0x88, 0xc8, 0x59, 0xaf, 0xb8, 0xdb, 0xaf, 0xa4, 0xcb, 0x6e, 0xdf, 0x23, 0x62, 0xa4, 0x2e,
|
||||
0x60, 0x7e, 0xba, 0x81, 0x5c, 0x6f, 0x60, 0x48, 0x5c, 0x7c, 0x71, 0xa8, 0x0c, 0x48, 0x39, 0x82,
|
||||
0x86, 0xcc, 0x73, 0x94, 0x6f, 0x30, 0xdf, 0x6f, 0x98, 0x2d, 0x97, 0x76, 0xca, 0x5f, 0x66, 0x95,
|
||||
0xac, 0x8f, 0xee, 0x33, 0x0c, 0x94, 0x6b, 0x36, 0xc9, 0xef, 0x89, 0x42, 0x94, 0xf6, 0x62, 0x56,
|
||||
0xad, 0xcd, 0xff, 0xff, 0x2c, 0x94, 0x8d, 0xe9, 0x7d, 0x99, 0xb1, 0x72, 0xb8, 0xc9, 0x34, 0xd4,
|
||||
0x68, 0xfb, 0x0b, 0x6d, 0x55, 0x8d, 0x36, 0xbe, 0xdc, 0x78, 0x39, 0xac, 0x99, 0x2d, 0x3f, 0x59,
|
||||
0xf3, 0xcb, 0x26, 0xb4, 0xc9, 0x62, 0x19, 0xff, 0x76, 0x73, 0xdd, 0x6e, 0xd9, 0x04, 0xab, 0x16,
|
||||
0x13, 0x66, 0xb3, 0xaf, 0x91, 0x66, 0x8c, 0x38, 0x7a, 0xd2, 0xb4, 0x79, 0xa3, 0xed, 0xed, 0xa6,
|
||||
0x85, 0x65, 0x1b, 0x5c, 0x6d, 0x55, 0xc2, 0x35, 0xab, 0x8f, 0x34, 0xab, 0x5c, 0xad, 0x95, 0x19,
|
||||
0x4d, 0xfc, 0xe9, 0xc8, 0x16, 0xda, 0x80, 0xed, 0xf1, 0x11, 0xcc, 0xc1, 0xe2, 0xd2, 0xc8, 0xad,
|
||||
0xe1, 0xc1, 0x20, 0xd5, 0xb2, 0xa3, 0x8d, 0x26, 0x9e, 0xb9, 0xce, 0x17, 0x96, 0x0d, 0x3f, 0x3c,
|
||||
0x62, 0x12, 0xda, 0x3e, 0x42, 0xf6, 0xa2, 0xdf, 0x8d, 0xb4, 0x71, 0x96, 0x08, 0xb5, 0x69, 0x71,
|
||||
0xce, 0x55, 0xe9, 0x9b, 0x58, 0xef, 0xfe, 0xab, 0x80, 0xd7, 0xfb, 0xcd, 0x7c, 0xae, 0xd0, 0x43,
|
||||
0x35, 0x21, 0x42, 0x0a, 0x3b, 0x26, 0x92, 0x3e, 0xa9, 0xcc, 0x20, 0x2f, 0x3e, 0x07, 0x91, 0xb1,
|
||||
0xcf, 0x77, 0x71, 0xff, 0x39, 0xee, 0x15, 0x21, 0x91, 0x7c, 0xca, 0x79, 0xfb, 0xd9, 0x3e, 0x16,
|
||||
0xb5, 0x1d, 0xad, 0x02, 0x14, 0x58, 0xac, 0x9c, 0x1f, 0x3e, 0x82, 0x7d, 0x73, 0x63, 0xd0, 0xd5,
|
||||
0x98, 0xb4, 0x21, 0x95, 0x21, 0x79, 0xd6, 0xda, 0xac, 0xfe, 0x88, 0xdb, 0x26, 0xb5, 0x57, 0x82,
|
||||
0x83, 0x09, 0xaa, 0xe3, 0x0e, 0xf1, 0x77, 0xc4, 0xa2, 0x84, 0x4c, 0xe6, 0xd3, 0x1d, 0x0b, 0x5a,
|
||||
0x4e, 0x1b, 0xa6, 0x58, 0x7a, 0xa7, 0x7c, 0xf9, 0x09, 0x03, 0x69, 0xb1, 0x4c, 0xf6, 0x2f, 0x65,
|
||||
0x18, 0x18, 0xe2, 0xad, 0xae, 0x2c, 0xc5, 0x69, 0xff, 0x46, 0xac, 0x85, 0x94, 0xe9, 0xc9, 0x32,
|
||||
0xb6, 0x1a, 0xd8, 0x6c, 0x40, 0xcd, 0x13, 0x9a, 0xe5, 0xc5, 0xa5, 0xe1, 0x1c, 0x46, 0x3f, 0x8f,
|
||||
0x72, 0xe9, 0x51, 0xaf, 0x7a, 0xa4, 0xd6, 0x95, 0x0d, 0x35, 0x1b, 0x50, 0x3f, 0xcf, 0x7c, 0x5a,
|
||||
0xd9, 0x48, 0x34, 0x37, 0x2b, 0x4b, 0x07, 0x7a, 0x74, 0x80, 0x01, 0xcf, 0xee, 0xcd, 0xc9, 0x31,
|
||||
0xdd, 0x11, 0x1c, 0x78, 0x48, 0x39, 0x63, 0x95, 0x31, 0x6a, 0x4c, 0x04, 0xab, 0xbd, 0x1b, 0x64,
|
||||
0x91, 0x11, 0xb8, 0x46, 0x9d, 0xc3, 0x7a, 0x7f, 0x7d, 0xbd, 0xbf, 0xfe, 0x46, 0xcf, 0x3b, 0xc3,
|
||||
0x1c, 0xfd, 0x58, 0x78, 0xc3, 0x5a, 0xd3, 0x95, 0xca, 0x25, 0xf1, 0x84, 0xb7, 0x9d, 0x08, 0xa2,
|
||||
0x35, 0xe5, 0x05, 0x95, 0xeb, 0xf5, 0xa5, 0x7e, 0x74, 0x4f, 0x8d, 0xed, 0x14, 0x60, 0xa5, 0x6e,
|
||||
0xf8, 0x29, 0x24, 0x03, 0xcf, 0x1a, 0x5c, 0xfe, 0x17, 0x0c, 0xae, 0x6d, 0x81, 0xe9, 0xf4, 0xf1,
|
||||
0x88, 0x88, 0xd3, 0x39, 0xfe, 0xde, 0x6a, 0xbd, 0x15, 0xf5, 0x25, 0x9a, 0xd7, 0x2f, 0xc1, 0xf2,
|
||||
0xaa, 0xaa, 0xe2, 0x93, 0x49, 0x08, 0xc4, 0xb5, 0x38, 0x78, 0xe1, 0xf1, 0x35, 0xd9, 0x97, 0x87,
|
||||
0x53, 0x40, 0x65, 0x38, 0x6c, 0x46, 0x49, 0x5b, 0x8f, 0x37, 0x8c, 0x0e, 0x33, 0x78, 0x1a, 0xe1,
|
||||
0x43, 0x9e, 0x70, 0xa2, 0xa2, 0x49, 0x3c, 0x8e, 0x4a, 0xd5, 0xd5, 0x25, 0x4f, 0x08, 0xcf, 0x5e,
|
||||
0x1c, 0xa1, 0x1c, 0x34, 0x4e, 0x25, 0x98, 0xb0, 0x2b, 0xc3, 0xe8, 0xf2, 0x08, 0xef, 0x3c, 0x63,
|
||||
0x2c, 0xf3, 0x30, 0x3e, 0xe9, 0xec, 0x74, 0xc3, 0xee, 0xce, 0x93, 0x63, 0x51, 0xae, 0x22, 0xdf,
|
||||
0xcb, 0x80, 0x22, 0xdc, 0x6f, 0x15, 0x7c, 0x69, 0xb8, 0xf3, 0xdc, 0xbb, 0xee, 0x64, 0xc3, 0x65,
|
||||
0xb7, 0xb3, 0xde, 0x70, 0xae, 0x10, 0xe8, 0x4d, 0x21, 0x89, 0xa9, 0xf0, 0xbd, 0xb4, 0x66, 0xda,
|
||||
0x4e, 0xe3, 0xb9, 0xad, 0xc1, 0x8c, 0x9a, 0xbe, 0x89, 0x25, 0x09, 0x64, 0x30, 0x51, 0x15, 0x1f,
|
||||
0x0a, 0xad, 0x5c, 0xd4, 0x6e, 0x22, 0xfd, 0xb2, 0xcc, 0x1a, 0x57, 0x65, 0x7b, 0xfc, 0x91, 0xf1,
|
||||
0x63, 0xc4, 0xf9, 0xd7, 0x0f, 0xe2, 0x86, 0xf3, 0x54, 0xac, 0x10, 0x79, 0x7f, 0x37, 0xf5, 0xc1,
|
||||
0x99, 0x87, 0x08, 0xc4, 0xa5, 0x05, 0xbe, 0x30, 0x7c, 0x50, 0x0d, 0xe9, 0xf6, 0x0f, 0x55, 0xa4,
|
||||
0x0b, 0x2d, 0xca, 0x85, 0x53, 0xbb, 0xf5, 0x9f, 0x98, 0xc9, 0xe7, 0x5d, 0xfa, 0xe5, 0x7e, 0x3d,
|
||||
0xef, 0xda, 0x3f, 0xe2, 0xe0, 0xd0, 0x75, 0xf8, 0xa8, 0x5d, 0xfc, 0x02, 0xff, 0xb7, 0x44, 0x07,
|
||||
0xe4, 0x9b, 0xe2, 0xa2, 0x54, 0x0a, 0x8d, 0xaa, 0x27, 0x69, 0xff, 0xa2, 0x91, 0xad, 0xa4, 0x2d,
|
||||
0xb3, 0x89, 0xac, 0x3d, 0x68, 0xab, 0xcd, 0xb5, 0x86, 0xf2, 0x25, 0x2d, 0x92, 0xa6, 0x72, 0x19,
|
||||
0x2e, 0x07, 0x04, 0xef, 0xed, 0xe1, 0xd9, 0xf9, 0xba, 0x66, 0x93, 0x2c, 0x3c, 0x58, 0xd8, 0x7c,
|
||||
0x1b, 0x64, 0xb0, 0x30, 0x7e, 0x84, 0x92, 0x74, 0x98, 0x23, 0x63, 0x2a, 0xa8, 0xcf, 0x4a, 0xe4,
|
||||
0x51, 0xd4, 0xf2, 0xdb, 0x08, 0xe7, 0xab, 0xb0, 0x16, 0x3a, 0x18, 0x1d, 0xb1, 0xa1, 0x35, 0xd4,
|
||||
0x01, 0x43, 0xc3, 0x4e, 0x28, 0xd4, 0x16, 0xa2, 0x2e, 0x44, 0x92, 0xe4, 0xaf, 0xb9, 0x82, 0xf2,
|
||||
0xc5, 0xa2, 0x64, 0x36, 0xf3, 0x27, 0xcd, 0xa9, 0x92, 0xa7, 0xcc, 0xa9, 0xc0, 0x36, 0x7b, 0x5b,
|
||||
0x7e, 0xa2, 0xcc, 0x9e, 0xb4, 0x01, 0x27, 0xc3, 0xc2, 0x15, 0xce, 0x8b, 0xb9, 0x0b, 0xe7, 0xc6,
|
||||
0x61, 0x83, 0x47, 0xc8, 0x89, 0x47, 0xe8, 0x26, 0xeb, 0xf5, 0xa8, 0x66, 0xef, 0xa5, 0x19, 0x52,
|
||||
0xc5, 0xcf, 0x30, 0xa4, 0x0a, 0x9e, 0x61, 0x48, 0x95, 0xf2, 0x86, 0xd0, 0x6b, 0x7e, 0xec, 0x8a,
|
||||
0xef, 0xf4, 0xd8, 0x0f, 0xd6, 0xfa, 0x62, 0xa7, 0xbc, 0x86, 0x2c, 0x1e, 0x9d, 0xab, 0xdd, 0xd0,
|
||||
0x74, 0xd6, 0xe5, 0x06, 0x55, 0x2e, 0x47, 0x13, 0x4d, 0x8c, 0x8a, 0x98, 0x7f, 0x49, 0x28, 0xc2,
|
||||
0x12, 0x72, 0xec, 0xbf, 0xe5, 0x4d, 0x5c, 0x44, 0x44, 0xa0, 0x55, 0x4e, 0x53, 0xf4, 0x44, 0xc6,
|
||||
0x5b, 0x22, 0x40, 0xdb, 0x42, 0xbe, 0x09, 0xed, 0xb8, 0x8a, 0x44, 0x62, 0xa2, 0xe5, 0xdd, 0x5d,
|
||||
0x77, 0x13, 0x14, 0x60, 0x21, 0x3d, 0xb1, 0xdd, 0xe6, 0x7e, 0xc3, 0x67, 0x6e, 0x33, 0xf4, 0x20,
|
||||
0xfa, 0xb4, 0xbe, 0x38, 0xf4, 0xfb, 0x51, 0xe8, 0xf9, 0x39, 0x7a, 0xa4, 0xb1, 0x65, 0x64, 0xb4,
|
||||
0xb5, 0x8c, 0x9e, 0x02, 0x44, 0xf8, 0x99, 0x6f, 0x6e, 0x2e, 0x4d, 0x86, 0x5b, 0xca, 0x7d, 0x3d,
|
||||
0x3c, 0x6f, 0x6f, 0x01, 0xfe, 0xe2, 0x9b, 0x5b, 0x20, 0xea, 0x68, 0xd8, 0x0a, 0x03, 0xec, 0x24,
|
||||
0x56, 0xda, 0x3a, 0x36, 0x1a, 0xae, 0x82, 0xb6, 0x89, 0xac, 0xc6, 0xc8, 0x04, 0x5d, 0x01, 0x53,
|
||||
0x3d, 0xbf, 0xd0, 0xce, 0x57, 0x42, 0x3d, 0x65, 0xd5, 0xed, 0x33, 0x86, 0x72, 0xf2, 0x3b, 0xaa,
|
||||
0xab, 0x61, 0xfd, 0xd5, 0x8b, 0x4d, 0xaf, 0x9e, 0xe9, 0xec, 0xff, 0x79, 0xb5, 0x8e, 0xfe, 0x96,
|
||||
0xd2, 0x35, 0x37, 0xb2, 0x1c, 0xa9, 0xa6, 0x74, 0x93, 0x8e, 0x02, 0x96, 0x05, 0x8f, 0xda, 0xc6,
|
||||
0x6c, 0x1c, 0x51, 0xc3, 0xa8, 0x23, 0x7c, 0xc2, 0xca, 0xa5, 0x05, 0x34, 0x17, 0xf7, 0x43, 0x2d,
|
||||
0x68, 0x2f, 0x2f, 0x74, 0x5d, 0x32, 0x5f, 0xf9, 0x53, 0x7c, 0xe6, 0x9a, 0x9b, 0xae, 0x0f, 0xad,
|
||||
0x96, 0x46, 0x4f, 0xaf, 0xff, 0xb3, 0x9a, 0x51, 0x7b, 0x41, 0x74, 0xc0, 0xb3, 0xf6, 0xa1, 0xe6,
|
||||
0x94, 0xf1, 0x27, 0xb7, 0xa3, 0xc5, 0xc5, 0xe3, 0x4f, 0xee, 0x0a, 0x4d, 0x6c, 0x18, 0x6e, 0xda,
|
||||
0x0c, 0x1c, 0xa8, 0x52, 0x25, 0xd3, 0x38, 0x3f, 0x4d, 0x0b, 0x10, 0xe7, 0x2f, 0xd6, 0xd4, 0xe0,
|
||||
0x58, 0x43, 0x4f, 0xde, 0x69, 0x3b, 0xd4, 0xf9, 0x7d, 0xeb, 0x70, 0x0c, 0xc5, 0xfa, 0x46, 0x30,
|
||||
0x2b, 0x15, 0xec, 0xad, 0x4d, 0x47, 0xed, 0x4d, 0x37, 0xb4, 0xf2, 0x1b, 0x9b, 0x7f, 0x97, 0x36,
|
||||
0x71, 0x19, 0x12, 0x11, 0x86, 0xeb, 0x8d, 0xfa, 0xa8, 0xa3, 0x7f, 0x56, 0x4b, 0x9d, 0xc5, 0xc3,
|
||||
0xdd, 0xfe, 0x7a, 0xb4, 0xc1, 0xca, 0x65, 0x7b, 0xbb, 0xd3, 0x11, 0x95, 0x3c, 0x17, 0xa6, 0x29,
|
||||
0xc3, 0x07, 0xe2, 0x39, 0x6a, 0x03, 0xd6, 0x6d, 0x5f, 0x1c, 0x84, 0xce, 0x6a, 0x3e, 0x0f, 0xab,
|
||||
0xe7, 0x50, 0x65, 0x0f, 0x5b, 0x37, 0x4b, 0x9b, 0xa9, 0xf3, 0x19, 0x3b, 0xfb, 0xac, 0xad, 0x95,
|
||||
0x31, 0xf1, 0x2a, 0x82, 0x29, 0xcb, 0x69, 0x81, 0x46, 0xda, 0x75, 0xf9, 0x4e, 0x46, 0xbb, 0xcd,
|
||||
0x54, 0x64, 0x65, 0x25, 0x79, 0x91, 0x91, 0x7b, 0x38, 0x68, 0x8f, 0x5b, 0x27, 0x98, 0x1a, 0x5d,
|
||||
0x31, 0xb3, 0x44, 0xdd, 0x74, 0xb6, 0x3a, 0xd9, 0x71, 0x8d, 0x0e, 0xa8, 0xc5, 0x93, 0x46, 0x06,
|
||||
0x8f, 0xec, 0xf8, 0xb0, 0x0f, 0x6b, 0x59, 0xaa, 0xbb, 0x89, 0x7d, 0x73, 0x38, 0x17, 0x4f, 0x27,
|
||||
0x7b, 0xaf, 0x91, 0x9d, 0xc5, 0x7d, 0x49, 0x34, 0xf1, 0xdb, 0xef, 0xb5, 0x88, 0xd0, 0xd9, 0xb1,
|
||||
0xf2, 0x51, 0x7b, 0xa8, 0x08, 0x99, 0x36, 0x62, 0x95, 0x88, 0xc2, 0x68, 0xaa, 0x47, 0xba, 0x9e,
|
||||
0x1a, 0x8f, 0x91, 0xc5, 0x45, 0x7f, 0x9c, 0x9b, 0x8f, 0x2b, 0x95, 0x7a, 0xae, 0x55, 0x0a, 0xb2,
|
||||
0xf2, 0x7e, 0xe3, 0xc0, 0xc6, 0x85, 0x1e, 0x02, 0x32, 0x57, 0x41, 0x8b, 0x13, 0xb6, 0x38, 0xe2,
|
||||
0x18, 0xd1, 0x3e, 0xd1, 0x62, 0x92, 0x5f, 0x38, 0x1c, 0x28, 0xbd, 0x3b, 0x6b, 0xd3, 0x1f, 0x8b,
|
||||
0xab, 0xad, 0x22, 0x67, 0x1b, 0x69, 0x4e, 0x38, 0x4e, 0xb1, 0x26, 0x30, 0xb1, 0x16, 0xd1, 0x8a,
|
||||
0xc3, 0xe5, 0x73, 0x5a, 0xa3, 0x88, 0xc8, 0x9a, 0xfb, 0x5f, 0x16, 0x1d, 0xfb, 0xc1, 0x76, 0xc6,
|
||||
0xbb, 0xfd, 0xcf, 0xee, 0xea, 0xf4, 0x63, 0x52, 0x04, 0xf7, 0x52, 0xf5, 0x4d, 0x5c, 0xd3, 0xec,
|
||||
0x86, 0x48, 0x9f, 0xa5, 0x85, 0xe9, 0xe9, 0x9d, 0x8a, 0xee, 0x3c, 0xdf, 0xd7, 0x7a, 0x14, 0xa3,
|
||||
0xb4, 0x9d, 0x2f, 0x9d, 0x9e, 0x0c, 0x5f, 0xca, 0x4a, 0xd0, 0x0c, 0x01, 0xb0, 0xa6, 0x21, 0xd1,
|
||||
0xf9, 0x44, 0xd0, 0xa5, 0xf3, 0x68, 0xf1, 0x11, 0x40, 0xcb, 0x9a, 0x54, 0xc9, 0x5a, 0x3b, 0xeb,
|
||||
0xa2, 0x97, 0x22, 0x5c, 0x62, 0xd1, 0xcb, 0x00, 0x8e, 0x7e, 0x76, 0x4c, 0x5b, 0x49, 0xc7, 0xe8,
|
||||
0xbd, 0xb4, 0xc5, 0xac, 0x7a, 0xfe, 0x23, 0x2e, 0x37, 0x2b, 0x29, 0x43, 0x9d, 0xc2, 0x93, 0xad,
|
||||
0xf7, 0x47, 0x4c, 0x24, 0xb4, 0x1e, 0xe2, 0x5a, 0x46, 0x62, 0xc6, 0xb1, 0x10, 0x07, 0x22, 0x3b,
|
||||
0x7e, 0xec, 0x44, 0x50, 0x8f, 0xe9, 0x44, 0x04, 0x48, 0x3c, 0xcb, 0x8e, 0xcf, 0xfd, 0xc2, 0x35,
|
||||
0x02, 0x7b, 0x52, 0x91, 0x18, 0x5c, 0xb3, 0x38, 0x6d, 0x16, 0xdd, 0x36, 0x8b, 0x38, 0x4e, 0xd9,
|
||||
0x50, 0xeb, 0xe0, 0x81, 0xb0, 0xd2, 0x7b, 0x17, 0x41, 0xc7, 0xed, 0x4d, 0xab, 0x06, 0xdb, 0x88,
|
||||
0x50, 0x46, 0x8e, 0x4e, 0xc2, 0xbb, 0xf8, 0x23, 0x9f, 0xd6, 0xb9, 0xda, 0xb9, 0x9e, 0xbd, 0x76,
|
||||
0x19, 0x24, 0x55, 0xf4, 0x52, 0xee, 0x08, 0x20, 0xca, 0xa5, 0x6c, 0xcd, 0x1b, 0x1b, 0xcf, 0x68,
|
||||
0x91, 0x50, 0xe6, 0x38, 0x2d, 0x31, 0x8f, 0x75, 0xbe, 0xd6, 0xa0, 0xd9, 0x4f, 0x1a, 0xc8, 0x3a,
|
||||
0xa3, 0x52, 0x1d, 0x5b, 0x9b, 0xb3, 0x0d, 0xcf, 0x9b, 0xad, 0x1b, 0x5c, 0x9a, 0xb2, 0x11, 0x83,
|
||||
0xd7, 0x3f, 0x92, 0xfb, 0x86, 0xa3, 0x8d, 0x49, 0x72, 0x9e, 0xeb, 0xa8, 0x90, 0xae, 0x58, 0xc0,
|
||||
0x8c, 0x64, 0x93, 0x39, 0x7c, 0x83, 0x4b, 0x67, 0xa2, 0xd0, 0xb1, 0x5d, 0xad, 0xe2, 0x32, 0x58,
|
||||
0x5d, 0x42, 0x53, 0x83, 0x24, 0x91, 0x7a, 0xb9, 0x54, 0x7c, 0x1d, 0x20, 0x49, 0xe5, 0xa8, 0x10,
|
||||
0x06, 0x69, 0xb5, 0xb6, 0x5f, 0x6c, 0x68, 0x5b, 0xaf, 0xab, 0x9a, 0x1f, 0x88, 0xe6, 0xf5, 0x47,
|
||||
0xb2, 0x87, 0x17, 0x48, 0x52, 0x29, 0xb3, 0xf3, 0x88, 0x6c, 0xa7, 0xc0, 0xf2, 0xb5, 0x1e, 0x4d,
|
||||
0x3b, 0x21, 0xc7, 0x35, 0x0d, 0xda, 0xdb, 0x6c, 0xe7, 0x1e, 0x33, 0x7f, 0xdf, 0x60, 0xc5, 0xee,
|
||||
0xd6, 0x9c, 0x67, 0x85, 0xa7, 0x16, 0x1d, 0x9d, 0x2b, 0x44, 0x60, 0x2b, 0x7d, 0x9d, 0x8f, 0xa4,
|
||||
0xad, 0xab, 0xbd, 0xe2, 0x34, 0xd6, 0xb8, 0x28, 0xe8, 0x7a, 0xbd, 0xa2, 0xdb, 0x95, 0x78, 0x4f,
|
||||
0xf7, 0x76, 0xc8, 0x91, 0x53, 0x7b, 0x46, 0x92, 0x89, 0x32, 0x76, 0xa2, 0xf4, 0xca, 0xec, 0xbe,
|
||||
0xf0, 0x9c, 0xd1, 0x3c, 0x7d, 0x08, 0x7b, 0x57, 0x7a, 0xb5, 0xfd, 0x97, 0xb5, 0x7a, 0xce, 0x9a,
|
||||
0xe6, 0x14, 0x87, 0x1d, 0x2e, 0x0c, 0xa6, 0x08, 0x9c, 0x78, 0xc5, 0xb9, 0x6e, 0xaf, 0x9c, 0x43,
|
||||
0x34, 0x21, 0x06, 0x47, 0x85, 0xeb, 0xfa, 0xfa, 0xc1, 0x6d, 0x49, 0xe5, 0x33, 0xf2, 0x1a, 0x46,
|
||||
0xe4, 0x3c, 0x5d, 0x49, 0x3d, 0xe8, 0x6f, 0xae, 0x2e, 0xa7, 0xae, 0xb2, 0xd0, 0xe7, 0xe5, 0xfa,
|
||||
0x15, 0x84, 0x67, 0x69, 0xb6, 0xba, 0x32, 0x56, 0xb5, 0x70, 0xfb, 0x8e, 0xdb, 0x31, 0xaa, 0xff,
|
||||
0x0d, 0x61, 0xee, 0x55, 0xed, 0xcb, 0x5a, 0xed, 0x41, 0xbd, 0xf6, 0x5b, 0xbd, 0xf6, 0xb4, 0x56,
|
||||
0x7b, 0xbf, 0x31, 0x68, 0x91, 0x55, 0xb4, 0x39, 0xe8, 0xab, 0xf0, 0xfe, 0x94, 0x8d, 0xe6, 0x46,
|
||||
0x68, 0x27, 0xbf, 0x99, 0x0a, 0x13, 0x3a, 0x15, 0x0e, 0xb3, 0x30, 0xe0, 0x62, 0x54, 0x30, 0x76,
|
||||
0x0c, 0xbb, 0x3e, 0x5c, 0xc8, 0x4e, 0x65, 0xcd, 0x97, 0x8e, 0x04, 0x29, 0x6a, 0x6b, 0x56, 0xd9,
|
||||
0xe9, 0x56, 0x65, 0xc9, 0x62, 0xb3, 0xcd, 0x9a, 0x02, 0xfe, 0x7d, 0x47, 0x93, 0xef, 0xd0, 0x4b,
|
||||
0xac, 0xdb, 0x51, 0x12, 0xb1, 0xe7, 0x36, 0x02, 0x8f, 0x9e, 0xfe, 0x3e, 0x41, 0x15, 0x92, 0x13,
|
||||
0xf5, 0xae, 0xc3, 0x8f, 0x47, 0x9c, 0xf1, 0x06, 0x16, 0xe5, 0x3c, 0xff, 0xaa, 0x87, 0xb2, 0x48,
|
||||
0xcf, 0x8a, 0xa0, 0x8f, 0x7f, 0xa4, 0xcf, 0x5b, 0x4b, 0x80, 0xa2, 0x2d, 0xd1, 0x4b, 0xc7, 0xa5,
|
||||
0xb9, 0xf3, 0x2d, 0x5f, 0x07, 0x20, 0xfb, 0x2b, 0x84, 0x3a, 0xac, 0xaa, 0x7a, 0x2e, 0x2d, 0x52,
|
||||
0x95, 0xb0, 0xa0, 0x59, 0x7d, 0xb1, 0x08, 0x02, 0x24, 0x3b, 0x5d, 0x0b, 0xcf, 0x31, 0xbd, 0x73,
|
||||
0xa7, 0x32, 0x90, 0x15, 0x83, 0xf1, 0x34, 0xe8, 0x1c, 0xd4, 0xe6, 0xa4, 0xc3, 0xa6, 0x09, 0x89,
|
||||
0x52, 0xc2, 0x54, 0x87, 0xb8, 0x52, 0xf0, 0x64, 0x82, 0x96, 0x5c, 0x84, 0xfa, 0x40, 0xa5, 0xdf,
|
||||
0x70, 0x08, 0x97, 0xe1, 0x02, 0x1f, 0xf9, 0xda, 0xb9, 0xd8, 0x70, 0x58, 0xca, 0x42, 0x43, 0xe6,
|
||||
0x55, 0x47, 0xc8, 0x7d, 0xce, 0x52, 0x62, 0x66, 0x23, 0xf3, 0xfd, 0x47, 0x11, 0xd8, 0xf6, 0x76,
|
||||
0x6d, 0x58, 0xf0, 0xd8, 0x4d, 0xc2, 0x98, 0x36, 0x30, 0xbf, 0xb5, 0x5d, 0x9b, 0xfe, 0xb1, 0xaf,
|
||||
0xf3, 0xa3, 0x8d, 0xd4, 0x4f, 0xae, 0x00, 0x66, 0x77, 0xc0, 0x69, 0x4d, 0xcc, 0xf5, 0x6e, 0x43,
|
||||
0x97, 0xca, 0xbd, 0xbd, 0x7e, 0xfe, 0x13, 0x29, 0x6f, 0xa3, 0x92, 0xe1, 0xd9, 0x59, 0x4e, 0x87,
|
||||
0x3e, 0xa7, 0xa3, 0x9c, 0xd3, 0x01, 0xd5, 0x9b, 0x3c, 0x77, 0xcf, 0xf0, 0xff, 0xf9, 0x7a, 0x8d,
|
||||
0xf9, 0xa3, 0x68, 0x62, 0xbe, 0x48, 0x4f, 0x1f, 0x7b, 0x97, 0x5e, 0x1c, 0x0e, 0xc4, 0x8b, 0xec,
|
||||
0x02, 0x59, 0x7b, 0xf5, 0xb1, 0xb7, 0xe9, 0xd5, 0xcd, 0x28, 0x3c, 0xf9, 0x52, 0x7e, 0x32, 0xa9,
|
||||
0x38, 0x01, 0xac, 0xcb, 0xd5, 0x4c, 0xc7, 0xf9, 0x48, 0x44, 0xf5, 0xb7, 0x9f, 0x08, 0x2c, 0x65,
|
||||
0x96, 0x2f, 0xfc, 0xee, 0x94, 0x79, 0x25, 0x65, 0x32, 0x49, 0x24, 0xbe, 0x7c, 0x53, 0xa6, 0x98,
|
||||
0xdc, 0x83, 0x97, 0xc7, 0xde, 0x5d, 0x74, 0x4d, 0xdc, 0xee, 0x5a, 0x72, 0x90, 0x2b, 0xea, 0xd7,
|
||||
0xc8, 0xc5, 0xa4, 0x4c, 0x9d, 0x3a, 0x9d, 0xab, 0x59, 0xd7, 0xef, 0xbf, 0x72, 0xc6, 0xfb, 0x9c,
|
||||
0xaa, 0x07, 0xbd, 0x3b, 0xee, 0xd5, 0x6c, 0x3c, 0x50, 0x3f, 0xf7, 0x3d, 0x9c, 0xd5, 0x83, 0x03,
|
||||
0xdf, 0xbf, 0x9a, 0x71, 0x49, 0xd7, 0xdf, 0x47, 0x89, 0xf7, 0x4a, 0x2b, 0xa1, 0x06, 0x14, 0xca,
|
||||
0x42, 0xd2, 0x33, 0x85, 0x6c, 0x78, 0x6f, 0xfd, 0x8b, 0xab, 0x1c, 0x89, 0x1b, 0xaf, 0x66, 0x6b,
|
||||
0xe4, 0x37, 0xf5, 0xbe, 0x71, 0xad, 0x17, 0xde, 0x37, 0x70, 0xde, 0x74, 0xdc, 0xd7, 0x7d, 0xe9,
|
||||
0xe4, 0x43, 0x28, 0x8a, 0xe3, 0x16, 0x54, 0xce, 0x23, 0xc9, 0xe2, 0x57, 0xe6, 0xba, 0x84, 0x77,
|
||||
0x07, 0x9e, 0x1b, 0x67, 0x93, 0xa9, 0x19, 0x8e, 0x79, 0x54, 0xa6, 0xe8, 0x31, 0x3a, 0x15, 0xbe,
|
||||
0xd3, 0x6e, 0xa8, 0x53, 0xc6, 0x47, 0x69, 0x42, 0x54, 0xfd, 0xd2, 0xfa, 0x35, 0x9c, 0xa6, 0x69,
|
||||
0x61, 0x0b, 0xbb, 0x5b, 0xd1, 0x33, 0x1d, 0xbe, 0x46, 0x1e, 0x35, 0x91, 0xb4, 0x51, 0xaa, 0x9c,
|
||||
0xd4, 0x20, 0x4f, 0x8d, 0x51, 0xae, 0x10, 0xfd, 0xc9, 0x44, 0x1a, 0x32, 0x12, 0xd3, 0x48, 0x8d,
|
||||
0xfa, 0xd4, 0xf9, 0xec, 0xf1, 0x89, 0x2e, 0xab, 0xe1, 0x9d, 0xb2, 0x2f, 0x94, 0xea, 0xdd, 0x6d,
|
||||
0x34, 0xb4, 0x58, 0xd4, 0x1a, 0xe2, 0x95, 0x2b, 0x25, 0xb5, 0x2a, 0xfd, 0x8e, 0x90, 0xf3, 0x3f,
|
||||
0xc8, 0x10, 0x7c, 0x42, 0xf8, 0xaa, 0x8c, 0x3b, 0x58, 0x20, 0x4f, 0x64, 0xbf, 0xa6, 0x05, 0x40,
|
||||
0x6a, 0xa4, 0x50, 0x6a, 0x01, 0xc2, 0xba, 0x16, 0x40, 0x08, 0x6e, 0x1f, 0xd5, 0x01, 0x34, 0xf3,
|
||||
0x10, 0x36, 0xa2, 0x6a, 0x88, 0x95, 0x79, 0x32, 0x63, 0x24, 0xb5, 0x72, 0x2f, 0x56, 0x34, 0x74,
|
||||
0x70, 0x63, 0xd0, 0x17, 0x22, 0x7c, 0xcc, 0x4c, 0x91, 0xdb, 0xdb, 0x1c, 0xf2, 0xd8, 0xf7, 0x95,
|
||||
0x2f, 0x01, 0x07, 0x40, 0xd6, 0x79, 0x26, 0xbd, 0x67, 0xf8, 0xdf, 0xe8, 0x49, 0x70, 0x8c, 0x67,
|
||||
0x0f, 0x6b, 0xc4, 0x36, 0x36, 0x86, 0xee, 0xb9, 0x66, 0x8e, 0xc4, 0x8d, 0x61, 0xde, 0x31, 0xd2,
|
||||
0x7a, 0xa4, 0xf7, 0x87, 0x6c, 0xa8, 0xb7, 0xef, 0xd2, 0xc0, 0x86, 0xfa, 0x28, 0x45, 0xd6, 0x44,
|
||||
0x93, 0x00, 0x74, 0xcc, 0xc4, 0x62, 0xc6, 0x60, 0xd8, 0xa5, 0xea, 0xd9, 0x39, 0x4a, 0xee, 0x27,
|
||||
0xe0, 0x5f, 0x7c, 0xba, 0x53, 0xcd, 0x50, 0x48, 0x7f, 0xc2, 0x9e, 0xff, 0x0b, 0x0c, 0xf9, 0x73,
|
||||
0x04, 0x4b, 0xd2, 0x17, 0xb9, 0x99, 0x0b, 0x4a, 0x5f, 0xa2, 0x9c, 0xb6, 0xc7, 0x0d, 0x0f, 0xf3,
|
||||
0xde, 0x72, 0xb2, 0x21, 0x99, 0x5c, 0x63, 0x51, 0xba, 0x7d, 0x5a, 0x16, 0x42, 0x29, 0x44, 0x9d,
|
||||
0x0e, 0x8b, 0xce, 0x97, 0x19, 0x7d, 0xd7, 0x92, 0x82, 0xac, 0x4d, 0xa5, 0x04, 0x82, 0x32, 0xb3,
|
||||
0xd3, 0x89, 0x10, 0xf8, 0xb2, 0xa7, 0x40, 0x12, 0xde, 0x2b, 0xe7, 0xee, 0xd3, 0x08, 0x39, 0xfc,
|
||||
0x2e, 0xeb, 0xce, 0xac, 0xf6, 0x96, 0xaf, 0x02, 0x14, 0xd4, 0x35, 0x78, 0x85, 0xee, 0xa5, 0x5d,
|
||||
0x38, 0x2d, 0xa1, 0x72, 0xf4, 0xd8, 0x38, 0x11, 0xcc, 0x3a, 0x0f, 0xcb, 0x10, 0x65, 0x91, 0x0a,
|
||||
0x51, 0x96, 0xf8, 0xf9, 0x59, 0x74, 0x8e, 0x70, 0x2e, 0xad, 0x91, 0x70, 0x38, 0x12, 0x86, 0x14,
|
||||
0x10, 0x7c, 0xa0, 0xd1, 0x12, 0xf1, 0xf9, 0x5b, 0x96, 0x85, 0xab, 0x23, 0x62, 0x73, 0x3b, 0xce,
|
||||
0x28, 0xa9, 0x8d, 0x37, 0x2d, 0x25, 0x0f, 0x72, 0xd0, 0x66, 0x7d, 0x48, 0x3f, 0xd8, 0x7a, 0x45,
|
||||
0xf8, 0xfa, 0xad, 0xcd, 0xdc, 0x7a, 0x89, 0x08, 0xb5, 0xd0, 0x16, 0xa7, 0x6e, 0xa4, 0xfc, 0x27,
|
||||
0x54, 0xfe, 0x26, 0x73, 0xd5, 0x4a, 0x5a, 0xdf, 0x46, 0x3a, 0xdc, 0x45, 0x3a, 0xbb, 0x01, 0x1f,
|
||||
0x5c, 0x70, 0x23, 0xd8, 0x46, 0x4e, 0x99, 0xd9, 0x81, 0x9b, 0x8e, 0xf8, 0x26, 0x52, 0xa9, 0xda,
|
||||
0xfa, 0x06, 0x29, 0xfd, 0xb0, 0xb9, 0xac, 0x6c, 0x57, 0xda, 0x15, 0xaa, 0x3d, 0xb8, 0xf4, 0x18,
|
||||
0x3a, 0x2a, 0xed, 0x47, 0x95, 0xd6, 0xb0, 0x74, 0x72, 0xac, 0x1e, 0xb6, 0xa9, 0x5e, 0x39, 0x18,
|
||||
0x32, 0x5a, 0x6e, 0x3a, 0x78, 0xea, 0x2f, 0xae, 0x52, 0x18, 0x0e, 0x75, 0xfa, 0xaf, 0x10, 0x64,
|
||||
0x03, 0x76, 0xbf, 0xb2, 0x40, 0xfc, 0x74, 0xc3, 0x31, 0xc8, 0x2d, 0xb9, 0x8f, 0xe1, 0x2e, 0xfd,
|
||||
0xd0, 0xa5, 0x6e, 0x09, 0x3c, 0xf5, 0x9b, 0xae, 0xf0, 0x5a, 0x07, 0x9f, 0x3e, 0x25, 0x5b, 0xbe,
|
||||
0xe1, 0x77, 0x38, 0xd1, 0x23, 0x03, 0x0c, 0x0d, 0xf2, 0x1e, 0xa2, 0x40, 0x2d, 0xfb, 0x23, 0x32,
|
||||
0x32, 0x56, 0x97, 0x86, 0x50, 0xde, 0x27, 0xca, 0x91, 0x49, 0xa5, 0x76, 0x4b, 0x9c, 0x51, 0x35,
|
||||
0x1a, 0x4d, 0x40, 0xe7, 0xa7, 0x2e, 0xc2, 0x39, 0x34, 0xe5, 0x54, 0xd2, 0xb7, 0x5b, 0xbc, 0x50,
|
||||
0x13, 0x1a, 0xe2, 0x1e, 0x73, 0x85, 0x3a, 0x3c, 0x21, 0xda, 0x84, 0x06, 0x23, 0x62, 0x70, 0x48,
|
||||
0x58, 0x58, 0x1b, 0xfa, 0xfe, 0x2f, 0x89, 0x2d, 0xa0, 0x71, 0x6e, 0x09, 0x03, 0x11, 0x67, 0xd9,
|
||||
0x5c, 0xe5, 0xa5, 0x55, 0xa0, 0xa6, 0x08, 0x98, 0xc6, 0x37, 0xab, 0x8e, 0xd3, 0xe6, 0xea, 0xd6,
|
||||
0x7c, 0xa2, 0x0b, 0xd4, 0xc5, 0xd3, 0xb5, 0x88, 0xbe, 0xf4, 0x5f, 0x47, 0x4d, 0x55, 0x4a, 0x0f,
|
||||
0xf1, 0x6a, 0x82, 0x28, 0x81, 0xf7, 0xaf, 0xfb, 0xde, 0x3f, 0xe0, 0xd8, 0x4c, 0x77, 0x32, 0xe3,
|
||||
0xa7, 0xef, 0xb9, 0xf7, 0x9e, 0x70, 0x55, 0x12, 0xd3, 0x3b, 0xe5, 0xd0, 0xeb, 0x62, 0x75, 0x34,
|
||||
0xca, 0xe2, 0x26, 0x11, 0x9e, 0x58, 0xa5, 0xef, 0x6c, 0x4f, 0xd8, 0xc2, 0xcc, 0x3f, 0x70, 0xb6,
|
||||
0xd8, 0x7c, 0x52, 0x2f, 0x38, 0xf3, 0xce, 0x87, 0xa1, 0xee, 0x20, 0x9b, 0x1f, 0xaf, 0x52, 0x8e,
|
||||
0x36, 0x81, 0x56, 0xaa, 0xf4, 0xc7, 0xcd, 0xe0, 0x5a, 0x40, 0x64, 0x88, 0xa3, 0xa5, 0xe7, 0x34,
|
||||
0xa0, 0x77, 0x4b, 0x91, 0x23, 0x91, 0x05, 0xca, 0x5d, 0x53, 0xbf, 0xdd, 0x67, 0xd7, 0x65, 0xde,
|
||||
0x3f, 0xce, 0x8e, 0xea, 0x94, 0x2e, 0x52, 0x32, 0xd4, 0x4a, 0xa9, 0xdd, 0xe1, 0xe4, 0x11, 0x46,
|
||||
0xfc, 0x15, 0xb9, 0xe1, 0x55, 0x15, 0x3a, 0xff, 0x72, 0xd5, 0xf2, 0x4e, 0x69, 0xdf, 0xe4, 0x7c,
|
||||
0xfa, 0xa4, 0x4f, 0xa3, 0xa8, 0xfd, 0xce, 0x91, 0xc4, 0x9a, 0x16, 0x53, 0x2d, 0x15, 0xb5, 0x86,
|
||||
0x78, 0x36, 0xff, 0x28, 0x17, 0xf6, 0xd1, 0xa4, 0xb2, 0x2a, 0xa8, 0x90, 0x73, 0x26, 0x36, 0xe6,
|
||||
0x5c, 0x82, 0xdb, 0x87, 0x34, 0x7b, 0x22, 0xb1, 0x6b, 0x47, 0x6d, 0x97, 0xe7, 0x18, 0x41, 0xc4,
|
||||
0x58, 0x2d, 0x26, 0x96, 0x44, 0xd4, 0xd8, 0xde, 0xae, 0x2d, 0x4d, 0x73, 0xa4, 0x7e, 0xb1, 0x7b,
|
||||
0xef, 0xa9, 0x0c, 0xa0, 0x7c, 0x15, 0xe6, 0x70, 0xc8, 0xeb, 0x76, 0x92, 0x6f, 0xf3, 0xbd, 0xbb,
|
||||
0x2a, 0xf5, 0xc1, 0xa0, 0xcc, 0xc3, 0x24, 0x46, 0x3b, 0xf6, 0xe8, 0xe4, 0x1f, 0x72, 0x60, 0x14,
|
||||
0x51, 0x70, 0xb8, 0x4f, 0x05, 0x1c, 0x29, 0x25, 0x1d, 0xf7, 0xfa, 0x83, 0xed, 0xed, 0x2f, 0x9d,
|
||||
0x3c, 0xa1, 0x08, 0xb1, 0x7c, 0xd4, 0xf4, 0x93, 0xf9, 0x6b, 0x77, 0x21, 0xe8, 0x4d, 0xfd, 0xfe,
|
||||
0x6e, 0x5a, 0x4f, 0x64, 0x2b, 0xf3, 0xdb, 0x6e, 0xce, 0x81, 0xbb, 0x40, 0x8a, 0x86, 0xe7, 0xae,
|
||||
0x74, 0x9f, 0x1a, 0x92, 0xc7, 0x66, 0x6d, 0x26, 0x85, 0x55, 0xbe, 0x1b, 0x2a, 0xb7, 0xa9, 0xa2,
|
||||
0xab, 0x92, 0xf9, 0x8c, 0xe5, 0x2d, 0x77, 0xe3, 0xef, 0x5e, 0x7f, 0xf7, 0xe9, 0xd3, 0xdd, 0xf8,
|
||||
0xc5, 0xfe, 0xeb, 0xed, 0xed, 0xbb, 0xc3, 0xef, 0x06, 0x06, 0x9f, 0xcd, 0xde, 0x2c, 0x0f, 0x77,
|
||||
0x2a, 0xab, 0x3a, 0xa3, 0xc3, 0xdf, 0x21, 0x1e, 0xfc, 0x33, 0x01, 0x39, 0x46, 0x1a, 0x3b, 0x40,
|
||||
0x84, 0xb2, 0xad, 0xf6, 0xfb, 0xa7, 0x10, 0x66, 0x8f, 0xa3, 0x9c, 0x98, 0x68, 0xac, 0x00, 0xa7,
|
||||
0xe0, 0xe8, 0xda, 0xd9, 0x3d, 0xe2, 0x26, 0xc8, 0xb2, 0xe9, 0x95, 0xf2, 0x03, 0x49, 0x8b, 0xda,
|
||||
0x7b, 0xb2, 0x26, 0x3c, 0x72, 0x20, 0x47, 0xda, 0xf5, 0x0f, 0xaa, 0xd7, 0x8a, 0xac, 0x6a, 0xca,
|
||||
0x48, 0x70, 0xdd, 0x74, 0x5f, 0x13, 0xe5, 0x22, 0x82, 0x03, 0xe7, 0xda, 0xe2, 0x82, 0x37, 0xbe,
|
||||
0x04, 0xd5, 0x37, 0x1b, 0x92, 0x18, 0x21, 0x7b, 0xb6, 0x2b, 0xab, 0x38, 0xf2, 0x8b, 0x5f, 0xfe,
|
||||
0xbe, 0x3b, 0xec, 0x73, 0x7e, 0xd4, 0x2d, 0x95, 0x65, 0x79, 0x8b, 0x25, 0x01, 0xb2, 0x14, 0x9b,
|
||||
0x22, 0xbe, 0x63, 0x23, 0x7c, 0xad, 0x50, 0xfc, 0xc0, 0x39, 0x56, 0x19, 0x97, 0x39, 0x81, 0x91,
|
||||
0x6c, 0x6f, 0x22, 0xbb, 0xd9, 0xea, 0x0f, 0x65, 0x4f, 0x88, 0x59, 0x53, 0x8e, 0xb9, 0xea, 0xbe,
|
||||
0x99, 0x73, 0x5d, 0x8f, 0xeb, 0x82, 0xbc, 0xdf, 0x9a, 0x27, 0x8d, 0x78, 0xab, 0x25, 0xf8, 0x4a,
|
||||
0x5a, 0x31, 0xae, 0x57, 0xbc, 0xe2, 0x7e, 0x99, 0xf6, 0xb9, 0xca, 0xb4, 0x35, 0x5b, 0x52, 0xbd,
|
||||
0x89, 0xed, 0x81, 0x4e, 0xbe, 0x29, 0x52, 0xfb, 0x33, 0x76, 0xae, 0x3c, 0x09, 0x42, 0xfe, 0xac,
|
||||
0xc6, 0x01, 0x96, 0x98, 0x5a, 0x3b, 0xc0, 0x1f, 0xf6, 0x49, 0x26, 0x68, 0xd4, 0xb6, 0xad, 0x4c,
|
||||
0x32, 0xa6, 0xdd, 0x05, 0xdb, 0xdb, 0x76, 0xca, 0x85, 0x10, 0xf7, 0x10, 0xd1, 0x9e, 0x2e, 0x50,
|
||||
0xb6, 0x65, 0xba, 0xbd, 0xeb, 0xe6, 0x3e, 0xcb, 0x90, 0x90, 0xef, 0xf7, 0x61, 0x98, 0x11, 0x79,
|
||||
0xd4, 0xeb, 0xf5, 0x44, 0x44, 0xb3, 0x2d, 0x25, 0xc2, 0x2f, 0x39, 0xd4, 0x91, 0xb8, 0xd4, 0x10,
|
||||
0xc4, 0x43, 0xc5, 0xcd, 0xa4, 0x7a, 0xda, 0x08, 0xb6, 0xb7, 0xcb, 0x1f, 0xb9, 0x53, 0x25, 0xdb,
|
||||
0x11, 0xa9, 0x73, 0x73, 0xa7, 0x7a, 0x48, 0xf7, 0x89, 0x33, 0xe1, 0x6b, 0xe5, 0xd3, 0x27, 0x93,
|
||||
0xd4, 0x27, 0x36, 0x84, 0x4a, 0x87, 0x0f, 0x90, 0xa5, 0x68, 0xc3, 0xa2, 0x32, 0x97, 0xdf, 0x72,
|
||||
0x86, 0xad, 0xf5, 0xf1, 0x6c, 0x5d, 0xf2, 0xfa, 0x8d, 0xf9, 0xac, 0x65, 0x72, 0xf8, 0x4d, 0xd8,
|
||||
0x26, 0xb1, 0x5d, 0x3a, 0x2e, 0xf2, 0x94, 0x37, 0x53, 0xb0, 0x13, 0xe5, 0x44, 0xef, 0x0b, 0xef,
|
||||
0x36, 0x95, 0xb9, 0xbb, 0x59, 0x6b, 0x99, 0x42, 0xab, 0x9a, 0xde, 0x51, 0x63, 0x38, 0xee, 0x9b,
|
||||
0x2b, 0xea, 0xf9, 0xdf, 0x1f, 0xaf, 0xc9, 0x4d, 0x12, 0x6f, 0x63, 0xbb, 0xb8, 0x3d, 0x9e, 0xa8,
|
||||
0x77, 0x93, 0x3d, 0x55, 0xad, 0x4a, 0x25, 0xaf, 0xea, 0xfd, 0xaf, 0xc3, 0x3d, 0xc2, 0xe7, 0x51,
|
||||
0x56, 0x8c, 0xad, 0xc3, 0x3d, 0xf8, 0x61, 0xe3, 0xef, 0x55, 0xb1, 0x8c, 0xc7, 0xd6, 0x7f, 0x03,
|
||||
0x85, 0xba, 0x35, 0xc8, 0xe5, 0x89, 0x01, 0x00
|
||||
0x75, 0x2d, 0x46, 0x17, 0x3b, 0xa1, 0x4a, 0xe7, 0xa3, 0x50, 0xb2, 0xe1, 0xc4, 0xfc, 0x9a, 0x20,
|
||||
0xd9, 0x76, 0xec, 0x47, 0x1c, 0x7a, 0x0f, 0x59, 0xc6, 0xdc, 0x3a, 0x0e, 0x94, 0x3e, 0x12, 0x21,
|
||||
0x74, 0xf0, 0x1c, 0x99, 0x2f, 0xec, 0x25, 0x31, 0x2a, 0x8a, 0x90, 0x79, 0xfc, 0x6b, 0x7e, 0xb3,
|
||||
0x92, 0x81, 0xf3, 0xf8, 0x67, 0x21, 0xaa, 0x72, 0x00, 0x3d, 0x2e, 0x58, 0xd0, 0xb7, 0x2a, 0x62,
|
||||
0x5f, 0xd8, 0xbb, 0x99, 0x67, 0x09, 0xbb, 0xdb, 0xd6, 0x42, 0xe7, 0xc1, 0xcc, 0x49, 0xfa, 0x33,
|
||||
0x7f, 0xfc, 0xc0, 0x64, 0x25, 0x3b, 0xa5, 0x0b, 0xf8, 0xa7, 0x87, 0xf1, 0xd8, 0xf7, 0xd4, 0xf3,
|
||||
0x59, 0xae, 0x8d, 0x6d, 0x36, 0x4b, 0x16, 0xbd, 0x65, 0x94, 0x94, 0x0f, 0xc3, 0xc6, 0xc3, 0xe0,
|
||||
0xbe, 0x7c, 0x58, 0xd4, 0x1f, 0xc2, 0x50, 0x6b, 0xaf, 0x5f, 0x35, 0x5d, 0xe8, 0x35, 0x18, 0xf6,
|
||||
0xd8, 0x3e, 0x86, 0xaa, 0x28, 0x9b, 0x74, 0xf6, 0x90, 0x6f, 0xb1, 0x24, 0x2a, 0xa9, 0x17, 0x91,
|
||||
0x6a, 0xa0, 0xc5, 0x3e, 0x88, 0x93, 0x0e, 0xb0, 0x75, 0x1e, 0x2c, 0x82, 0x92, 0x73, 0x9c, 0x5d,
|
||||
0xe7, 0xa1, 0xf0, 0x73, 0xc1, 0xab, 0xac, 0xf3, 0x6e, 0x77, 0xad, 0xdb, 0x0c, 0x15, 0x42, 0xaa,
|
||||
0x92, 0x54, 0xdb, 0x59, 0x32, 0xe8, 0x7e, 0x82, 0xe0, 0x4d, 0xf2, 0x3c, 0xb7, 0xb8, 0xf1, 0x6b,
|
||||
0xa4, 0x54, 0x5a, 0x65, 0x06, 0x0c, 0xc7, 0x20, 0xac, 0x76, 0x77, 0x05, 0xc2, 0x62, 0x09, 0x89,
|
||||
0x1b, 0xd5, 0xa4, 0x0f, 0xdc, 0xb0, 0x90, 0x3c, 0xc4, 0xbe, 0xfa, 0x01, 0xa9, 0x43, 0x50, 0xfd,
|
||||
0xea, 0x73, 0x9c, 0x0d, 0xf5, 0x6b, 0x70, 0x5e, 0xdd, 0x65, 0x51, 0x55, 0xbc, 0x7f, 0x8e, 0xdc,
|
||||
0xf4, 0x55, 0x1b, 0xa5, 0x04, 0x22, 0xd0, 0x8a, 0x84, 0xf4, 0x61, 0xc5, 0xd2, 0x07, 0x55, 0xda,
|
||||
0xd6, 0xda, 0x78, 0x3c, 0x38, 0xd8, 0x66, 0x81, 0x90, 0x9b, 0x3e, 0x42, 0x09, 0x42, 0x1e, 0x61,
|
||||
0x77, 0xe3, 0xae, 0xed, 0xda, 0xdd, 0x80, 0x3f, 0x57, 0x30, 0x12, 0xab, 0x5a, 0x14, 0x61, 0x21,
|
||||
0xa9, 0x85, 0x8a, 0x46, 0x8f, 0x58, 0xd9, 0x54, 0xc6, 0x2d, 0x40, 0x60, 0xc7, 0x32, 0x28, 0x68,
|
||||
0xf3, 0xde, 0x97, 0xb0, 0x21, 0xdb, 0x41, 0xe5, 0x73, 0x77, 0x63, 0x2d, 0x82, 0xf4, 0x7b, 0xb7,
|
||||
0x9d, 0x36, 0x28, 0x6b, 0x44, 0xf7, 0x46, 0x64, 0xc9, 0x84, 0x78, 0xb1, 0x58, 0x0f, 0x3c, 0x99,
|
||||
0xf4, 0x16, 0xf7, 0xae, 0x81, 0x57, 0x35, 0xd9, 0xba, 0xdb, 0x70, 0xe3, 0x75, 0x09, 0x4d, 0x68,
|
||||
0x82, 0xc8, 0x2a, 0x58, 0x01, 0xfb, 0x4d, 0x03, 0x78, 0xe9, 0x23, 0x91, 0x46, 0xcc, 0xcf, 0xf4,
|
||||
0x9f, 0x0e, 0x5e, 0x7b, 0xb6, 0x1e, 0xd8, 0xb2, 0x8c, 0x61, 0xa3, 0xf9, 0x86, 0x7c, 0xfa, 0xd4,
|
||||
0xd1, 0x7e, 0xe9, 0x7e, 0xcf, 0xa6, 0xa3, 0x8b, 0xbb, 0x1f, 0xee, 0x3b, 0xea, 0x22, 0x12, 0xf9,
|
||||
0xc9, 0xfc, 0x8d, 0xea, 0x8b, 0x4e, 0x31, 0x91, 0x1a, 0x8c, 0x3c, 0xb2, 0x87, 0x61, 0xf9, 0x03,
|
||||
0x24, 0x2c, 0x21, 0xd9, 0xf2, 0x11, 0xa4, 0x6e, 0xf4, 0x34, 0x4b, 0x73, 0x58, 0xa9, 0x40, 0xbb,
|
||||
0xc1, 0x21, 0x35, 0x88, 0x19, 0xf6, 0x73, 0x17, 0xbe, 0xca, 0xb7, 0xfe, 0x00, 0x61, 0x56, 0x69,
|
||||
0x44, 0xba, 0x07, 0x31, 0xe6, 0xd0, 0x4b, 0xd2, 0xbb, 0x8e, 0x03, 0x33, 0x5e, 0xb8, 0x17, 0xd7,
|
||||
0x0c, 0xd3, 0x21, 0xc7, 0x16, 0x1a, 0x96, 0xb8, 0x54, 0x9e, 0x04, 0x2e, 0x62, 0xa3, 0x84, 0x88,
|
||||
0x45, 0x09, 0x77, 0x6b, 0x48, 0x63, 0x76, 0x21, 0x13, 0xa2, 0x8e, 0x11, 0x93, 0x23, 0x12, 0x6a,
|
||||
0x2d, 0x1e, 0xda, 0xc8, 0x9a, 0x5d, 0x01, 0xca, 0x0a, 0xff, 0xb7, 0x0f, 0x3f, 0xee, 0xbe, 0xb2,
|
||||
0xd7, 0x2e, 0x62, 0x7f, 0x0f, 0xd3, 0x2f, 0x70, 0x06, 0x82, 0x86, 0x05, 0xac, 0x8d, 0xee, 0x85,
|
||||
0xae, 0xad, 0xb7, 0xa3, 0x6f, 0x85, 0x58, 0xd6, 0x26, 0x64, 0x3c, 0x73, 0xb7, 0xbd, 0xef, 0x3c,
|
||||
0x44, 0x36, 0x14, 0x78, 0xea, 0x66, 0x36, 0x0b, 0xf3, 0xdc, 0x01, 0x65, 0x21, 0xe5, 0x98, 0x92,
|
||||
0xd6, 0x09, 0x45, 0x78, 0x83, 0x89, 0xfc, 0x3b, 0x0c, 0x19, 0x55, 0x69, 0x77, 0x51, 0x51, 0x06,
|
||||
0x5f, 0xd6, 0xf4, 0x4a, 0xef, 0x53, 0x4b, 0x61, 0x4c, 0xa9, 0x4a, 0xaa, 0x82, 0x23, 0xf4, 0x1d,
|
||||
0xbe, 0xf2, 0x3a, 0xa2, 0x2f, 0x47, 0xe8, 0x34, 0xd9, 0xbb, 0x9c, 0xdd, 0x10, 0xe4, 0xf7, 0x4a,
|
||||
0xfb, 0x59, 0x25, 0xbc, 0x97, 0x0f, 0x84, 0xb0, 0xc8, 0x83, 0xa8, 0xa7, 0xd2, 0x5f, 0x71, 0x5a,
|
||||
0x4d, 0x6b, 0x51, 0x9a, 0xaa, 0x6e, 0x19, 0xe2, 0xa2, 0x3e, 0xcb, 0x96, 0x60, 0x9c, 0x1d, 0x26,
|
||||
0xe9, 0xcd, 0xe5, 0x95, 0x95, 0x67, 0xc1, 0x2c, 0x84, 0x9f, 0x61, 0x0e, 0x2f, 0x4f, 0xe1, 0x36,
|
||||
0x50, 0x7b, 0x85, 0x05, 0x4f, 0x1f, 0xae, 0x42, 0x75, 0xba, 0xc2, 0x79, 0xe9, 0x99, 0x99, 0x86,
|
||||
0x39, 0x77, 0x1a, 0xde, 0x83, 0x4a, 0x32, 0x5f, 0x7b, 0x8d, 0xd7, 0xde, 0x68, 0x23, 0xb1, 0x78,
|
||||
0xd8, 0x74, 0x7d, 0xe7, 0x56, 0x3a, 0xa3, 0xcb, 0x10, 0x9a, 0xc7, 0xb5, 0xb6, 0x56, 0xbc, 0x77,
|
||||
0x44, 0xc1, 0xc8, 0xf9, 0x75, 0xed, 0x21, 0xc8, 0x19, 0x76, 0x6a, 0x30, 0x82, 0x89, 0x88, 0xf5,
|
||||
0x12, 0x8e, 0x0b, 0xfa, 0xeb, 0xcb, 0xac, 0xf8, 0x48, 0x63, 0xcc, 0xb3, 0x34, 0x41, 0x66, 0x41,
|
||||
0x0e, 0x4e, 0xf2, 0xf9, 0x9a, 0x38, 0xd5, 0xbc, 0x11, 0x5d, 0x50, 0xc4, 0x0d, 0x01, 0x93, 0x58,
|
||||
0x2a, 0x99, 0x1e, 0xd2, 0x64, 0x28, 0x82, 0xf8, 0xe2, 0x13, 0xaa, 0xa2, 0xea, 0xf2, 0xac, 0x70,
|
||||
0x6d, 0xdf, 0xfb, 0xb6, 0x79, 0xd1, 0x22, 0x50, 0x8a, 0x8e, 0xa7, 0x38, 0x36, 0xf0, 0xef, 0xa7,
|
||||
0x8d, 0x0e, 0xdf, 0xc7, 0x46, 0xb0, 0x83, 0x0e, 0xc7, 0x0a, 0xa6, 0x0f, 0x67, 0x72, 0xc1, 0x1e,
|
||||
0x69, 0x32, 0x78, 0x45, 0xcf, 0xfa, 0x27, 0x1c, 0x6d, 0x45, 0xf0, 0x03, 0x76, 0x74, 0x65, 0x28,
|
||||
0xfc, 0xfa, 0x81, 0xc9, 0x94, 0xb1, 0x37, 0xb1, 0xd3, 0x84, 0x0e, 0x2b, 0xcc, 0xf1, 0xd6, 0x5c,
|
||||
0x0a, 0x62, 0x85, 0x0a, 0x6f, 0x39, 0xd2, 0x79, 0xb0, 0x60, 0xd6, 0x9c, 0x1f, 0x10, 0x91, 0xb3,
|
||||
0x86, 0xdd, 0x0f, 0x0b, 0x30, 0x2f, 0x86, 0xb6, 0xe8, 0x65, 0x1e, 0x72, 0x3f, 0x30, 0xb1, 0x86,
|
||||
0x12, 0xd8, 0x08, 0x08, 0x93, 0xc4, 0x43, 0x2c, 0x04, 0x0d, 0x6a, 0x5d, 0x0b, 0x73, 0x2a, 0xa6,
|
||||
0x00, 0x06, 0xd8, 0x9c, 0x44, 0x15, 0xcc, 0x58, 0x7d, 0x23, 0x9e, 0xf6, 0x17, 0xd6, 0x38, 0xf3,
|
||||
0x0c, 0xe0, 0xdc, 0xcb, 0xfe, 0xb6, 0x49, 0x58, 0xdc, 0xa5, 0xab, 0x6b, 0x31, 0x23, 0x42, 0x5a,
|
||||
0x16, 0xea, 0x03, 0x52, 0xd9, 0x83, 0x97, 0xc8, 0xcd, 0x1e, 0x8d, 0xfe, 0x03, 0xbe, 0x8b, 0x99,
|
||||
0xb3, 0x4f, 0xef, 0xd3, 0xed, 0x58, 0x71, 0x9a, 0x5c, 0x52, 0x25, 0xb4, 0xd6, 0xb3, 0x55, 0xc8,
|
||||
0xa2, 0x07, 0x90, 0x69, 0xc3, 0x07, 0xd0, 0x69, 0x43, 0x35, 0xae, 0xf5, 0x7a, 0xa4, 0x39, 0x78,
|
||||
0x30, 0x7a, 0x65, 0x62, 0x6e, 0x05, 0x77, 0x8f, 0x72, 0xf0, 0x8d, 0xbd, 0x6c, 0xac, 0x01, 0x7c,
|
||||
0x4e, 0x6e, 0x21, 0x20, 0x21, 0x5a, 0x88, 0xc3, 0x3c, 0xe3, 0x53, 0x12, 0xe9, 0xf2, 0x51, 0x83,
|
||||
0xca, 0x46, 0x95, 0x7a, 0xa0, 0x50, 0x31, 0xd2, 0x47, 0x54, 0xdf, 0x65, 0x6b, 0xa3, 0x46, 0xe3,
|
||||
0xab, 0x99, 0x68, 0x12, 0x49, 0x56, 0xa7, 0x88, 0xd7, 0x3b, 0x8d, 0x83, 0xe4, 0xda, 0x94, 0x55,
|
||||
0xd4, 0x05, 0x20, 0x18, 0x81, 0x26, 0xa5, 0x10, 0x21, 0x78, 0xea, 0x93, 0x63, 0x67, 0x11, 0x4c,
|
||||
0x8c, 0xe5, 0x13, 0x2a, 0xc4, 0x8e, 0x14, 0x56, 0xb8, 0x1d, 0x15, 0xcf, 0x5a, 0xfc, 0x25, 0x2e,
|
||||
0xb5, 0xf4, 0x2b, 0x52, 0xd1, 0xea, 0xe0, 0x30, 0xd4, 0x64, 0x94, 0x44, 0xfd, 0x67, 0xb1, 0x47,
|
||||
0xfa, 0x1c, 0x8e, 0x6b, 0x53, 0x10, 0x8d, 0x54, 0x93, 0x68, 0x9c, 0x30, 0x69, 0x55, 0x20, 0x6a,
|
||||
0xaa, 0xd1, 0xcb, 0xf1, 0x75, 0xca, 0x10, 0xdc, 0xf2, 0x8b, 0x1c, 0xbe, 0x9a, 0x9c, 0xf0, 0x3a,
|
||||
0x32, 0x04, 0x36, 0xfa, 0x04, 0xb8, 0xda, 0x67, 0xcf, 0x40, 0x09, 0x80, 0xf4, 0x59, 0xc8, 0x96,
|
||||
0xda, 0xa6, 0xb1, 0x0c, 0xae, 0x41, 0x92, 0x97, 0x58, 0x89, 0x2d, 0x63, 0x0c, 0x6b, 0x29, 0xef,
|
||||
0x11, 0x81, 0xb3, 0x5e, 0x71, 0xb7, 0x5f, 0xc9, 0x96, 0xdd, 0xbe, 0x47, 0xb4, 0x48, 0x5d, 0xbc,
|
||||
0xfc, 0x74, 0x03, 0xb9, 0xde, 0xc0, 0x90, 0x78, 0xf8, 0xe2, 0x50, 0x99, 0x8f, 0x72, 0xfc, 0x0c,
|
||||
0x99, 0xe5, 0x28, 0xdf, 0x60, 0xbc, 0xdf, 0x30, 0x5a, 0x2e, 0xad, 0x94, 0xbf, 0xcc, 0x26, 0x59,
|
||||
0x1f, 0xdd, 0x67, 0x98, 0x27, 0xd7, 0x2c, 0x92, 0xdf, 0x13, 0xf1, 0x27, 0xad, 0xc5, 0xac, 0x5a,
|
||||
0x9b, 0xff, 0xff, 0xd9, 0x27, 0x1b, 0xd3, 0xfb, 0x32, 0x53, 0xe5, 0x70, 0x93, 0x61, 0xa8, 0xd1,
|
||||
0xf6, 0x17, 0x5a, 0xaa, 0x1a, 0x6d, 0x7c, 0xb9, 0xe9, 0x72, 0x58, 0x33, 0x5a, 0x7e, 0xb2, 0xe6,
|
||||
0x97, 0x4d, 0x68, 0x93, 0xbd, 0x32, 0xfe, 0xed, 0xe6, 0xba, 0xd5, 0xb2, 0x09, 0x56, 0x2d, 0x06,
|
||||
0xcc, 0x66, 0x5f, 0x23, 0xcd, 0x14, 0x71, 0xf4, 0xa4, 0x61, 0xf3, 0x46, 0xcb, 0xdb, 0x4d, 0x0b,
|
||||
0xcb, 0x16, 0xb8, 0xda, 0xaa, 0x84, 0x6b, 0x56, 0x1e, 0x69, 0x36, 0xb9, 0x5a, 0x2b, 0x33, 0x9a,
|
||||
0xf8, 0xd3, 0x71, 0x2d, 0xb4, 0x01, 0xdb, 0xe3, 0x23, 0x18, 0x83, 0xc5, 0xa5, 0x89, 0x5b, 0xc3,
|
||||
0x7f, 0x41, 0x2a, 0x65, 0x47, 0x1b, 0x0d, 0x3c, 0x73, 0x9d, 0xe5, 0x2b, 0x1b, 0x7e, 0x78, 0xc4,
|
||||
0x20, 0xb4, 0x7d, 0x84, 0xec, 0x43, 0xbf, 0x1b, 0x69, 0xe3, 0x2c, 0x11, 0x6a, 0xd3, 0xde, 0x9c,
|
||||
0xab, 0xd2, 0x37, 0xb1, 0xde, 0xfd, 0x57, 0x01, 0xaf, 0xf7, 0x9b, 0xf9, 0x5c, 0xa1, 0x87, 0x6a,
|
||||
0x42, 0x84, 0x14, 0x76, 0x4c, 0x24, 0x7d, 0x52, 0x19, 0x41, 0x5e, 0x7c, 0x0e, 0x22, 0x63, 0x8f,
|
||||
0xef, 0xe2, 0xfe, 0x73, 0x9c, 0x2b, 0x42, 0x22, 0xf9, 0x94, 0xeb, 0xf6, 0xb3, 0x3d, 0x2c, 0x6a,
|
||||
0x3b, 0x5a, 0x85, 0x27, 0xb0, 0x58, 0x35, 0x3f, 0x7c, 0x04, 0xfb, 0xe6, 0xc6, 0xa0, 0xab, 0x31,
|
||||
0x69, 0x43, 0x2a, 0x03, 0xf2, 0xac, 0xb5, 0x59, 0xfd, 0x11, 0xb7, 0x4d, 0x6a, 0xaf, 0x04, 0x07,
|
||||
0x13, 0x54, 0xc7, 0x1d, 0xe2, 0xef, 0x88, 0x45, 0x09, 0x99, 0xcc, 0xa7, 0x3b, 0x16, 0xb4, 0x9c,
|
||||
0x36, 0x4c, 0xb1, 0xf4, 0x4e, 0xf9, 0xf2, 0x13, 0xe6, 0xd1, 0x62, 0x99, 0xec, 0x5f, 0xca, 0x20,
|
||||
0x30, 0xc4, 0x5b, 0x5d, 0x59, 0x8a, 0xd1, 0xfe, 0x8d, 0x58, 0x0b, 0x29, 0xae, 0x93, 0x65, 0x6c,
|
||||
0x33, 0xb0, 0xd9, 0x7c, 0x9a, 0x27, 0x34, 0xcb, 0x8b, 0x4b, 0xc3, 0x35, 0x8c, 0x7e, 0x1e, 0xe5,
|
||||
0xd2, 0x9f, 0x5e, 0xf5, 0x48, 0xad, 0x2b, 0x0b, 0x6a, 0x36, 0x9f, 0x7e, 0x9e, 0xf1, 0xb4, 0xb2,
|
||||
0x90, 0x68, 0x6e, 0x56, 0x96, 0x0e, 0xf4, 0xd8, 0x00, 0x03, 0x9e, 0xdd, 0x9b, 0x93, 0x63, 0xba,
|
||||
0x23, 0x38, 0xec, 0x90, 0x72, 0xc5, 0x2a, 0x23, 0xd4, 0x98, 0x08, 0x56, 0x7b, 0x37, 0xc8, 0x22,
|
||||
0x23, 0x6c, 0x8d, 0x3a, 0x87, 0xf5, 0xfe, 0xfa, 0x7a, 0x7f, 0xfd, 0x8d, 0x7e, 0x77, 0x86, 0x31,
|
||||
0xfa, 0xb1, 0xf0, 0x85, 0xb5, 0xa6, 0x2b, 0x95, 0x49, 0xe2, 0x09, 0x5f, 0x3b, 0x11, 0x42, 0x6b,
|
||||
0xca, 0x0b, 0x2a, 0xd7, 0xeb, 0x4b, 0xbd, 0xe8, 0x9e, 0x1a, 0xdb, 0x29, 0xc0, 0x4a, 0xdd, 0xf0,
|
||||
0x53, 0x48, 0x06, 0x9e, 0x35, 0xb8, 0xfc, 0x2f, 0x18, 0x5c, 0xdb, 0x02, 0xd3, 0xe9, 0xe3, 0x11,
|
||||
0x11, 0xa7, 0x73, 0xfc, 0xbd, 0xd5, 0x7a, 0x2b, 0xea, 0x4b, 0x34, 0xaf, 0x5f, 0x82, 0xe5, 0x55,
|
||||
0x55, 0x45, 0x27, 0x93, 0x10, 0x88, 0x6b, 0x71, 0xf0, 0xc2, 0xe3, 0x6b, 0xb2, 0x2f, 0x0f, 0xa7,
|
||||
0x80, 0xca, 0x70, 0xd8, 0x8c, 0x91, 0xb6, 0x1e, 0x6f, 0x18, 0x1d, 0x66, 0xf0, 0x34, 0xc2, 0x87,
|
||||
0x3c, 0xe1, 0x44, 0xc5, 0x92, 0x78, 0x1c, 0x95, 0xaa, 0xab, 0x4b, 0x9e, 0x10, 0x9e, 0xbd, 0x38,
|
||||
0x42, 0x39, 0x68, 0x9c, 0x4a, 0x30, 0x61, 0x57, 0x66, 0xd1, 0xe5, 0x11, 0xde, 0x79, 0xc6, 0x58,
|
||||
0xe6, 0x61, 0x7c, 0xd2, 0xd9, 0xe9, 0x86, 0xdd, 0x9d, 0x27, 0xc7, 0xa2, 0x1c, 0x45, 0xbe, 0x97,
|
||||
0xe1, 0x44, 0xb8, 0xdf, 0x2a, 0xf4, 0xd2, 0x70, 0xe7, 0xb9, 0x77, 0xdd, 0xc9, 0x86, 0xcb, 0x6e,
|
||||
0x67, 0xbd, 0xe1, 0x5c, 0x21, 0xcc, 0x9b, 0x42, 0x12, 0x53, 0xe1, 0x79, 0x69, 0xcd, 0xb4, 0x9d,
|
||||
0xc6, 0x73, 0x5b, 0x83, 0x19, 0x35, 0x7d, 0x13, 0x4b, 0x12, 0xc8, 0x60, 0xa2, 0x2a, 0x3a, 0x14,
|
||||
0x5a, 0xb9, 0xa8, 0xdd, 0x44, 0xfa, 0x65, 0x99, 0x35, 0xae, 0xca, 0xf6, 0xe8, 0x23, 0xe3, 0xc7,
|
||||
0x88, 0xf3, 0xaf, 0x1f, 0xc4, 0x0d, 0xe7, 0xa9, 0x48, 0x21, 0xf2, 0xfe, 0x6e, 0x6a, 0x83, 0x33,
|
||||
0x0f, 0xf1, 0x87, 0x4b, 0xfb, 0x7b, 0x61, 0xf6, 0xa0, 0x1a, 0xd2, 0xad, 0x1f, 0xaa, 0x38, 0x17,
|
||||
0x5a, 0x8c, 0x0b, 0xa7, 0x76, 0xeb, 0x3f, 0x31, 0x93, 0xcf, 0xbb, 0xf4, 0xcb, 0xfd, 0x7a, 0xde,
|
||||
0xb5, 0x7f, 0xc4, 0xa1, 0xa1, 0xeb, 0xf0, 0x51, 0xbb, 0xf8, 0x05, 0xfe, 0x6f, 0x89, 0x0d, 0xc8,
|
||||
0x37, 0xc5, 0x45, 0xa9, 0xef, 0x19, 0x55, 0x4f, 0xd2, 0xfe, 0x45, 0x23, 0x57, 0x49, 0x5b, 0x5e,
|
||||
0x13, 0x59, 0x7b, 0xd0, 0x56, 0x9b, 0x6b, 0x0d, 0xe5, 0x4b, 0x5a, 0x1c, 0x4d, 0xe5, 0x30, 0x5c,
|
||||
0x0e, 0x08, 0xbe, 0xdb, 0xc3, 0xb3, 0xf3, 0x75, 0xcd, 0x22, 0x59, 0xf8, 0xaf, 0xb0, 0xf1, 0x36,
|
||||
0xc8, 0x60, 0x61, 0xfa, 0x08, 0x15, 0xe9, 0x30, 0x47, 0xbe, 0x54, 0x50, 0x9f, 0x95, 0xc8, 0xa3,
|
||||
0xa8, 0x65, 0xb7, 0x11, 0xae, 0x57, 0x61, 0x2d, 0x70, 0x30, 0x3a, 0x62, 0x33, 0x6b, 0x48, 0xfa,
|
||||
0x87, 0x86, 0x95, 0x50, 0xa8, 0x2d, 0x44, 0x5d, 0x88, 0x24, 0xc9, 0x5f, 0x73, 0x05, 0xe5, 0x8b,
|
||||
0x45, 0xc9, 0x6c, 0xe6, 0x4f, 0x1a, 0x53, 0x25, 0x4f, 0x19, 0x53, 0x81, 0x6d, 0xf6, 0xb6, 0xfc,
|
||||
0x44, 0x19, 0x3d, 0x69, 0x03, 0x4e, 0x86, 0x85, 0x2b, 0x5c, 0x17, 0x73, 0x17, 0xae, 0x8d, 0xc3,
|
||||
0x06, 0x8f, 0x90, 0x13, 0x8f, 0xd0, 0x4d, 0xd6, 0xeb, 0x51, 0xcd, 0xda, 0x4b, 0x33, 0xa3, 0x8a,
|
||||
0x9f, 0x61, 0x46, 0x15, 0x3c, 0xc3, 0x8c, 0x2a, 0xe5, 0x0d, 0xa1, 0xd7, 0xfc, 0xd8, 0x15, 0xdf,
|
||||
0xe9, 0xb1, 0x1f, 0xac, 0xf5, 0xc5, 0x4e, 0x79, 0x0d, 0x59, 0x3c, 0x3a, 0x57, 0xbb, 0xa1, 0x69,
|
||||
0xac, 0xcb, 0x0d, 0xaa, 0x1c, 0x8e, 0x26, 0x9a, 0x18, 0x15, 0x11, 0xff, 0x92, 0x50, 0x04, 0x25,
|
||||
0xe4, 0xc8, 0x7f, 0xcb, 0x9b, 0xb8, 0x88, 0x88, 0x40, 0xab, 0x5c, 0xa6, 0xe8, 0x89, 0x8c, 0xb6,
|
||||
0x44, 0x80, 0xb6, 0x85, 0x6c, 0x13, 0xda, 0x71, 0x15, 0x69, 0xc4, 0x44, 0xcb, 0xbb, 0xbb, 0xee,
|
||||
0x26, 0x28, 0xc0, 0x42, 0x7a, 0x62, 0xbb, 0xcd, 0xfd, 0x86, 0xc7, 0xdc, 0x66, 0xe8, 0x41, 0xec,
|
||||
0x69, 0x7d, 0x71, 0xe8, 0xf7, 0xa3, 0xd0, 0xf3, 0x73, 0xf4, 0x48, 0x63, 0xcb, 0xc8, 0x68, 0x6b,
|
||||
0x19, 0x3d, 0x05, 0x88, 0xf0, 0x32, 0xdf, 0xdc, 0x5c, 0x9a, 0x0c, 0xb7, 0x94, 0xf3, 0x7a, 0x78,
|
||||
0xde, 0xde, 0x02, 0xbc, 0xc5, 0x37, 0xb7, 0x40, 0xd4, 0xd1, 0xb0, 0x15, 0x06, 0xd8, 0x45, 0xac,
|
||||
0xb4, 0x74, 0x6c, 0x34, 0x5c, 0x85, 0x6c, 0x13, 0x39, 0x8d, 0x91, 0x07, 0xba, 0x02, 0xa6, 0x7a,
|
||||
0x76, 0xa1, 0x9d, 0xaf, 0x84, 0x7e, 0xdc, 0xaa, 0x5b, 0x67, 0x0c, 0xe5, 0xe4, 0x77, 0x54, 0x57,
|
||||
0xc3, 0xfa, 0xab, 0x17, 0x9b, 0x5e, 0x3d, 0xd3, 0xd9, 0xff, 0xf3, 0x6a, 0x1d, 0xfd, 0x2d, 0xa5,
|
||||
0x46, 0x6e, 0xe4, 0x38, 0x52, 0x4d, 0xe9, 0x06, 0x1d, 0x05, 0xec, 0x0a, 0x1e, 0xb5, 0x8c, 0xd9,
|
||||
0x38, 0xa2, 0x86, 0x49, 0x47, 0xf8, 0x84, 0x8d, 0x4b, 0x0b, 0x68, 0x2e, 0xee, 0x87, 0x5a, 0xc8,
|
||||
0x5e, 0x5e, 0xe8, 0xba, 0x64, 0xbe, 0xf2, 0xa6, 0xf8, 0xcc, 0x35, 0x37, 0x1d, 0x1f, 0x5a, 0xed,
|
||||
0x8c, 0x9e, 0x5e, 0xff, 0x67, 0x35, 0xa3, 0xf6, 0x82, 0xe8, 0x80, 0x67, 0xed, 0x43, 0xcd, 0x25,
|
||||
0xe3, 0x4f, 0x6e, 0x47, 0x8b, 0x83, 0xc7, 0x9f, 0xdc, 0x15, 0x9a, 0xd8, 0x30, 0xdc, 0xb4, 0x19,
|
||||
0x38, 0x50, 0xa5, 0x4a, 0xa6, 0x71, 0x7e, 0x9a, 0xc6, 0x1d, 0xce, 0x5f, 0xac, 0xa9, 0xc1, 0xb1,
|
||||
0x86, 0x0a, 0xbc, 0xd3, 0x76, 0xa8, 0xf3, 0xfb, 0xd6, 0xe1, 0x18, 0x3a, 0xf3, 0x8d, 0x60, 0x56,
|
||||
0xea, 0xce, 0x5b, 0x9b, 0x8e, 0xda, 0x9b, 0x6e, 0x28, 0xdc, 0x37, 0x36, 0xff, 0x2e, 0x6d, 0xe2,
|
||||
0x32, 0xa4, 0x21, 0x0c, 0xd7, 0x1b, 0xf5, 0x51, 0x47, 0xff, 0xac, 0x96, 0x3a, 0x8b, 0x87, 0xbb,
|
||||
0xfd, 0xf5, 0x68, 0x83, 0x01, 0xcb, 0xf6, 0x76, 0xa7, 0x23, 0x2a, 0x79, 0x2e, 0xac, 0x4e, 0x86,
|
||||
0x0f, 0xc4, 0x73, 0xd4, 0x06, 0xac, 0x9b, 0xb5, 0x38, 0x08, 0x9c, 0xd5, 0x7c, 0x1e, 0x56, 0xcf,
|
||||
0xa1, 0xca, 0x1e, 0xb6, 0x6e, 0x96, 0x36, 0x53, 0xe7, 0x33, 0x76, 0xf6, 0x59, 0x5b, 0x2b, 0x23,
|
||||
0xe2, 0x55, 0x04, 0x53, 0x96, 0xd3, 0x02, 0x8d, 0xb4, 0xeb, 0xf2, 0x9d, 0x8c, 0x75, 0x9b, 0xa9,
|
||||
0xb8, 0xca, 0x4a, 0xf2, 0x22, 0xe3, 0xf6, 0x70, 0xc8, 0x1e, 0xb7, 0x4e, 0x30, 0x35, 0xba, 0x62,
|
||||
0x66, 0x89, 0xba, 0xe9, 0x6c, 0x75, 0xb2, 0xe3, 0x1a, 0x1d, 0x50, 0x8b, 0x26, 0x8d, 0xfc, 0x1d,
|
||||
0xd9, 0xf1, 0x61, 0x1f, 0xb6, 0xb2, 0x54, 0x77, 0x13, 0xfb, 0xe6, 0x70, 0x26, 0x9e, 0x4e, 0xf6,
|
||||
0x5e, 0x23, 0x3b, 0x8b, 0xfb, 0x92, 0x68, 0xe2, 0xb7, 0xdf, 0x6b, 0xf1, 0xa0, 0xb3, 0x63, 0xe5,
|
||||
0xa1, 0xf6, 0x50, 0x11, 0x32, 0x6d, 0xc4, 0x2a, 0x11, 0x85, 0xd1, 0x54, 0x8f, 0x73, 0x3d, 0x35,
|
||||
0x1e, 0x23, 0x87, 0x8b, 0xfe, 0x38, 0x37, 0x1f, 0x57, 0x2a, 0xf5, 0x5c, 0xab, 0x14, 0x64, 0xe5,
|
||||
0xfd, 0xc6, 0x61, 0x8d, 0x0b, 0x3d, 0x00, 0x64, 0xae, 0x42, 0x16, 0x27, 0x6c, 0x4c, 0xc4, 0x11,
|
||||
0xa2, 0x7d, 0xa2, 0xc5, 0x24, 0xbf, 0x70, 0x38, 0x50, 0x7a, 0x77, 0xd6, 0xa6, 0x3f, 0x16, 0x55,
|
||||
0x5b, 0xc5, 0xcd, 0x36, 0x92, 0x9c, 0x70, 0x94, 0x62, 0x4d, 0x60, 0x62, 0x2d, 0xa2, 0x15, 0x07,
|
||||
0xcb, 0xe7, 0xa4, 0x46, 0x11, 0x91, 0x35, 0xf7, 0xbf, 0x2c, 0x3a, 0xf6, 0x83, 0xed, 0x8c, 0x77,
|
||||
0xfb, 0x9f, 0xdd, 0xd5, 0xe9, 0xc7, 0xa4, 0x08, 0xee, 0xa5, 0xea, 0x9b, 0xb8, 0xa6, 0xd9, 0x0d,
|
||||
0x91, 0x3e, 0x4b, 0x0b, 0xd3, 0xd3, 0x3b, 0x15, 0xdd, 0x79, 0xbe, 0xaf, 0xf5, 0x28, 0x46, 0x69,
|
||||
0x3b, 0x5f, 0x3a, 0x3d, 0x19, 0xbc, 0x94, 0x95, 0xa0, 0x19, 0xc2, 0x5f, 0x4d, 0x43, 0xa2, 0xf3,
|
||||
0x89, 0xa0, 0x4b, 0xe7, 0xd1, 0xe2, 0x23, 0x80, 0x96, 0x35, 0xa9, 0x92, 0xb5, 0x76, 0xd6, 0x45,
|
||||
0x2f, 0x45, 0xb0, 0xc4, 0xa2, 0x97, 0x01, 0x1c, 0xfd, 0xec, 0x98, 0xb6, 0x92, 0x8e, 0xd1, 0x7b,
|
||||
0x69, 0x89, 0x59, 0xf5, 0xfc, 0x47, 0x5c, 0x6e, 0x56, 0x52, 0x06, 0x3a, 0x85, 0x1f, 0x5b, 0xef,
|
||||
0x8f, 0x98, 0x48, 0x68, 0x3d, 0xc0, 0xb5, 0x8c, 0xc3, 0x8c, 0x63, 0x21, 0x0e, 0x44, 0x76, 0xfc,
|
||||
0xd8, 0x89, 0xa0, 0x1e, 0xd3, 0x89, 0x08, 0x8f, 0x78, 0x96, 0x1d, 0x9f, 0xfb, 0x85, 0x6b, 0x84,
|
||||
0xf5, 0xa4, 0x22, 0x31, 0xb8, 0x66, 0x71, 0xda, 0x2c, 0xba, 0x6d, 0x16, 0x71, 0x94, 0xb2, 0xa1,
|
||||
0xd6, 0xc1, 0x03, 0x61, 0xa5, 0xf7, 0x2e, 0x42, 0x8e, 0xdb, 0x9b, 0x56, 0x0d, 0xb6, 0x11, 0xa1,
|
||||
0x8c, 0x1b, 0x9d, 0x84, 0x77, 0xf1, 0x47, 0x3e, 0xad, 0x73, 0xb5, 0x73, 0x3d, 0x7b, 0xed, 0x32,
|
||||
0x48, 0xaa, 0xd8, 0xa5, 0xdc, 0x11, 0x40, 0x94, 0x4b, 0xd9, 0x96, 0x37, 0x36, 0x9e, 0xd1, 0x22,
|
||||
0xa1, 0xcc, 0x71, 0x5a, 0x22, 0x1e, 0xeb, 0x7c, 0xad, 0x41, 0xb3, 0x9f, 0x34, 0x90, 0x75, 0x46,
|
||||
0xa5, 0x3a, 0xb6, 0x36, 0x67, 0x1b, 0x9e, 0x37, 0x5b, 0x37, 0xb8, 0x34, 0x65, 0xfe, 0x05, 0x9f,
|
||||
0x7f, 0xa4, 0xf6, 0x0d, 0x47, 0x1b, 0x53, 0xe4, 0x3c, 0xd7, 0x4d, 0x21, 0x5d, 0xb1, 0x80, 0x19,
|
||||
0xa9, 0x26, 0x73, 0x78, 0x06, 0x97, 0xae, 0x44, 0xa1, 0x63, 0xbb, 0x5a, 0xc5, 0x65, 0xb0, 0xba,
|
||||
0x84, 0xa6, 0x06, 0x29, 0x22, 0xf5, 0x72, 0xa9, 0xf8, 0x3a, 0x40, 0x8a, 0xca, 0x51, 0x21, 0x6c,
|
||||
0xcd, 0x6a, 0x6d, 0xbf, 0xd8, 0xd0, 0xb6, 0x5e, 0x57, 0x35, 0x3f, 0x10, 0xcd, 0xeb, 0x8f, 0x64,
|
||||
0x0f, 0x2f, 0x90, 0xa2, 0x52, 0xe6, 0xe6, 0x11, 0xb9, 0x4e, 0x81, 0xe5, 0x6b, 0x3d, 0x9a, 0x76,
|
||||
0x42, 0x8e, 0x6b, 0x9a, 0xb3, 0xb7, 0x99, 0xc5, 0x3d, 0x66, 0xfc, 0xbe, 0xc1, 0x86, 0xdd, 0xad,
|
||||
0xb9, 0xce, 0x0a, 0x3f, 0x2d, 0x3a, 0x3a, 0x57, 0x88, 0xbf, 0x56, 0x7a, 0x3a, 0x1f, 0x49, 0x4b,
|
||||
0x57, 0x7b, 0xc5, 0x49, 0xac, 0x71, 0x51, 0xd0, 0xf5, 0x7a, 0x45, 0xb7, 0x2b, 0xf1, 0x9e, 0xee,
|
||||
0xed, 0x90, 0xe3, 0xa6, 0xf6, 0x8c, 0x14, 0x13, 0x65, 0xe4, 0x44, 0xe9, 0x93, 0xd9, 0x7d, 0xe1,
|
||||
0x39, 0xa3, 0x79, 0xfa, 0x10, 0xf6, 0xae, 0xf4, 0x6a, 0xfb, 0x2f, 0x6b, 0xf5, 0x9c, 0x35, 0xcd,
|
||||
0x29, 0x0e, 0x3b, 0x5c, 0x18, 0x4c, 0x11, 0x36, 0xf1, 0x8a, 0x33, 0xdd, 0x5e, 0x39, 0x87, 0x68,
|
||||
0x42, 0x0c, 0x8e, 0x0a, 0xd7, 0xf5, 0xf5, 0x83, 0xd3, 0x92, 0xca, 0x66, 0xe4, 0x35, 0x4c, 0xc8,
|
||||
0x79, 0xba, 0x92, 0x7a, 0xd0, 0xdf, 0x5c, 0x5d, 0x4e, 0x5d, 0x65, 0x9f, 0xcf, 0xcb, 0xf5, 0x2b,
|
||||
0x08, 0xcf, 0xd2, 0x22, 0x75, 0x65, 0xac, 0x6a, 0xe1, 0xf6, 0x1d, 0xb7, 0x63, 0x54, 0xff, 0x1b,
|
||||
0x82, 0xdc, 0xab, 0xda, 0x97, 0xb5, 0xda, 0x83, 0x7a, 0xed, 0xb7, 0x7a, 0xed, 0x69, 0xad, 0xf6,
|
||||
0x7e, 0x63, 0xd0, 0x22, 0xa7, 0x68, 0x73, 0xd0, 0x57, 0xe1, 0xfd, 0x29, 0x1b, 0xcd, 0x8d, 0xd0,
|
||||
0x4e, 0x7e, 0x33, 0x15, 0x26, 0x74, 0x2a, 0x18, 0x66, 0x61, 0xc0, 0xc5, 0xa8, 0x60, 0xec, 0x18,
|
||||
0x76, 0x7d, 0x38, 0x90, 0x9d, 0xca, 0x9a, 0x2f, 0x1d, 0x09, 0x52, 0xd4, 0xd6, 0xac, 0x32, 0xc1,
|
||||
0xad, 0xca, 0x92, 0xc5, 0x66, 0x9b, 0x35, 0x05, 0xfc, 0xfb, 0x8e, 0x26, 0xdf, 0xa1, 0x97, 0x58,
|
||||
0xb7, 0xa3, 0x24, 0x62, 0xcf, 0x6d, 0x04, 0xfe, 0x3c, 0xfd, 0x7d, 0x82, 0x2a, 0xa4, 0x26, 0xea,
|
||||
0x5d, 0x87, 0x1f, 0x8f, 0x38, 0xdf, 0x0d, 0xec, 0xc9, 0x79, 0xfe, 0x55, 0x0f, 0x65, 0x91, 0x9e,
|
||||
0x13, 0x41, 0x1f, 0xff, 0x48, 0x9f, 0xb7, 0x96, 0xfe, 0x44, 0x5b, 0xa2, 0x97, 0x8e, 0x4b, 0x73,
|
||||
0xe7, 0x5b, 0xbe, 0x0e, 0x40, 0xf6, 0x57, 0x08, 0x74, 0x58, 0x55, 0xf5, 0x5c, 0x5a, 0xa4, 0x2a,
|
||||
0x5d, 0x41, 0xb3, 0xfa, 0x62, 0x11, 0x04, 0x48, 0x75, 0xba, 0x16, 0x7e, 0x63, 0x7a, 0xe7, 0x4e,
|
||||
0x65, 0xfb, 0x2a, 0x06, 0xe3, 0x69, 0xd0, 0x39, 0xa8, 0xcd, 0x49, 0x87, 0x4d, 0x13, 0x12, 0xa5,
|
||||
0x84, 0xa9, 0x0e, 0x71, 0xa5, 0xe0, 0xc9, 0x04, 0x2d, 0xb9, 0x08, 0xf5, 0x81, 0x4a, 0xaf, 0xe1,
|
||||
0x10, 0x0e, 0xc3, 0x05, 0x3e, 0xf2, 0xb5, 0x73, 0xb1, 0xe1, 0xb0, 0x94, 0x85, 0x86, 0xcc, 0xab,
|
||||
0x8e, 0x90, 0xfb, 0x9c, 0xa3, 0xc4, 0xcc, 0x45, 0xe6, 0xfb, 0x8f, 0x22, 0xb0, 0xed, 0xed, 0xda,
|
||||
0xb0, 0xe0, 0xaf, 0x9b, 0x84, 0x31, 0x6d, 0x60, 0x7e, 0x6b, 0xbb, 0x36, 0xfd, 0x63, 0x4f, 0xe7,
|
||||
0x47, 0x1b, 0xa9, 0x9f, 0x5c, 0x01, 0xcc, 0xee, 0x80, 0x93, 0x9a, 0x98, 0xeb, 0xdd, 0x86, 0x2e,
|
||||
0x95, 0x73, 0x7b, 0xfd, 0xfc, 0x27, 0x52, 0xde, 0x46, 0x25, 0xc3, 0xb3, 0xb3, 0x9c, 0x0e, 0x7d,
|
||||
0x4e, 0x47, 0x39, 0xa7, 0x03, 0xaa, 0x37, 0x79, 0xee, 0x9e, 0xe1, 0xff, 0xf3, 0xf5, 0x1a, 0xf3,
|
||||
0x47, 0xd1, 0xc4, 0x7c, 0x91, 0x9e, 0x3e, 0xf6, 0x2e, 0xbd, 0x38, 0x1c, 0x88, 0x17, 0xd9, 0x01,
|
||||
0xb2, 0xf6, 0xea, 0x63, 0x6f, 0xd3, 0xab, 0x9b, 0x51, 0x78, 0xf2, 0xa5, 0xfc, 0x64, 0x52, 0x71,
|
||||
0x02, 0x58, 0x97, 0xab, 0x99, 0x8e, 0xf3, 0x91, 0x86, 0xea, 0x6f, 0x3f, 0x11, 0x58, 0xca, 0x1c,
|
||||
0x5f, 0xf8, 0xdd, 0x29, 0xb3, 0x4a, 0xca, 0x54, 0x92, 0x48, 0x7b, 0xf9, 0xa6, 0x4c, 0x30, 0xb9,
|
||||
0x07, 0x1f, 0x8f, 0xbd, 0xbb, 0xe8, 0x9a, 0xb8, 0xdd, 0xb5, 0xe4, 0x20, 0x57, 0xd4, 0xaf, 0x91,
|
||||
0x89, 0x49, 0x99, 0x3a, 0x75, 0x3a, 0x57, 0xb3, 0xae, 0xdf, 0x7f, 0xe5, 0x8c, 0xf7, 0x39, 0x51,
|
||||
0x0f, 0x7a, 0x77, 0xdc, 0xab, 0xd9, 0x78, 0xa0, 0x7e, 0xee, 0x7b, 0x38, 0xab, 0x07, 0x07, 0xbe,
|
||||
0x7f, 0x35, 0xe3, 0x92, 0xae, 0xbf, 0x8f, 0x12, 0xef, 0x95, 0x56, 0x42, 0x0d, 0x28, 0x94, 0x85,
|
||||
0x94, 0x67, 0x0a, 0xd9, 0xf0, 0xde, 0xfa, 0x17, 0x57, 0x39, 0xd2, 0x36, 0x5e, 0xcd, 0xd6, 0xc8,
|
||||
0x6e, 0xea, 0x7d, 0xe3, 0x5a, 0x2f, 0xbc, 0x6f, 0xe0, 0xba, 0xe9, 0xb8, 0xaf, 0xfb, 0xd2, 0xc5,
|
||||
0x87, 0x50, 0x14, 0x47, 0x2d, 0xa8, 0x5c, 0x47, 0x92, 0xc5, 0xaf, 0xcc, 0x75, 0x09, 0xdf, 0x0e,
|
||||
0x3c, 0x37, 0xce, 0x26, 0x53, 0x33, 0x1c, 0xf1, 0xa8, 0x4c, 0xd0, 0x63, 0x74, 0x2a, 0x3c, 0xa7,
|
||||
0xdd, 0x50, 0xa7, 0x8c, 0x8f, 0xd2, 0x84, 0xa8, 0xfa, 0xa5, 0xf5, 0x6b, 0x38, 0x4d, 0xd3, 0xc2,
|
||||
0x16, 0x76, 0xb7, 0xa2, 0x67, 0x3a, 0x7c, 0x8d, 0x2c, 0x6a, 0x22, 0x65, 0xa3, 0x54, 0x39, 0xa9,
|
||||
0x41, 0x9e, 0x1a, 0xa3, 0x5c, 0x21, 0xf6, 0x93, 0x89, 0x34, 0x64, 0x1c, 0xa6, 0x91, 0x1a, 0xf5,
|
||||
0xa9, 0xf3, 0xd9, 0xe3, 0x13, 0x5d, 0x56, 0xc3, 0x3b, 0x65, 0x4f, 0x28, 0xd5, 0xbb, 0xdb, 0x68,
|
||||
0x68, 0xb1, 0xa8, 0x35, 0xc4, 0x2b, 0x57, 0x4a, 0x6a, 0x55, 0xf2, 0x1d, 0x21, 0xe7, 0x7f, 0x90,
|
||||
0x01, 0xf8, 0x84, 0xf0, 0x55, 0x19, 0x77, 0xb0, 0x40, 0x9e, 0xc8, 0x7e, 0x4d, 0x0b, 0x80, 0xc4,
|
||||
0x48, 0xa1, 0xd4, 0x02, 0x84, 0x75, 0x2d, 0x80, 0x10, 0xdc, 0x3e, 0xaa, 0x03, 0x68, 0x66, 0x21,
|
||||
0x6c, 0xc4, 0xd4, 0x10, 0x2b, 0xf3, 0x64, 0xbe, 0x48, 0x6a, 0xe5, 0x5e, 0xac, 0x68, 0xe8, 0xe0,
|
||||
0xc6, 0xa0, 0x2f, 0x44, 0xf8, 0x98, 0x79, 0x22, 0xb7, 0xb7, 0x39, 0xe0, 0xb1, 0xef, 0x2b, 0x37,
|
||||
0x01, 0x0e, 0x7f, 0xac, 0xf3, 0x4c, 0x7a, 0xcf, 0x70, 0xad, 0xd1, 0x53, 0xe0, 0x18, 0xcf, 0x1e,
|
||||
0xd6, 0x88, 0x6c, 0x6c, 0x0c, 0xdd, 0x73, 0xcd, 0x0c, 0x89, 0x1b, 0x83, 0xbc, 0x63, 0xa4, 0xf5,
|
||||
0x38, 0xef, 0x0f, 0xd9, 0x50, 0x6f, 0xdf, 0xa5, 0x81, 0x0d, 0xf5, 0x51, 0x8a, 0x9c, 0x89, 0x26,
|
||||
0x01, 0xe8, 0x98, 0x69, 0xc5, 0x8c, 0xc1, 0xb0, 0x43, 0xd5, 0xb3, 0x33, 0x94, 0xdc, 0x4f, 0xc0,
|
||||
0xbf, 0xf8, 0x74, 0xa7, 0x9a, 0x81, 0x90, 0xfe, 0x84, 0x3d, 0xff, 0x17, 0x18, 0xf2, 0xe7, 0x08,
|
||||
0x95, 0xa4, 0x2f, 0x72, 0x33, 0x13, 0x94, 0xbe, 0x44, 0x39, 0x6d, 0x8f, 0x1b, 0x1e, 0xe6, 0xbd,
|
||||
0xe5, 0x64, 0x43, 0x2a, 0xb9, 0xc6, 0xa2, 0x74, 0xfb, 0xb4, 0x2c, 0x84, 0x52, 0x88, 0x3a, 0x1d,
|
||||
0x16, 0x9d, 0x2f, 0x33, 0xfa, 0xae, 0xa5, 0x04, 0x59, 0x9b, 0x4a, 0x09, 0x84, 0x64, 0x66, 0x7f,
|
||||
0x12, 0x21, 0xf0, 0x65, 0x4f, 0x81, 0x24, 0xbc, 0x57, 0xae, 0xdd, 0xa7, 0x11, 0x32, 0xf8, 0x5d,
|
||||
0xd6, 0x5d, 0x59, 0xed, 0x2d, 0x5f, 0x85, 0x27, 0xa8, 0x6b, 0xf0, 0x0a, 0xdd, 0x47, 0xbb, 0x70,
|
||||
0x5a, 0x02, 0xe5, 0xe8, 0x91, 0x71, 0x22, 0x98, 0x75, 0x1e, 0x96, 0x01, 0xca, 0x22, 0x15, 0xa0,
|
||||
0x2c, 0xf1, 0xf3, 0xb3, 0xe8, 0x1c, 0xc1, 0x5c, 0x5a, 0xe3, 0xe0, 0x70, 0x1c, 0x0c, 0x29, 0x20,
|
||||
0xf8, 0x40, 0xa3, 0x25, 0xe2, 0xf3, 0xb7, 0x2c, 0x0b, 0x57, 0x47, 0xc4, 0xe6, 0x76, 0x9c, 0x51,
|
||||
0x52, 0x1b, 0x6f, 0x5a, 0x4a, 0x1e, 0xe4, 0xa0, 0xcd, 0xfa, 0x90, 0x7e, 0xb0, 0xf5, 0x8a, 0xf0,
|
||||
0xf4, 0x5b, 0x9b, 0x99, 0xf5, 0x12, 0x11, 0x68, 0xa1, 0x2d, 0x4a, 0xdd, 0x48, 0xf9, 0x4f, 0xa8,
|
||||
0xec, 0x4d, 0xe6, 0xaa, 0x95, 0xb4, 0xbe, 0x8d, 0x64, 0xb8, 0x8b, 0x74, 0x76, 0x03, 0x3e, 0xb8,
|
||||
0xe0, 0x46, 0xb0, 0x8d, 0x9c, 0x30, 0xb3, 0x03, 0x0f, 0x1c, 0xf1, 0x4d, 0x24, 0x52, 0xb5, 0xf5,
|
||||
0x0d, 0x52, 0xfa, 0x61, 0x73, 0x59, 0xd9, 0xae, 0xb4, 0x2b, 0x54, 0x7b, 0xf0, 0xd6, 0x31, 0x74,
|
||||
0x54, 0xda, 0x8f, 0x2a, 0xa9, 0x61, 0xe9, 0xe2, 0x58, 0x3d, 0x6c, 0x53, 0xbd, 0x72, 0x28, 0x64,
|
||||
0xb4, 0xdc, 0x74, 0xef, 0xd4, 0x5f, 0x5c, 0xa5, 0x30, 0x1c, 0xea, 0xf4, 0x5f, 0x21, 0xc4, 0x06,
|
||||
0xec, 0x7e, 0x65, 0x81, 0xf8, 0xe9, 0x86, 0x63, 0x90, 0x5b, 0x72, 0x1f, 0xc3, 0x5d, 0xfa, 0xa1,
|
||||
0x4b, 0xdd, 0x12, 0xf8, 0xe9, 0x37, 0x1d, 0xe1, 0xb5, 0x0e, 0x3e, 0x7d, 0x4a, 0xb6, 0x7c, 0xc3,
|
||||
0xa5, 0x70, 0xa2, 0xc7, 0x05, 0x18, 0x1a, 0xe4, 0x3d, 0x44, 0x81, 0x5a, 0xee, 0x47, 0xe4, 0x63,
|
||||
0xac, 0x2e, 0x0d, 0xa1, 0xbc, 0x4f, 0x94, 0x8f, 0x92, 0x4a, 0xec, 0x96, 0x38, 0xa3, 0x6a, 0x34,
|
||||
0x9a, 0x80, 0xce, 0x4f, 0x5d, 0x04, 0x73, 0x68, 0xca, 0xa9, 0xa4, 0x67, 0xb7, 0x78, 0xa1, 0x26,
|
||||
0x34, 0xc4, 0x3d, 0xe6, 0x0a, 0x75, 0x78, 0x42, 0xb4, 0x09, 0x0d, 0x46, 0x44, 0xe0, 0x90, 0xb0,
|
||||
0xb0, 0x36, 0xf4, 0xfd, 0x5f, 0x12, 0x59, 0x40, 0xe3, 0xdc, 0x12, 0x06, 0x22, 0xce, 0xb1, 0xb9,
|
||||
0xca, 0x4b, 0xab, 0x40, 0x4d, 0x11, 0x30, 0x8d, 0x6f, 0x56, 0x1d, 0xa7, 0xcd, 0x8b, 0xad, 0xf9,
|
||||
0x44, 0x17, 0xa8, 0x8b, 0xa7, 0x6b, 0x11, 0x7b, 0xe9, 0xbf, 0x8e, 0x9a, 0xaa, 0x94, 0x1e, 0xa2,
|
||||
0xd5, 0x04, 0x51, 0x02, 0xdf, 0x5f, 0xf7, 0xbd, 0x7f, 0xc0, 0x91, 0x99, 0xee, 0x64, 0xbe, 0x4f,
|
||||
0xdf, 0x73, 0xef, 0x3d, 0xe1, 0xaa, 0x24, 0xa6, 0x77, 0xca, 0x81, 0xd7, 0xc5, 0xea, 0x68, 0x94,
|
||||
0xc5, 0x4d, 0x22, 0x3c, 0xb1, 0x4a, 0xcf, 0xd9, 0x9e, 0xb0, 0x85, 0x99, 0x7f, 0xe0, 0x5c, 0xb1,
|
||||
0xf9, 0xa4, 0x5e, 0x70, 0xe6, 0x9d, 0x0f, 0x43, 0xdd, 0x3d, 0x36, 0x3f, 0x5e, 0xa5, 0x1c, 0x6b,
|
||||
0x02, 0xad, 0x54, 0xc9, 0x8f, 0x9b, 0xa1, 0xb5, 0x80, 0xc8, 0x10, 0x45, 0x4b, 0xcf, 0x68, 0x40,
|
||||
0xef, 0x96, 0x22, 0x47, 0x22, 0x0b, 0x94, 0x27, 0xa6, 0x7e, 0xbb, 0xcf, 0xae, 0xcb, 0xac, 0x7f,
|
||||
0x9c, 0x1b, 0xd5, 0x29, 0x5d, 0xa4, 0x64, 0xa0, 0x95, 0x52, 0xbb, 0xc3, 0xa9, 0x23, 0x8c, 0xe8,
|
||||
0x2b, 0x72, 0xc3, 0xab, 0x2a, 0x74, 0xfe, 0xe5, 0xaa, 0xe5, 0x9d, 0xd2, 0xbe, 0xc9, 0xf9, 0xf4,
|
||||
0x49, 0x9f, 0x46, 0x51, 0xfb, 0x9d, 0x23, 0x85, 0x35, 0x2d, 0xa6, 0x5a, 0x2a, 0x6a, 0x0d, 0xd1,
|
||||
0x6c, 0xfe, 0x51, 0x2e, 0xec, 0xa3, 0x29, 0x65, 0x55, 0x48, 0x21, 0xe7, 0x4c, 0x6c, 0xcc, 0xb9,
|
||||
0x04, 0xb7, 0x0f, 0x69, 0xf6, 0x44, 0x5a, 0xd7, 0x8e, 0xda, 0x2e, 0xcf, 0x31, 0x42, 0x88, 0xb1,
|
||||
0x5a, 0x4c, 0x2c, 0x89, 0xa8, 0xb1, 0xbd, 0x5d, 0x5b, 0x9a, 0xe6, 0x48, 0xfd, 0x62, 0xf7, 0xde,
|
||||
0x53, 0xf9, 0x3f, 0xf9, 0x2a, 0xcc, 0xe1, 0x90, 0xd7, 0xed, 0x24, 0xdf, 0xe6, 0x7b, 0x77, 0x55,
|
||||
0xe2, 0x83, 0x41, 0x99, 0x85, 0x49, 0x8c, 0x76, 0xec, 0xd1, 0xc9, 0x3f, 0xe4, 0xb0, 0x28, 0xa2,
|
||||
0xe0, 0x70, 0x9f, 0x0a, 0x38, 0x4e, 0x4a, 0x3a, 0xee, 0xf5, 0x07, 0xdb, 0xdb, 0x5f, 0x3a, 0x79,
|
||||
0x42, 0x11, 0x62, 0xf9, 0xa8, 0xe9, 0x27, 0xb3, 0xd7, 0xee, 0x42, 0xd0, 0x9b, 0xfa, 0xfd, 0xdd,
|
||||
0xb4, 0x9e, 0xc6, 0x56, 0x66, 0xb7, 0xdd, 0x9c, 0x01, 0x77, 0x81, 0x04, 0x0d, 0xcf, 0x5d, 0xe9,
|
||||
0x3e, 0x35, 0x24, 0x8f, 0xcd, 0xda, 0x4c, 0x09, 0xab, 0x7c, 0x37, 0x54, 0x66, 0x53, 0x45, 0x57,
|
||||
0x25, 0xf3, 0x19, 0xcb, 0x5b, 0xee, 0xc6, 0xdf, 0xbd, 0xfe, 0xee, 0xd3, 0xa7, 0xbb, 0xf1, 0x8b,
|
||||
0xfd, 0xd7, 0xdb, 0xdb, 0x77, 0x87, 0xdf, 0x0d, 0x0c, 0x3e, 0x9b, 0xbd, 0x59, 0x1e, 0xee, 0x54,
|
||||
0x4e, 0x75, 0x46, 0x87, 0xbf, 0x43, 0x3c, 0xf8, 0x67, 0xc2, 0x71, 0x8c, 0x34, 0x76, 0x80, 0x08,
|
||||
0x65, 0x5b, 0xed, 0xf7, 0x4f, 0x21, 0xcc, 0x1e, 0x47, 0x39, 0x31, 0xd1, 0x58, 0x01, 0x4e, 0xc0,
|
||||
0xd1, 0xb5, 0xb3, 0x7b, 0x44, 0x4d, 0x90, 0x65, 0xd3, 0x2b, 0xe5, 0x07, 0x92, 0x16, 0xb5, 0xf7,
|
||||
0x64, 0x4d, 0x78, 0xe4, 0x40, 0x8e, 0xb4, 0xeb, 0x1f, 0x54, 0xaf, 0x15, 0x59, 0xd5, 0x94, 0x91,
|
||||
0xde, 0xba, 0xe9, 0xbe, 0x26, 0xca, 0x45, 0xfc, 0x06, 0xce, 0xb4, 0xc5, 0x05, 0x6f, 0x7c, 0x09,
|
||||
0xaa, 0x6f, 0x36, 0xa4, 0x30, 0x42, 0xee, 0x6c, 0x57, 0x56, 0x71, 0xe4, 0x17, 0xbf, 0xfc, 0x7d,
|
||||
0x77, 0xd8, 0xe7, 0xec, 0xa8, 0x5b, 0x2a, 0xc7, 0xf2, 0x16, 0x4b, 0x02, 0x64, 0x29, 0x36, 0x45,
|
||||
0x7c, 0xc7, 0x46, 0xf8, 0x5a, 0xa1, 0xf8, 0x81, 0x73, 0xac, 0xf2, 0x2d, 0x73, 0xfa, 0x22, 0xd9,
|
||||
0xde, 0x44, 0x76, 0xb3, 0xd5, 0x1f, 0xca, 0x9e, 0x10, 0xb1, 0xa6, 0x1c, 0x73, 0xd5, 0x7d, 0x33,
|
||||
0xe3, 0xba, 0x1e, 0xd5, 0x05, 0x59, 0xbf, 0x35, 0x4f, 0x1a, 0xf1, 0x56, 0x4b, 0xe8, 0x95, 0xb4,
|
||||
0x62, 0x5c, 0xaf, 0x78, 0xc5, 0xfd, 0x32, 0xe9, 0x73, 0x95, 0x67, 0x6b, 0xb6, 0xa4, 0x7a, 0x13,
|
||||
0xdb, 0x03, 0x9d, 0x7c, 0x53, 0xa4, 0xf6, 0x67, 0xec, 0x5c, 0x79, 0x12, 0x84, 0xfc, 0x59, 0x8d,
|
||||
0x03, 0x2c, 0x31, 0xb5, 0x76, 0x80, 0x3f, 0xec, 0x6e, 0x4c, 0xd0, 0xa8, 0x6d, 0x5b, 0x99, 0x62,
|
||||
0x4c, 0xbb, 0x0b, 0xb6, 0xb7, 0xed, 0x94, 0x0b, 0x21, 0xee, 0x21, 0xa2, 0x3d, 0x5d, 0xa0, 0x6c,
|
||||
0xcb, 0xf4, 0x68, 0xd7, 0xcd, 0x7d, 0x96, 0x21, 0x21, 0xdf, 0xef, 0xc3, 0x30, 0x23, 0xf2, 0xa8,
|
||||
0xd7, 0xeb, 0x89, 0x78, 0x66, 0x5b, 0x4a, 0x84, 0x5f, 0x72, 0xa8, 0x23, 0x71, 0xa9, 0x21, 0x84,
|
||||
0x87, 0x8a, 0x9a, 0x49, 0xf5, 0xb4, 0x11, 0x6c, 0x6f, 0x97, 0x3f, 0x72, 0xa7, 0x4a, 0xb5, 0x23,
|
||||
0x12, 0xe7, 0xe6, 0x4e, 0xf5, 0x90, 0xee, 0x13, 0x67, 0xc2, 0xd7, 0xca, 0xa7, 0x4f, 0x26, 0xa9,
|
||||
0x4f, 0x6c, 0x08, 0x95, 0x0e, 0x1f, 0x20, 0x4b, 0xd1, 0x86, 0x45, 0x65, 0x2e, 0xbf, 0xe5, 0x0c,
|
||||
0x5b, 0xeb, 0xe3, 0xd9, 0xba, 0xe4, 0xf5, 0x1b, 0xf3, 0x59, 0xcb, 0xd4, 0xf0, 0x9b, 0xb0, 0x4d,
|
||||
0x62, 0xbb, 0x74, 0x5c, 0xe4, 0x29, 0x6f, 0x26, 0x60, 0x27, 0xca, 0x89, 0xde, 0x17, 0xde, 0x6d,
|
||||
0x2a, 0x6f, 0x77, 0xb3, 0xd6, 0x32, 0x85, 0x56, 0x35, 0xbd, 0xa3, 0xc6, 0x70, 0xdc, 0x37, 0x57,
|
||||
0xd4, 0xb3, 0xbf, 0x3f, 0x5e, 0x93, 0x9b, 0x24, 0xde, 0xc6, 0x76, 0x71, 0x7b, 0x3c, 0x51, 0xef,
|
||||
0x26, 0x7b, 0xaa, 0x5a, 0x95, 0x48, 0x5e, 0xd5, 0xfb, 0x5f, 0x87, 0x7b, 0x84, 0xcf, 0xa3, 0xac,
|
||||
0x18, 0x5b, 0x87, 0x7b, 0xf0, 0xc3, 0xc6, 0xdf, 0xab, 0x62, 0x19, 0x8f, 0xad, 0xff, 0x06, 0x9d,
|
||||
0xe0, 0x6a, 0xd1, 0xe3, 0x89, 0x01, 0x00
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
* 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;
|
||||
if (id < strip.getMaxSegments())
|
||||
@ -127,15 +127,18 @@ void deserializeSegment(JsonObject elem, byte it, bool fromPlaylist)
|
||||
|
||||
//temporary, strip object gets updated via colorUpdated()
|
||||
if (id == strip.getMainSegmentId()) {
|
||||
// it may be a good idea to also stop playlist if effect has changed
|
||||
if (!fromPlaylist && !elem["fx"].isNull()) unloadPlaylist();
|
||||
effectCurrent = elem["fx"] | effectCurrent;
|
||||
byte effectPrev = effectCurrent;
|
||||
effectCurrent = elem[F("fx")] | effectCurrent;
|
||||
if (!presetId && effectCurrent != effectPrev) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||
effectSpeed = elem[F("sx")] | effectSpeed;
|
||||
effectIntensity = elem[F("ix")] | effectIntensity;
|
||||
effectPalette = elem["pal"] | effectPalette;
|
||||
} else { //permanent
|
||||
byte fx = elem["fx"] | seg.mode;
|
||||
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
|
||||
byte fx = elem[F("fx")] | seg.mode;
|
||||
if (fx != seg.mode && fx < strip.getModeCount()) {
|
||||
strip.setMode(id, fx);
|
||||
if (!presetId) unloadPlaylist(); //stop playlist if active and FX changed manually
|
||||
}
|
||||
seg.speed = elem[F("sx")] | seg.speed;
|
||||
seg.intensity = elem[F("ix")] | seg.intensity;
|
||||
seg.palette = elem["pal"] | seg.palette;
|
||||
@ -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;
|
||||
bool stateResponse = root[F("v")] | false;
|
||||
@ -202,13 +205,16 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
||||
|
||||
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||
|
||||
int tr = root[F("transition")] | -1;
|
||||
int tr = -1;
|
||||
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;
|
||||
if (tr >= 0)
|
||||
{
|
||||
transitionDelay = tr;
|
||||
transitionDelay *= 100;
|
||||
transitionDelayTemp = transitionDelay;
|
||||
}
|
||||
}
|
||||
|
||||
tr = root[F("tt")] | -1;
|
||||
if (tr >= 0)
|
||||
@ -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
|
||||
if (timein != UINT32_MAX) {
|
||||
time_t prev = now();
|
||||
if (millis() - ntpLastSyncTime > 50000000L) {
|
||||
setTime(timein);
|
||||
if (abs(now() - prev) > 60L) {
|
||||
updateLocalTime();
|
||||
calculateSunriseAndSunset();
|
||||
}
|
||||
}
|
||||
setTimeFromAPI(timein);
|
||||
if (presetsModifiedTime == 0) presetsModifiedTime = timein;
|
||||
}
|
||||
|
||||
@ -286,24 +285,30 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
||||
{
|
||||
if (lowestActive == 99) lowestActive = s;
|
||||
if (sg.isSelected()) {
|
||||
deserializeSegment(segVar, s, fromPlaylist);
|
||||
deserializeSegment(segVar, s, presetId);
|
||||
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
|
||||
deserializeSegment(segVar, id, fromPlaylist);
|
||||
deserializeSegment(segVar, it, presetId);
|
||||
}
|
||||
} else {
|
||||
JsonArray segs = segVar.as<JsonArray>();
|
||||
for (JsonObject elem : segs)
|
||||
{
|
||||
deserializeSegment(elem, it, fromPlaylist);
|
||||
deserializeSegment(elem, it, presetId);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
if (root["nx"].is<const char*>()) {
|
||||
strncpy(cronixieDisplay, root["nx"], 6);
|
||||
}
|
||||
#endif
|
||||
|
||||
usermods.readFromJsonState(root);
|
||||
|
||||
int8_t ledmap = root[F("ledmap")] | -1;
|
||||
@ -320,7 +325,11 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
||||
deletePreset(ps);
|
||||
}
|
||||
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
|
||||
const char* httpwin = root["win"];
|
||||
@ -333,7 +342,7 @@ bool deserializeState(JsonObject root, bool fromPlaylist)
|
||||
|
||||
JsonObject playlist = root[F("playlist")];
|
||||
if (!playlist.isNull()) {
|
||||
loadPlaylist(playlist);
|
||||
loadPlaylist(playlist, presetId);
|
||||
noNotification = true; //do not notify both for this request and the first playlist entry
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,9 @@
|
||||
/*
|
||||
* Acquires time from NTP server
|
||||
*/
|
||||
//#define WLED_DEBUG_NTP
|
||||
#define NTP_SYNC_INTERVAL 42000UL //Get fresh NTP time about twice per day
|
||||
|
||||
Timezone* tz;
|
||||
|
||||
#define TZ_UTC 0
|
||||
@ -144,9 +147,28 @@ void updateTimezone() {
|
||||
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()
|
||||
{
|
||||
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WLED_CONNECTED)
|
||||
if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > (1000*NTP_SYNC_INTERVAL) && WLED_CONNECTED)
|
||||
{
|
||||
if (millis() - ntpPacketSentTime > 10000)
|
||||
{
|
||||
@ -193,35 +215,52 @@ void sendNTPPacket()
|
||||
bool checkNTPResponse()
|
||||
{
|
||||
int cb = ntpUdp.parsePacket();
|
||||
if (cb) {
|
||||
if (!cb) return false;
|
||||
|
||||
uint32_t ntpPacketReceivedTime = millis();
|
||||
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]);
|
||||
unsigned long lowWord = word(pbuf[42], pbuf[43]);
|
||||
if (highWord == 0 && lowWord == 0) return false;
|
||||
Toki::Time arrived = toki.fromNTP(pbuf + 32);
|
||||
Toki::Time departed = toki.fromNTP(pbuf + 40);
|
||||
if (departed.sec == 0) return false;
|
||||
//basic half roundtrip estimation
|
||||
uint32_t serverDelay = toki.msDifference(arrived, departed);
|
||||
uint32_t offset = (ntpPacketReceivedTime - ntpPacketSentTime - serverDelay) >> 1;
|
||||
#ifdef WLED_DEBUG_NTP
|
||||
//the time the packet departed the NTP server
|
||||
toki.printTime(departed);
|
||||
#endif
|
||||
|
||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||
toki.adjust(departed, offset);
|
||||
toki.setTime(departed, TOKI_TS_NTP);
|
||||
|
||||
DEBUG_PRINT(F("Unix time = "));
|
||||
unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
|
||||
setTime(epoch);
|
||||
DEBUG_PRINTLN(epoch);
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
#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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateLocalTime()
|
||||
{
|
||||
if (currentTimezone != tzCurrent) updateTimezone();
|
||||
unsigned long tmc = now()+ utcOffsetSecs;
|
||||
unsigned long tmc = toki.second()+ utcOffsetSecs;
|
||||
localTime = tz->toLocal(tmc);
|
||||
}
|
||||
|
||||
@ -245,13 +284,13 @@ void setCountdown()
|
||||
{
|
||||
if (currentTimezone != tzCurrent) updateTimezone();
|
||||
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
|
||||
bool checkCountdown()
|
||||
{
|
||||
unsigned long n = now();
|
||||
unsigned long n = toki.second();
|
||||
if (countdownMode) localTime = countdownTime - n + utcOffsetSecs;
|
||||
if (n > countdownTime) {
|
||||
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()
|
||||
{
|
||||
if (overlayCurrent == 3 && !cronixieInit)
|
||||
if (overlayCurrent == 3 && dP[0] == 255) //if dP[0] is 255, cronixie is not yet init'ed
|
||||
{
|
||||
setCronixie();
|
||||
strip.getSegment(0).grouping = 10; //10 LEDs per digit
|
||||
cronixieInit = true;
|
||||
} else if (cronixieInit && overlayCurrent != 3)
|
||||
} else if (dP[0] < 255 && overlayCurrent != 3)
|
||||
{
|
||||
strip.getSegment(0).grouping = 1;
|
||||
cronixieInit = false;
|
||||
dP[0] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleOverlays()
|
||||
{
|
||||
if (millis() - overlayRefreshedTime > overlayRefreshMs)
|
||||
{
|
||||
initCronixie();
|
||||
updateLocalTime();
|
||||
checkTimers();
|
||||
checkCountdown();
|
||||
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
|
||||
overlayRefreshedTime = millis();
|
||||
if (overlayCurrent == 3) {
|
||||
_overlayCronixie();//Diamex cronixie clock kit
|
||||
strip.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,15 +68,14 @@ void _overlayAnalogClock()
|
||||
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
||||
strip.setPixelColor(minutePixel, 0x00FF00);
|
||||
strip.setPixelColor(hourPixel, 0x0000FF);
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
@ -220,8 +213,6 @@ void setCronixie()
|
||||
DEBUG_PRINT("cset ");
|
||||
DEBUG_PRINTLN(cronixieDisplay);
|
||||
|
||||
overlayRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
dP[i] = 10;
|
||||
@ -241,8 +232,8 @@ void setCronixie()
|
||||
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] = 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] = 30 + getSameCodeLength('S',i,cronixieDisplay); i = i+dP[i]-30; overlayRefreshMs = 497; break;
|
||||
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; 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 '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 {
|
||||
uint8_t preset;
|
||||
uint16_t dur;
|
||||
uint16_t tr;
|
||||
uint8_t preset; //ID of the preset to apply
|
||||
uint16_t dur; //Duration of the entry (in tenths of seconds)
|
||||
uint16_t tr; //Duration of the transition TO this entry (in tenths of seconds)
|
||||
} ple;
|
||||
|
||||
bool playlistEndless = false;
|
||||
int8_t playlistRepeat = 1;
|
||||
byte playlistEndPreset = 0;
|
||||
byte playlistRepeat = 1; //how many times to repeat the playlist (0 = infinitely)
|
||||
byte playlistEndPreset = 0; //what preset to apply after playlist end (0 = stay on last preset)
|
||||
byte playlistOptions = 0; //bit 0: shuffle playlist after each iteration. bits 1-7 TBD
|
||||
|
||||
PlaylistEntry *playlistEntries = nullptr;
|
||||
byte playlistLen;
|
||||
byte playlistLen; //number of playlist entries
|
||||
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() {
|
||||
@ -42,12 +48,12 @@ void unloadPlaylist() {
|
||||
playlistEntries = nullptr;
|
||||
}
|
||||
currentPlaylist = playlistIndex = -1;
|
||||
playlistLen = playlistEntryDur = 0;
|
||||
playlistLen = playlistEntryDur = playlistOptions = 0;
|
||||
DEBUG_PRINTLN(F("Playlist unloaded."));
|
||||
}
|
||||
|
||||
|
||||
void loadPlaylist(JsonObject playlistObj) {
|
||||
void loadPlaylist(JsonObject playlistObj, byte presetId) {
|
||||
unloadPlaylist();
|
||||
|
||||
JsonArray presets = playlistObj["ps"];
|
||||
@ -68,12 +74,12 @@ void loadPlaylist(JsonObject playlistObj) {
|
||||
it = 0;
|
||||
JsonArray durations = playlistObj["dur"];
|
||||
if (durations.isNull()) {
|
||||
playlistEntries[0].dur = playlistObj["dur"] | 100;
|
||||
playlistEntries[0].dur = playlistObj["dur"] | 100; //10 seconds as fallback
|
||||
it = 1;
|
||||
} else {
|
||||
for (int dur : durations) {
|
||||
if (it >= playlistLen) break;
|
||||
playlistEntries[it].dur = (dur > 0) ? dur : presetCycleTime;
|
||||
playlistEntries[it].dur = (dur > 1) ? dur : 100;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
@ -93,12 +99,19 @@ void loadPlaylist(JsonObject playlistObj) {
|
||||
}
|
||||
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;
|
||||
shuffle = shuffle || playlistObj["r"];
|
||||
if (shuffle) playlistOptions += PL_OPTION_SHUFFLE;
|
||||
|
||||
if (playlistRepeat <= 0) playlistRepeat--; // make it endless (-2 == endless & random)
|
||||
|
||||
currentPlaylist = 0; //TODO here we need the preset ID where the playlist is saved
|
||||
currentPlaylist = presetId;
|
||||
DEBUG_PRINTLN(F("Playlist loaded."));
|
||||
}
|
||||
|
||||
@ -112,21 +125,21 @@ void handlePlaylist() {
|
||||
|
||||
++playlistIndex %= playlistLen; // -1 at 1st run (limit to playlistLen)
|
||||
|
||||
if (!playlistRepeat && !playlistIndex) { //stop if repeat == 0 and restart of playlist
|
||||
// playlist roll-over
|
||||
if (!playlistIndex) {
|
||||
if (playlistRepeat == 1) { //stop if all repetitions are done
|
||||
unloadPlaylist();
|
||||
if (playlistEndPreset) applyPreset(playlistEndPreset);
|
||||
return;
|
||||
}
|
||||
// playlist roll-over
|
||||
if (!playlistIndex) {
|
||||
// playlistRepeat < 0 => endless loop
|
||||
if (playlistRepeat > 0) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
|
||||
if (playlistRepeat < -1) shufflePlaylist(); // shuffle playlist and start over
|
||||
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;
|
||||
transitionDelayTemp = playlistEntries[playlistIndex].tr * 100;
|
||||
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
||||
applyPreset(playlistEntries[playlistIndex].preset, true);
|
||||
applyPreset(playlistEntries[playlistIndex].preset);
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,17 @@
|
||||
* 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 (fileDoc) { // from POST "/json" handler (wled_server.cpp)
|
||||
if (fileDoc) {
|
||||
errorFlag = readObjectFromFileUsingId("/presets.json", index, fileDoc) ? ERR_NONE : ERR_FS_PLOAD;
|
||||
JsonObject fdo = fileDoc->as<JsonObject>();
|
||||
if (fdo["ps"] == index) fdo.remove("ps"); //remove load request for same presets to prevent recursive crash
|
||||
#ifdef WLED_DEBUG_FS
|
||||
serializeJson(*fileDoc, Serial);
|
||||
#endif
|
||||
deserializeState(fdo, fromPlaylist);
|
||||
deserializeState(fdo, index);
|
||||
} else {
|
||||
DEBUGFS_PRINTLN(F("Make read buf"));
|
||||
DynamicJsonDocument fDoc(JSON_BUFFER_SIZE);
|
||||
@ -24,7 +24,7 @@ bool applyPreset(byte index, bool fromPlaylist)
|
||||
#ifdef WLED_DEBUG_FS
|
||||
serializeJson(fDoc, Serial);
|
||||
#endif
|
||||
deserializeState(fdo, fromPlaylist);
|
||||
deserializeState(fdo, index);
|
||||
}
|
||||
|
||||
if (!errorFlag) {
|
||||
@ -35,6 +35,7 @@ bool applyPreset(byte index, bool fromPlaylist)
|
||||
return false;
|
||||
}
|
||||
|
||||
//persist=false is not currently honored
|
||||
void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
||||
{
|
||||
if (index == 0 || index > 250) return;
|
||||
@ -55,6 +56,7 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
||||
DEBUGFS_PRINTLN(F("Reuse recv buffer"));
|
||||
sObj.remove(F("psave"));
|
||||
sObj.remove(F("v"));
|
||||
|
||||
if (!sObj["o"]) {
|
||||
DEBUGFS_PRINTLN(F("Save current state"));
|
||||
serializeState(sObj, true, sObj["ib"], sObj["sb"]);
|
||||
@ -68,13 +70,13 @@ void savePreset(byte index, bool persist, const char* pname, JsonObject saveobj)
|
||||
|
||||
writeObjectToFileUsingId("/presets.json", index, fileDoc);
|
||||
}
|
||||
presetsModifiedTime = now(); //unix time
|
||||
presetsModifiedTime = toki.second(); //unix time
|
||||
updateFSInfo();
|
||||
}
|
||||
|
||||
void deletePreset(byte index) {
|
||||
StaticJsonDocument<24> empty;
|
||||
writeObjectToFileUsingId("/presets.json", index, &empty);
|
||||
presetsModifiedTime = now(); //unix time
|
||||
presetsModifiedTime = toki.second(); //unix time
|
||||
updateFSInfo();
|
||||
}
|
@ -78,9 +78,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
int t = 0;
|
||||
|
||||
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
|
||||
#endif
|
||||
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++)
|
||||
if (btnPin[s]>=0 && pinManager.isPinAllocated(btnPin[s]))
|
||||
pinManager.deallocatePin(btnPin[s]);
|
||||
@ -127,7 +125,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
ledCount = request->arg(F("LC")).toInt();
|
||||
|
||||
// upate other pins
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
int hw_ir_pin = request->arg(F("IR")).toInt();
|
||||
if (pinManager.allocatePin(hw_ir_pin,false)) {
|
||||
irPin = hw_ir_pin;
|
||||
@ -135,7 +132,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
irPin = -1;
|
||||
}
|
||||
irEnabled = request->arg(F("IT")).toInt();
|
||||
#endif
|
||||
|
||||
int hw_rly_pin = request->arg(F("RL")).toInt();
|
||||
if (pinManager.allocatePin(hw_rly_pin,true)) {
|
||||
@ -202,8 +198,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
//SYNC
|
||||
if (subPage == 4)
|
||||
{
|
||||
//buttonType = request->arg(F("BT")).toInt();
|
||||
//irEnabled = request->arg(F("IR")).toInt();
|
||||
int t = request->arg(F("UP")).toInt();
|
||||
if (t > 0) udpPort = t;
|
||||
t = request->arg(F("U2")).toInt();
|
||||
@ -814,14 +808,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
//set time (unix timestamp)
|
||||
pos = req.indexOf(F("ST="));
|
||||
if (pos > 0) {
|
||||
setTime(getNumVal(&req, pos));
|
||||
setTimeFromAPI(getNumVal(&req, pos));
|
||||
}
|
||||
|
||||
//set countdown goal (unix timestamp)
|
||||
pos = req.indexOf(F("CT="));
|
||||
if (pos > 0) {
|
||||
countdownTime = getNumVal(&req, pos);
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
if (countdownTime - toki.second() > 0) countdownOverTriggered = false;
|
||||
}
|
||||
|
||||
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
|
||||
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();
|
||||
}
|
||||
|
||||
@ -849,7 +843,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
if (pos > 0) //sets backlight
|
||||
{
|
||||
cronixieBacklight = (req.charAt(pos+3) != '0');
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
#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
|
||||
|
||||
! 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.
|
||||
|
||||
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:
|
||||
|
||||
hour(); // the hour now (0-23)
|
||||
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
|
||||
The time and date functions take a parameter for the time. This prevents
|
||||
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
|
||||
following functions eliminates this probglem
|
||||
time_t t = now(); // store the current time in time variable t
|
||||
following functions eliminates this problem
|
||||
hour(t); // returns the hour 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
|
||||
@ -43,25 +31,6 @@ following functions eliminates this probglem
|
||||
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
|
||||
of time units.
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
examples, add error checking and messages to RTC examples,
|
||||
add examples to DS1307RTC library.
|
||||
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
|
||||
@ -37,7 +38,6 @@
|
||||
|
||||
static tmElements_t tm; // a cache of time elements
|
||||
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) {
|
||||
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
|
||||
refreshCache(t);
|
||||
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
|
||||
refreshCache(t);
|
||||
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 ;
|
||||
}
|
||||
|
||||
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
|
||||
return !isPM(t);
|
||||
}
|
||||
|
||||
uint8_t isPM() { // returns true if PM
|
||||
return isPM(now());
|
||||
}
|
||||
|
||||
uint8_t isPM(time_t t) { // returns true if PM
|
||||
return (hour(t) >= 12);
|
||||
}
|
||||
|
||||
int minute() {
|
||||
return minute(now());
|
||||
}
|
||||
|
||||
int minute(time_t t) { // the minute for the given time
|
||||
refreshCache(t);
|
||||
return tm.Minute;
|
||||
}
|
||||
|
||||
int second() {
|
||||
return second(now());
|
||||
}
|
||||
|
||||
int second(time_t t) { // the second for the given time
|
||||
refreshCache(t);
|
||||
return tm.Second;
|
||||
}
|
||||
|
||||
int day(){
|
||||
return(day(now()));
|
||||
}
|
||||
|
||||
int day(time_t t) { // the day for the given time (0-6)
|
||||
refreshCache(t);
|
||||
return tm.Day;
|
||||
}
|
||||
|
||||
int weekday() { // Sunday is day 1
|
||||
return weekday(now());
|
||||
}
|
||||
|
||||
int weekday(time_t t) {
|
||||
refreshCache(t);
|
||||
return tm.Wday;
|
||||
}
|
||||
|
||||
int month(){
|
||||
return month(now());
|
||||
}
|
||||
|
||||
int month(time_t t) { // the month for the given time
|
||||
refreshCache(t);
|
||||
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
|
||||
refreshCache(t);
|
||||
return tmYearToCalendar(tm.Year);
|
||||
@ -231,57 +191,6 @@ time_t makeTime(tmElements_t &tm){
|
||||
seconds+= tm.Second;
|
||||
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){
|
||||
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
|
||||
@ -298,28 +207,3 @@ time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){
|
||||
tm.Second = sec;
|
||||
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
|
||||
// nothing too terrible will result from overriding the C library header?!
|
||||
extern "C++" {
|
||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
||||
} timeStatus_t ;
|
||||
|
||||
typedef enum {
|
||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
||||
@ -96,32 +94,18 @@ typedef time_t(*getExternalTime)();
|
||||
|
||||
/*============================================================================*/
|
||||
/* time and date functions */
|
||||
int hour(); // the hour now
|
||||
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
|
||||
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 isPM(); // returns true if time now 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 second(); // the second now
|
||||
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 weekday(); // the weekday now (Sunday is day 1)
|
||||
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 year(); // the full four digit year: (2009, 2010 etc)
|
||||
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
|
||||
void adjustTime(long adjustment);
|
||||
|
||||
/* date strings */
|
||||
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
||||
@ -130,11 +114,6 @@ char* dayStr(uint8_t day);
|
||||
char* monthShortStr(uint8_t month);
|
||||
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 */
|
||||
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
|
||||
|
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
|
||||
*/
|
||||
|
||||
#define WLEDPACKETSIZE 29
|
||||
#define WLEDPACKETSIZE 36
|
||||
#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)
|
||||
{
|
||||
@ -37,8 +38,8 @@ void notify(byte callMode, bool followUp)
|
||||
//compatibilityVersionByte:
|
||||
//0: old 1: supports white 2: supports secondary color
|
||||
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
|
||||
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color
|
||||
udpOut[11] = 7;
|
||||
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
|
||||
udpOut[11] = 8;
|
||||
udpOut[12] = colSec[0];
|
||||
udpOut[13] = colSec[1];
|
||||
udpOut[14] = colSec[2];
|
||||
@ -60,6 +61,18 @@ void notify(byte callMode, bool followUp)
|
||||
udpOut[27] = (t >> 8) & 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;
|
||||
broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP());
|
||||
|
||||
@ -209,6 +222,9 @@ void handleNotifications()
|
||||
if (millis() - notificationSentTime < 1000) return;
|
||||
if (udpIn[1] > 199) return; //do not receive custom versions
|
||||
|
||||
//compatibilityVersionByte:
|
||||
byte version = udpIn[11];
|
||||
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
//apply colors from notification
|
||||
if (receiveNotificationColor || !someSel)
|
||||
@ -216,40 +232,66 @@ void handleNotifications()
|
||||
col[0] = udpIn[3];
|
||||
col[1] = udpIn[4];
|
||||
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];
|
||||
if (udpIn[11] > 1)
|
||||
if (version > 1)
|
||||
{
|
||||
colSec[0] = udpIn[12];
|
||||
colSec[1] = udpIn[13];
|
||||
colSec[2] = udpIn[14];
|
||||
colSec[3] = udpIn[15];
|
||||
}
|
||||
if (udpIn[11] > 5)
|
||||
{
|
||||
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)
|
||||
if (version > 6)
|
||||
{
|
||||
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool timebaseUpdated = false;
|
||||
//apply effects from notification
|
||||
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
|
||||
if (version < 200 && (receiveNotificationEffects || !someSel))
|
||||
{
|
||||
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
|
||||
effectSpeed = udpIn[9];
|
||||
if (udpIn[11] > 2) effectIntensity = udpIn[16];
|
||||
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
|
||||
if (version > 2) effectIntensity = udpIn[16];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (udpIn[11] > 3)
|
||||
//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 (version > 3)
|
||||
{
|
||||
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
|
||||
}
|
||||
|
@ -14,6 +14,10 @@
|
||||
#include "../usermods/Temperature/usermod_temperature.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
#include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h"
|
||||
#endif
|
||||
|
||||
//#include "usermod_v2_empty.h"
|
||||
|
||||
#ifdef USERMOD_BUZZER
|
||||
@ -61,6 +65,14 @@
|
||||
#include "../usermods/multi_relay/usermod_multi_relay.h"
|
||||
#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()
|
||||
{
|
||||
/*
|
||||
@ -74,6 +86,10 @@ void registerUsermods()
|
||||
usermods.add(new UsermodTemperature());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
usermods.add(new Usermod_SN_Photoresistor());
|
||||
#endif
|
||||
|
||||
//usermods.add(new UsermodRenameMe());
|
||||
|
||||
#ifdef USERMOD_BUZZER
|
||||
@ -118,4 +134,12 @@ void registerUsermods()
|
||||
#ifdef USERMOD_MULTI_RELAY
|
||||
usermods.add(new MultiRelay());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_RTC
|
||||
usermods.add(new RTCUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ELEKSTUBE_IPS
|
||||
usermods.add(new ElekstubeIPSUsermod());
|
||||
#endif
|
||||
}
|
||||
|
@ -176,6 +176,7 @@ void WiFiEvent(WiFiEvent_t event)
|
||||
|
||||
void WLED::loop()
|
||||
{
|
||||
handleTime();
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
@ -190,10 +191,8 @@ void WLED::loop()
|
||||
yield();
|
||||
handleIO();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
handleAlexa();
|
||||
|
||||
handleOverlays();
|
||||
yield();
|
||||
|
||||
if (doReboot)
|
||||
@ -246,6 +245,7 @@ void WLED::loop()
|
||||
// refresh WLED nodes list
|
||||
refreshNodeList();
|
||||
if (nodeBroadcastEnabled) sendSysInfoUDP();
|
||||
yield();
|
||||
}
|
||||
|
||||
//LED settings have been saved, re-init busses
|
||||
@ -274,9 +274,9 @@ void WLED::loop()
|
||||
if (millis() - debugTime > 9999) {
|
||||
DEBUG_PRINTLN(F("---DEBUG INFO---"));
|
||||
DEBUG_PRINT(F("Runtime: ")); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT(F("Unix time: ")); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT(F("Unix time: ")); toki.printTime(toki.getTime());
|
||||
DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
DEBUG_PRINT(F("Total PSRAM: ")); DEBUG_PRINT(ESP.getPsramSize()/1024); DEBUG_PRINTLN("kB");
|
||||
DEBUG_PRINT(F("Free PSRAM: ")); DEBUG_PRINT(ESP.getFreePsram()/1024); DEBUG_PRINTLN("kB");
|
||||
@ -298,6 +298,7 @@ void WLED::loop()
|
||||
}
|
||||
loops++;
|
||||
#endif // WLED_DEBUG
|
||||
toki.resetTick();
|
||||
}
|
||||
|
||||
void WLED::setup()
|
||||
@ -325,31 +326,21 @@ void WLED::setup()
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
registerUsermods();
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
pinManager.allocatePin(16); // GPIO16 reserved for SPI RAM
|
||||
pinManager.allocatePin(17); // GPIO17 reserved for SPI RAM
|
||||
}
|
||||
/*
|
||||
TODO make reservation for Ethernet pins
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) {
|
||||
ethernet_settings es = ethernetBoards[ethernetType];
|
||||
if (es.eth_power>0) pinManager.allocatePin(es.eth_power);
|
||||
if (es.eth_mdc>0) pinManager.allocatePin(es.eth_mdc);
|
||||
if (es.eth_mdio>0) pinManager.allocatePin(es.eth_mdio);
|
||||
//if (es.eth_type>0) pinManager.allocatePin(es.eth_type);
|
||||
//if (es.eth_clk_mode>0) pinManager.allocatePin(es.eth_clk_mode);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
#endif
|
||||
|
||||
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
|
||||
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
pinManager.allocatePin(1,true); // GPIO1 reserved for debug output
|
||||
#endif
|
||||
#ifdef WLED_USE_DMX //reserve GPIO2 as hardcoded DMX pin
|
||||
pinManager.allocatePin(2,false);
|
||||
pinManager.allocatePin(2);
|
||||
#endif
|
||||
|
||||
bool fsinit = false;
|
||||
@ -374,7 +365,6 @@ void WLED::setup()
|
||||
DEBUG_PRINTLN(F("Usermods setup"));
|
||||
userSetup();
|
||||
usermods.setup();
|
||||
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
showWelcomePage = true;
|
||||
WiFi.persistent(false);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// 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
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -90,6 +90,7 @@
|
||||
#include <SPIFFSEditor.h>
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#include "src/dependencies/toki/Toki.h"
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
#define ESPALEXA_ASYNC
|
||||
@ -118,7 +119,7 @@
|
||||
// The following is a construct to enable code to compile without it.
|
||||
// There is a code thet will still not use PSRAM though:
|
||||
// AsyncJsonResponse is a derived class that implements DynamicJsonDocument (AsyncJson-v6.h)
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
struct PSRAM_Allocator {
|
||||
void* allocate(size_t size) {
|
||||
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
||||
@ -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 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 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_ETH_DEFAULT // default ethernet board type if specified
|
||||
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 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 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
|
||||
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
|
||||
WLED_GLOBAL byte dP[] _INIT_N(({ 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL bool cronixieInit _INIT(false);
|
||||
WLED_GLOBAL byte dP[] _INIT_N(({ 255, 255, 255, 255, 255, 255 }));
|
||||
|
||||
// countdown
|
||||
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 time_t sunrise _INIT(0);
|
||||
WLED_GLOBAL time_t sunset _INIT(0);
|
||||
WLED_GLOBAL Toki toki _INIT(Toki());
|
||||
|
||||
// Temp buffer
|
||||
WLED_GLOBAL char* obuf;
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <Arduino.h> //PI constant
|
||||
|
||||
//#define WLED_DEBUG_MATH
|
||||
|
||||
#define modd(x, y) ((x) - (int)((x) / (y)) * (y))
|
||||
|
||||
float cos_t(float x)
|
||||
@ -24,38 +26,58 @@ float cos_t(float 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) {
|
||||
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 c = cos_t(x);
|
||||
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
|
||||
// Absolute error <= 6.7e-5
|
||||
float acos_t(float x) {
|
||||
float negate = float(x < 0);
|
||||
x = std::abs(x);
|
||||
float xabs = std::abs(x);
|
||||
float ret = -0.0187293;
|
||||
ret = ret * x;
|
||||
ret = ret * xabs;
|
||||
ret = ret + 0.0742610;
|
||||
ret = ret * x;
|
||||
ret = ret * xabs;
|
||||
ret = ret - 0.2121144;
|
||||
ret = ret * x;
|
||||
ret = ret * xabs;
|
||||
ret = ret + HALF_PI;
|
||||
ret = ret * sqrt(1.0-x);
|
||||
ret = ret * sqrt(1.0-xabs);
|
||||
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) {
|
||||
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 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) {
|
||||
if (x>1) return atan(x);
|
||||
bool neg = (x < 0);
|
||||
#ifdef WLED_DEBUG_MATH
|
||||
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;
|
||||
return ((A*xx + B)*xx + C)*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
|
||||
@ -110,12 +157,19 @@ float floor_t(float x) {
|
||||
bool neg = x < 0;
|
||||
int val = x;
|
||||
if (neg) val--;
|
||||
#ifdef WLED_DEBUG_MATH
|
||||
Serial.printf("floor: %f,%f\n",val,floor(x));
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
float fmod_t(float num, float 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
|
||||
|
@ -247,7 +247,10 @@ void initServer()
|
||||
//make API CORS compatible
|
||||
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;
|
||||
|
@ -412,8 +412,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
if (subPage == 4)
|
||||
{
|
||||
//sappend('v',SET_F("BT"),buttonType);
|
||||
//sappend('v',SET_F("IR"),irEnabled);
|
||||
sappend('v',SET_F("UP"),udpPort);
|
||||
sappend('v',SET_F("U2"),udpPort2);
|
||||
sappend('c',SET_F("RB"),receiveNotificationBrightness);
|
||||
@ -531,9 +529,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("A1"),macroAlexaOff);
|
||||
sappend('v',SET_F("MC"),macroCountdown);
|
||||
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++) {
|
||||
oappend(SET_F("addRow("));
|
||||
oappend(itoa(i,tm,10)); oappend(",");
|
||||
|
Loading…
Reference in New Issue
Block a user