Merge remote-tracking branch 'upstream/main' into mdev

This commit is contained in:
Ewoud
2023-02-06 21:06:13 +01:00
27 changed files with 4603 additions and 4258 deletions

View File

@@ -29,7 +29,11 @@
#include "fcn_declare.h"
#define IBN 5100
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
#define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0))
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
// effect utility functions
@@ -1923,11 +1927,10 @@ uint16_t mode_palette() {
counter = counter >> 8;
}
bool noWrap = (strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0));
for (int i = 0; i < SEGLEN; i++)
{
uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, noWrap, 255));
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_MOVING_WRAP, 255));
}
return FRAMETIME;
@@ -3266,11 +3269,11 @@ uint16_t mode_exploding_fireworks(void)
if (SEGENV.aux0 < 2) { //FLARE
if (SEGENV.aux0 == 0) { //init flare
flare->pos = 0;
flare->posX = strip.isMatrix ? random16(2,cols-1) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D
flare->posX = strip.isMatrix ? random16(2,cols-3) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D
uint16_t peakHeight = 75 + random8(180); //0-255
peakHeight = (peakHeight * (rows -1)) >> 8;
flare->vel = sqrtf(-2.0f * gravity * peakHeight);
flare->velX = strip.isMatrix ? (random8(8)-4)/32.f : 0; // no X velocity on 1D
flare->velX = strip.isMatrix ? (random8(9)-4)/32.f : 0; // no X velocity on 1D
flare->col = 255; //brightness
SEGENV.aux0 = 1;
}
@@ -3297,16 +3300,16 @@ uint16_t mode_exploding_fireworks(void)
* Size is proportional to the height.
*/
int nSparks = flare->pos + random8(4);
nSparks = constrain(nSparks, 1, numSparks);
nSparks = constrain(nSparks, 4, numSparks);
// initialize sparks
if (SEGENV.aux0 == 2) {
for (int i = 1; i < nSparks; i++) {
sparks[i].pos = flare->pos;
sparks[i].posX = flare->posX;
sparks[i].vel = (float(random16(0, 20000)) / 10000.0f) - 0.9f; // from -0.9 to 1.1
sparks[i].vel = (float(random16(20001)) / 10000.0f) - 0.9f; // from -0.9 to 1.1
sparks[i].vel *= rows<32 ? 0.5f : 1; // reduce velocity for smaller strips
sparks[i].velX = strip.isMatrix ? (float(random16(0, 4000)) / 10000.0f) - 0.2f : 0; // from -0.2 to 0.2
sparks[i].velX = strip.isMatrix ? (float(random16(10001)) / 10000.0f) - 0.5f : 0; // from -0.5 to 0.5
sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright
//sparks[i].col = constrain(sparks[i].col, 0, 345);
sparks[i].colIndex = random8();

View File

@@ -420,8 +420,8 @@ void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t o
markForReset();
return;
}
if (i1 < Segment::maxWidth) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
stop = i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2);
if (i1 < Segment::maxWidth || (i1 >= Segment::maxWidth*Segment::maxHeight && i1 < strip.getLengthTotal())) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
stop = i2 > Segment::maxWidth*Segment::maxHeight ? MIN(i2,strip.getLengthTotal()) : (i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2));
startY = 0;
stopY = 1;
#ifndef WLED_DISABLE_2D
@@ -866,12 +866,14 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
}
return;
} else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) {
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
int x = 0, y = 0;
if (virtualHeight()>1) y = i;
if (virtualWidth() >1) x = i;
setPixelColorXY(x, y, col);
return;
if (start < Segment::maxWidth*Segment::maxHeight) {
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
int x = 0, y = 0;
if (virtualHeight()>1) y = i;
if (virtualWidth() >1) x = i;
setPixelColorXY(x, y, col);
return;
}
}
#endif
@@ -1741,6 +1743,20 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
_segments[i].spacing = 0;
_mainSegment = i;
}
// do we have LEDs after the matrix? (ignore buses)
if (autoSegments && _length > Segment::maxWidth*Segment::maxHeight /*&& getActiveSegmentsNum() == 2*/) {
if (_segments.size() == getLastActiveSegmentId()+1)
_segments.push_back(Segment(Segment::maxWidth*Segment::maxHeight, _length));
else {
size_t i = getLastActiveSegmentId() + 1;
_segments[i].start = Segment::maxWidth*Segment::maxHeight;
_segments[i].stop = _length;
_segments[i].startY = 0;
_segments[i].stopY = 1;
_segments[i].grouping = 1;
_segments[i].spacing = 0;
}
}
#endif
} else if (autoSegments) { //make one segment per bus
uint16_t segStarts[MAX_NUM_SEGMENTS] = {0};
@@ -1764,6 +1780,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
s++;
}
_segments.clear();
_segments.reserve(s); // prevent reallocations
for (size_t i = 0; i < s; i++) {
Segment seg = Segment(segStarts[i], segStops[i]);
seg.selected = true;
@@ -1811,8 +1828,7 @@ bool WS2812FX::checkSegmentAlignment() {
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
//Note: If called in an interrupt (e.g. JSON API), original segment must be restored,
//otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread
uint8_t WS2812FX::setPixelSegment(uint8_t n)
{
uint8_t WS2812FX::setPixelSegment(uint8_t n) {
uint8_t prevSegId = _segment_index;
if (n < _segments.size()) {
_segment_index = n;
@@ -1821,8 +1837,7 @@ uint8_t WS2812FX::setPixelSegment(uint8_t n)
return prevSegId;
}
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
{
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
if (i2 >= i)
{
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
@@ -1832,14 +1847,12 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
}
}
void WS2812FX::setTransitionMode(bool t)
{
void WS2812FX::setTransitionMode(bool t) {
for (segment &seg : _segments) if (!seg.transitional) seg.startTransition(t ? _transitionDur : 0);
}
#ifdef WLED_DEBUG
void WS2812FX::printSize()
{
void WS2812FX::printSize() {
size_t size = 0;
for (const Segment &seg : _segments) size += seg.getSize();
DEBUG_PRINTF("Segments: %d -> %uB\n", _segments.size(), size);
@@ -1850,8 +1863,7 @@ void WS2812FX::printSize()
}
#endif
void WS2812FX::loadCustomPalettes()
{
void WS2812FX::loadCustomPalettes() {
byte tcp[72]; //support gradient palettes with up to 18 entries
CRGBPalette16 targetPalette;
customPalettes.clear(); // start fresh
@@ -1953,7 +1965,7 @@ void WS2812FX::deserializeMap(uint8_t n) {
customMappingSize = map.size();
customMappingTable = new uint16_t[customMappingSize];
for (uint16_t i=0; i<MIN(map.size(),customMappingSize); i++) {
customMappingTable[i] = (uint16_t) map[i];
customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
}
loadedLedmap = n;
setUpMatrix(false); //WLEDMM: apply logical to physical mapping after the ledmap
@@ -1967,11 +1979,6 @@ void WS2812FX::deserializeMap(uint8_t n) {
WS2812FX* WS2812FX::instance = nullptr;
//Bus static member definition, would belong in bus_manager.cpp
int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255;
const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])=====";
//WLEDMM netmindz ar palette add Audio responsive
const char JSON_palette_names[] PROGMEM = R"=====([

540
wled00/bus_manager.cpp Normal file
View File

@@ -0,0 +1,540 @@
/*
* Class implementation for addressing various light types
*/
#include <Arduino.h>
#include <IPAddress.h>
#include "const.h"
#include "pin_manager.h"
#include "bus_wrapper.h"
#include "bus_manager.h"
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
uint16_t approximateKelvinFromRGB(uint32_t rgb);
void colorRGBtoRGBW(byte* rgb);
//udp.cpp
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
// enable additional debug output
#if defined(WLED_DEBUG_HOST)
#include "net_debug.h"
#define DEBUGOUT NetDebug
#else
#define DEBUGOUT Serial
#endif
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x...)
#endif
//color mangling macros
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
#define R(c) (byte((c) >> 16))
#define G(c) (byte((c) >> 8))
#define B(c) (byte(c))
#define W(c) (byte((c) >> 24))
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
return;
}
if (len == 0) {
return;
}
if (colorOrder > COL_ORDER_MAX) {
return;
}
_mappings[_count].start = start;
_mappings[_count].len = len;
_mappings[_count].colorOrder = colorOrder;
_count++;
}
uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
if (_count == 0) return defaultColorOrder;
// upper nibble containd W swap information
uint8_t swapW = defaultColorOrder >> 4;
for (uint8_t i = 0; i < _count; i++) {
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
return _mappings[i].colorOrder | (swapW << 4);
}
}
return defaultColorOrder;
}
uint32_t Bus::autoWhiteCalc(uint32_t c) {
uint8_t aWM = _autoWhiteMode;
if (_gAWM < 255) aWM = _gAWM;
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
uint8_t w = W(c);
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
return RGBW32(r, g, b, w);
}
BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
if (!IS_DIGITAL(bc.type) || !bc.count) return;
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
_pins[0] = bc.pins[0];
if (IS_2PIN(bc.type)) {
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
cleanup(); return;
}
_pins[1] = bc.pins[1];
}
reversed = bc.reversed;
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
_skip = bc.skipAmount; //sacrificial pixels
_len = bc.count + _skip;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
_valid = (_busPtr != nullptr);
_colorOrder = bc.colorOrder;
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
}
void BusDigital::show() {
PolyBus::show(_busPtr, _iType);
}
bool BusDigital::canShow() {
return PolyBus::canShow(_busPtr, _iType);
}
void BusDigital::setBrightness(uint8_t b) {
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
}
#endif
Bus::setBrightness(b);
PolyBus::setBrightness(_busPtr, _iType, b);
}
//If LEDs are skipped, it is possible to use the first as a status LED.
//TODO only show if no new show due in the next 50ms
void BusDigital::setStatusPixel(uint32_t c) {
if (_skip && canShow()) {
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
PolyBus::show(_busPtr, _iType);
}
}
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (reversed) pix = _len - pix -1;
else pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
uint32_t BusDigital::getPixelColor(uint16_t pix) {
if (reversed) pix = _len - pix -1;
else pix += _skip;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
uint8_t BusDigital::getPins(uint8_t* pinArray) {
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void BusDigital::setColorOrder(uint8_t colorOrder) {
// upper nibble contains W swap information
if ((colorOrder & 0x0F) > 5) return;
_colorOrder = colorOrder;
}
void BusDigital::reinit() {
PolyBus::begin(_busPtr, _iType, _pins);
}
void BusDigital::cleanup() {
DEBUG_PRINTLN(F("Digital Cleanup."));
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
}
BusPwm::BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (!IS_PWM(bc.type)) return;
uint8_t numPins = NUM_PWM_PINS(bc.type);
#ifdef ESP8266
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(WLED_PWM_FREQ);
#else
_ledcStart = pinManager.allocateLedc(numPins);
if (_ledcStart == 255) { //no more free LEDC channels
deallocatePins(); return;
}
#endif
for (uint8_t i = 0; i < numPins; i++) {
uint8_t currentPin = bc.pins[i];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
deallocatePins(); return;
}
_pins[i] = currentPin; //store only after allocatePin() succeeds
#ifdef ESP8266
pinMode(_pins[i], OUTPUT);
#else
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
ledcAttachPin(_pins[i], _ledcStart + i);
#endif
}
reversed = bc.reversed;
_valid = true;
}
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
}
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
}
uint8_t ww, cw;
#ifdef WLED_USE_IC_CCT
ww = w;
cw = cct;
#else
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
#endif
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w;
break;
case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw;
_data[0] = ww;
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw;
w = ww;
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
_data[0] = r; _data[1] = g; _data[2] = b;
break;
}
}
//does no index check
uint32_t BusPwm::getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
}
void BusPwm::show() {
if (!_valid) return;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t scaled = (_data[i] * _bri) / 255;
if (reversed) scaled = 255 - scaled;
#ifdef ESP8266
analogWrite(_pins[i], scaled);
#else
ledcWrite(_ledcStart + i, scaled);
#endif
}
}
uint8_t BusPwm::getPins(uint8_t* pinArray) {
if (!_valid) return 0;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinArray[i] = _pins[i];
}
return numPins;
}
void BusPwm::deallocatePins() {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
if (!pinManager.isPinOk(_pins[i])) continue;
#ifdef ESP8266
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
#else
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
#endif
}
#ifdef ARDUINO_ARCH_ESP32
pinManager.deallocateLedc(_ledcStart, numPins);
#endif
}
BusOnOff::BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (bc.type != TYPE_ONOFF) return;
uint8_t currentPin = bc.pins[0];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
return;
}
_pin = currentPin; //store only after allocatePin() succeeds
pinMode(_pin, OUTPUT);
reversed = bc.reversed;
_valid = true;
}
void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
c = autoWhiteCalc(c);
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0;
}
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data, _data, _data, _data);
}
void BusOnOff::show() {
if (!_valid) return;
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
}
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
if (!_valid) return 0;
pinArray[0] = _pin;
return 1;
}
BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
// switch (bc.type) {
// case TYPE_NET_ARTNET_RGB:
// _rgbw = false;
// _UDPtype = 2;
// break;
// case TYPE_NET_E131_RGB:
// _rgbw = false;
// _UDPtype = 1;
// break;
// case TYPE_NET_DDP_RGB:
// _rgbw = false;
// _UDPtype = 0;
// break;
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
_UDPtype = 0;
// break;
// }
_UDPchannels = _rgbw ? 4 : 3;
_data = (byte *)malloc(bc.count * _UDPchannels);
if (_data == nullptr) return;
memset(_data, 0, bc.count * _UDPchannels);
_len = bc.count;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
_broadcastLock = false;
_valid = true;
}
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return;
if (isRgbw()) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c);
_data[offset+1] = G(c);
_data[offset+2] = B(c);
if (_rgbw) _data[offset+3] = W(c);
}
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
if (!_valid || pix >= _len) return 0;
uint16_t offset = pix * _UDPchannels;
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
}
void BusNetwork::show() {
if (!_valid || !canShow()) return;
_broadcastLock = true;
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
_broadcastLock = false;
}
uint8_t BusNetwork::getPins(uint8_t* pinArray) {
for (uint8_t i = 0; i < 4; i++) {
pinArray[i] = _client[i];
}
return 4;
}
void BusNetwork::cleanup() {
_type = I_NONE;
_valid = false;
if (_data != nullptr) free(_data);
_data = nullptr;
}
//utility to get the approx. memory usage of a given BusConfig
uint32_t BusManager::memUsage(BusConfig &bc) {
uint8_t type = bc.type;
uint16_t len = bc.count + bc.skipAmount;
if (type > 15 && type < 32) {
#ifdef ESP8266
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
if (type > 29) return len*20; //RGBW
return len*15;
}
if (type > 29) return len*4; //RGBW
return len*3;
#else //ESP32 RMT uses double buffer?
if (type > 29) return len*8; //RGBW
return len*6;
#endif
}
if (type > 31 && type < 48) return 5;
if (type == 44 || type == 45) return len*4; //RGBW
return len*3; //RGB
}
int BusManager::add(BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
busses[numBusses] = new BusNetwork(bc);
} else if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
} else if (bc.type == TYPE_ONOFF) {
busses[numBusses] = new BusOnOff(bc);
} else {
busses[numBusses] = new BusPwm(bc);
}
return numBusses++;
}
//do not call this method from system context (network callback)
void BusManager::removeAll() {
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
}
void BusManager::show() {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->show();
}
}
void BusManager::setStatusPixel(uint32_t c) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setStatusPixel(c);
}
}
void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
}
}
void BusManager::setBrightness(uint8_t b) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setBrightness(b);
}
}
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
if (cct > 255) cct = 255;
if (cct >= 0) {
//if white balance correction allowed, save as kelvin value instead of 0-255
if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1;
Bus::setCCT(cct);
}
uint32_t BusManager::getPixelColor(uint16_t pix) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
return b->getPixelColor(pix - bstart);
}
return 0;
}
bool BusManager::canAllShow() {
for (uint8_t i = 0; i < numBusses; i++) {
if (!busses[i]->canShow()) return false;
}
return true;
}
Bus* BusManager::getBus(uint8_t busNr) {
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t BusManager::getTotalLength() {
uint16_t len = 0;
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
return len;
}
// Bus static member definition
int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255;

View File

@@ -6,45 +6,11 @@
*/
#include "const.h"
#include "pin_manager.h"
#include "bus_wrapper.h"
#include <Arduino.h>
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
void colorRGBtoRGBW(byte* rgb);
// enable additional debug output
#if defined(WLED_DEBUG_HOST)
#define DEBUGOUT NetDebug
#else
#define DEBUGOUT Serial
#endif
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x...)
#endif
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
//color mangling macros
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
#define R(c) (byte((c) >> 16))
#define G(c) (byte((c) >> 8))
#define B(c) (byte(c))
#define W(c) (byte((c) >> 24))
//temporary struct for passing bus configuration to bus
struct BusConfig {
uint8_t type;
@@ -88,53 +54,29 @@ struct ColorOrderMapEntry {
};
struct ColorOrderMap {
void add(uint16_t start, uint16_t len, uint8_t colorOrder) {
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
return;
}
if (len == 0) {
return;
}
if (colorOrder > COL_ORDER_MAX) {
return;
}
_mappings[_count].start = start;
_mappings[_count].len = len;
_mappings[_count].colorOrder = colorOrder;
_count++;
}
void add(uint16_t start, uint16_t len, uint8_t colorOrder);
uint8_t count() const {
return _count;
}
void reset() {
_count = 0;
memset(_mappings, 0, sizeof(_mappings));
}
const ColorOrderMapEntry* get(uint8_t n) const {
if (n > _count) {
return nullptr;
uint8_t count() const {
return _count;
}
return &(_mappings[n]);
}
inline uint8_t IRAM_ATTR getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
if (_count == 0) return defaultColorOrder;
// upper nibble containd W swap information
uint8_t swapW = defaultColorOrder >> 4;
for (uint8_t i = 0; i < _count; i++) {
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
return _mappings[i].colorOrder | (swapW << 4);
void reset() {
_count = 0;
memset(_mappings, 0, sizeof(_mappings));
}
const ColorOrderMapEntry* get(uint8_t n) const {
if (n > _count) {
return nullptr;
}
return &(_mappings[n]);
}
return defaultColorOrder;
}
uint8_t getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const;
private:
uint8_t _count;
ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS];
uint8_t _count;
ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS];
};
//parent class of BusDigital, BusPwm, and BusNetwork
@@ -214,440 +156,155 @@ class Bus {
bool _valid;
bool _needsRefresh;
uint8_t _autoWhiteMode;
static uint8_t _gAWM; // definition in FX_fcn.cpp
static int16_t _cct; // definition in FX_fcn.cpp
static uint8_t _cctBlend; // definition in FX_fcn.cpp
static uint8_t _gAWM;
static int16_t _cct;
static uint8_t _cctBlend;
uint32_t autoWhiteCalc(uint32_t c) {
uint8_t aWM = _autoWhiteMode;
if (_gAWM < 255) aWM = _gAWM;
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
uint8_t w = W(c);
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
return RGBW32(r, g, b, w);
}
uint32_t autoWhiteCalc(uint32_t c);
};
class BusDigital : public Bus {
public:
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
if (!IS_DIGITAL(bc.type) || !bc.count) return;
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
_pins[0] = bc.pins[0];
if (IS_2PIN(bc.type)) {
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
cleanup(); return;
}
_pins[1] = bc.pins[1];
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com);
inline void show();
bool canShow();
void setBrightness(uint8_t b);
void setStatusPixel(uint32_t c);
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix);
uint8_t getColorOrder() {
return _colorOrder;
}
reversed = bc.reversed;
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
_skip = bc.skipAmount; //sacrificial pixels
_len = bc.count + _skip;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
_valid = (_busPtr != nullptr);
_colorOrder = bc.colorOrder;
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
};
inline void show() {
PolyBus::show(_busPtr, _iType);
}
inline bool canShow() {
return PolyBus::canShow(_busPtr, _iType);
}
void setBrightness(uint8_t b) {
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
uint16_t getLength() {
return _len - _skip;
}
#endif
Bus::setBrightness(b);
PolyBus::setBrightness(_busPtr, _iType, b);
}
//If LEDs are skipped, it is possible to use the first as a status LED.
//TODO only show if no new show due in the next 50ms
void setStatusPixel(uint32_t c) {
if (_skip && canShow()) {
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
PolyBus::show(_busPtr, _iType);
uint8_t getPins(uint8_t* pinArray);
void setColorOrder(uint8_t colorOrder);
uint8_t skippedLeds() {
return _skip;
}
}
void setPixelColor(uint16_t pix, uint32_t c) {
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (reversed) pix = _len - pix -1;
else pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
void reinit();
uint32_t getPixelColor(uint16_t pix) {
if (reversed) pix = _len - pix -1;
else pix += _skip;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
void cleanup();
inline uint8_t getColorOrder() {
return _colorOrder;
}
uint16_t getLength() {
return _len - _skip;
}
uint8_t getPins(uint8_t* pinArray) {
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void setColorOrder(uint8_t colorOrder) {
// upper nibble contains W swap information
if ((colorOrder & 0x0F) > 5) return;
_colorOrder = colorOrder;
}
inline uint8_t skippedLeds() {
return _skip;
}
inline void reinit() {
PolyBus::begin(_busPtr, _iType, _pins);
}
void cleanup() {
DEBUG_PRINTLN(F("Digital Cleanup."));
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
}
~BusDigital() {
cleanup();
}
~BusDigital() {
cleanup();
}
private:
uint8_t _colorOrder = COL_ORDER_GRB;
uint8_t _pins[2] = {255, 255};
uint8_t _iType = I_NONE;
uint8_t _skip = 0;
void * _busPtr = nullptr;
const ColorOrderMap &_colorOrderMap;
uint8_t _colorOrder = COL_ORDER_GRB;
uint8_t _pins[2] = {255, 255};
uint8_t _iType = 0; //I_NONE;
uint8_t _skip = 0;
void * _busPtr = nullptr;
const ColorOrderMap &_colorOrderMap;
};
class BusPwm : public Bus {
public:
BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (!IS_PWM(bc.type)) return;
uint8_t numPins = NUM_PWM_PINS(bc.type);
BusPwm(BusConfig &bc);
#ifdef ESP8266
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(WLED_PWM_FREQ);
#else
_ledcStart = pinManager.allocateLedc(numPins);
if (_ledcStart == 255) { //no more free LEDC channels
deallocatePins(); return;
}
#endif
void setPixelColor(uint16_t pix, uint32_t c);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t currentPin = bc.pins[i];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
deallocatePins(); return;
}
_pins[i] = currentPin; //store only after allocatePin() succeeds
#ifdef ESP8266
pinMode(_pins[i], OUTPUT);
#else
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
ledcAttachPin(_pins[i], _ledcStart + i);
#endif
}
reversed = bc.reversed;
_valid = true;
};
//does no index check
uint32_t getPixelColor(uint16_t pix);
void setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
}
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
void show();
uint8_t getPins(uint8_t* pinArray);
void cleanup() {
deallocatePins();
}
uint8_t ww, cw;
#ifdef WLED_USE_IC_CCT
ww = w;
cw = cct;
#else
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
#endif
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w;
break;
case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw;
_data[0] = ww;
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw;
w = ww;
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
_data[0] = r; _data[1] = g; _data[2] = b;
break;
~BusPwm() {
cleanup();
}
}
//does no index check
uint32_t getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
}
void show() {
if (!_valid) return;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t scaled = (_data[i] * _bri) / 255;
if (reversed) scaled = 255 - scaled;
#ifdef ESP8266
analogWrite(_pins[i], scaled);
#else
ledcWrite(_ledcStart + i, scaled);
#endif
}
}
uint8_t getPins(uint8_t* pinArray) {
if (!_valid) return 0;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinArray[i] = _pins[i];
}
return numPins;
}
void cleanup() {
deallocatePins();
}
~BusPwm() {
cleanup();
}
private:
uint8_t _pins[5] = {255, 255, 255, 255, 255};
uint8_t _data[5] = {0};
#ifdef ARDUINO_ARCH_ESP32
uint8_t _ledcStart = 255;
#endif
void deallocatePins() {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
if (!pinManager.isPinOk(_pins[i])) continue;
#ifdef ESP8266
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
#else
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
#endif
}
uint8_t _pins[5] = {255, 255, 255, 255, 255};
uint8_t _data[5] = {0};
#ifdef ARDUINO_ARCH_ESP32
pinManager.deallocateLedc(_ledcStart, numPins);
uint8_t _ledcStart = 255;
#endif
}
void deallocatePins();
};
class BusOnOff : public Bus {
public:
BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (bc.type != TYPE_ONOFF) return;
BusOnOff(BusConfig &bc);
uint8_t currentPin = bc.pins[0];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
return;
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix);
void show();
uint8_t getPins(uint8_t* pinArray);
void cleanup() {
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
}
_pin = currentPin; //store only after allocatePin() succeeds
pinMode(_pin, OUTPUT);
reversed = bc.reversed;
_valid = true;
};
void setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
c = autoWhiteCalc(c);
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0;
}
uint32_t getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data, _data, _data, _data);
}
void show() {
if (!_valid) return;
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
}
uint8_t getPins(uint8_t* pinArray) {
if (!_valid) return 0;
pinArray[0] = _pin;
return 1;
}
void cleanup() {
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
}
~BusOnOff() {
cleanup();
}
~BusOnOff() {
cleanup();
}
private:
uint8_t _pin = 255;
uint8_t _data = 0;
uint8_t _pin = 255;
uint8_t _data = 0;
};
class BusNetwork : public Bus {
public:
BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
// switch (bc.type) {
// case TYPE_NET_ARTNET_RGB:
// _rgbw = false;
// _UDPtype = 2;
// break;
// case TYPE_NET_E131_RGB:
// _rgbw = false;
// _UDPtype = 1;
// break;
// case TYPE_NET_DDP_RGB:
// _rgbw = false;
// _UDPtype = 0;
// break;
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
_UDPtype = 0;
// break;
// }
_UDPchannels = _rgbw ? 4 : 3;
_data = (byte *)malloc(bc.count * _UDPchannels);
if (_data == nullptr) return;
memset(_data, 0, bc.count * _UDPchannels);
_len = bc.count;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
_broadcastLock = false;
_valid = true;
};
BusNetwork(BusConfig &bc);
bool hasRGB() { return true; }
bool hasWhite() { return _rgbw; }
bool hasRGB() { return true; }
bool hasWhite() { return _rgbw; }
void setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return;
if (isRgbw()) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c);
_data[offset+1] = G(c);
_data[offset+2] = B(c);
if (_rgbw) _data[offset+3] = W(c);
}
void setPixelColor(uint16_t pix, uint32_t c);
uint32_t getPixelColor(uint16_t pix) {
if (!_valid || pix >= _len) return 0;
uint16_t offset = pix * _UDPchannels;
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
}
uint32_t getPixelColor(uint16_t pix);
void show() {
if (!_valid || !canShow()) return;
_broadcastLock = true;
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
_broadcastLock = false;
}
void show();
inline bool canShow() {
// this should be a return value from UDP routine if it is still sending data out
return !_broadcastLock;
}
uint8_t getPins(uint8_t* pinArray) {
for (uint8_t i = 0; i < 4; i++) {
pinArray[i] = _client[i];
bool canShow() {
// this should be a return value from UDP routine if it is still sending data out
return !_broadcastLock;
}
return 4;
}
inline bool isRgbw() {
return _rgbw;
}
uint8_t getPins(uint8_t* pinArray);
inline uint16_t getLength() {
return _len;
}
bool isRgbw() {
return _rgbw;
}
void cleanup() {
_type = I_NONE;
_valid = false;
if (_data != nullptr) free(_data);
_data = nullptr;
}
uint16_t getLength() {
return _len;
}
~BusNetwork() {
cleanup();
}
void cleanup();
~BusNetwork() {
cleanup();
}
private:
IPAddress _client;
@@ -661,154 +318,56 @@ class BusNetwork : public Bus {
class BusManager {
public:
BusManager() {};
BusManager() {};
//utility to get the approx. memory usage of a given BusConfig
static uint32_t memUsage(BusConfig &bc) {
uint8_t type = bc.type;
uint16_t len = bc.count + bc.skipAmount;
if (type > 15 && type < 32) {
#ifdef ESP8266
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
if (type > 29) return len*20; //RGBW
return len*15;
}
if (type > 29) return len*4; //RGBW
return len*3;
#else //ESP32 RMT uses double buffer?
if (type > 29) return len*8; //RGBW
return len*6;
#endif
//utility to get the approx. memory usage of a given BusConfig
static uint32_t memUsage(BusConfig &bc);
int add(BusConfig &bc);
//do not call this method from system context (network callback)
void removeAll();
void show();
void setStatusPixel(uint32_t c);
void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
void setBrightness(uint8_t b);
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
uint32_t getPixelColor(uint16_t pix);
bool canAllShow();
Bus* getBus(uint8_t busNr);
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t getTotalLength();
inline void updateColorOrderMap(const ColorOrderMap &com) {
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
}
if (type > 31 && type < 48) return 5;
if (type == 44 || type == 45) return len*4; //RGBW
return len*3; //RGB
}
/*
int add(BusConfig &bc);
void removeAll(); //do not call this method from system context (network callback)
void setStatusPixel(uint32_t c);
void setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
void setBrightness(uint8_t b);
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
uint32_t getPixelColor(uint16_t pix);
bool canAllShow();
Bus* getBus(uint8_t busNr);
void show();
uint16_t getTotalLength(); //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
*/
// the following functions are inlined by compiler since they are defined within class definition
// they should be placed in cpp file instead
int add(BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
busses[numBusses] = new BusNetwork(bc);
} else if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
} else if (bc.type == TYPE_ONOFF) {
busses[numBusses] = new BusOnOff(bc);
} else {
busses[numBusses] = new BusPwm(bc);
inline const ColorOrderMap& getColorOrderMap() const {
return colorOrderMap;
}
return numBusses++;
}
//do not call this method from system context (network callback)
void removeAll() {
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
}
void show() {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->show();
inline uint8_t getNumBusses() {
return numBusses;
}
}
void setStatusPixel(uint32_t c) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setStatusPixel(c);
}
}
void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
}
}
void setBrightness(uint8_t b) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setBrightness(b);
}
}
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false) {
if (cct > 255) cct = 255;
if (cct >= 0) {
//if white balance correction allowed, save as kelvin value instead of 0-255
if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1;
Bus::setCCT(cct);
}
uint32_t getPixelColor(uint16_t pix) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
return b->getPixelColor(pix - bstart);
}
return 0;
}
bool canAllShow() {
for (uint8_t i = 0; i < numBusses; i++) {
if (!busses[i]->canShow()) return false;
}
return true;
}
Bus* getBus(uint8_t busNr) {
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t getTotalLength() {
uint16_t len = 0;
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
return len;
}
inline void updateColorOrderMap(const ColorOrderMap &com) {
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
}
inline const ColorOrderMap& getColorOrderMap() const {
return colorOrderMap;
}
inline uint8_t getNumBusses() {
return numBusses;
}
private:
uint8_t numBusses = 0;
Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
ColorOrderMap colorOrderMap;
uint8_t numBusses = 0;
Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
ColorOrderMap colorOrderMap;
inline uint8_t getNumVirtualBusses() {
int j = 0;
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
return j;
}
inline uint8_t getNumVirtualBusses() {
int j = 0;
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
return j;
}
};
#endif

View File

@@ -731,7 +731,7 @@ function populateSegments(s)
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`;
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`;
let rvYck = "", miYck ="";
if (isM) {
if (isM && staX<mw*mh) {
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
}
@@ -775,19 +775,19 @@ function populateSegments(s)
<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
<table class="infot segt">
<tr>
<td>${isM?'Start X':'Start LED'}</td>
<td>${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
<td>${isM?'':'Offset'}</td>
<td>${isM&&staX<mw*mh?'Start X':'Start LED'}</td>
<td>${isM&&staX<mw*mh?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
<td>${isM&&staX<mw*mh?'':'Offset'}</td>
</tr>
<tr>
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM?mw:ledCount)-(cfg.comp.seglen?staX:0)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td style="text-align:revert;">${isM?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td style="text-align:revert;">${isM&&staX<mw*mh?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM&&staX<mw*mh?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
</tr>
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
${isM&&staX<mw*mh ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
'<tr>'+
'<td><input class="noslide segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+(mh-(cfg.comp.seglen?staY:0))+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+mh+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+
'</tr>':''}
<tr>
@@ -798,17 +798,18 @@ function populateSegments(s)
<tr>
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td style="text-align:left;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td>
<td style="text-align:revert;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td>
</tr>
</table>
<div class="h bp" id="seg${i}len"></div>
${!isM?rvXck:''}
${isM&&stoY-staY>1&&stoX-staX>1?map2D:''}
${!(isM&&staX<mw*mh)?rvXck:''}
${isM&&staX<mw*mh&&stoY-staY>1&&stoX-staX>1?map2D:''}
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim}
${s.CustomEffects && s.CustomEffects.on && fxName.includes("Custom Effect") ? cusEff : ""}
<label class="check revchkl" id="seg${i}lbtm">
${isM?'Transpose':'Mirror effect'}
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
${isM&&staX<mw*mh?'Transpose':'Mirror effect'}${isM&&staX<mw*mh?
'<input type="checkbox" id="seg'+i+'tp" onchange="setTp('+i+')" '+(inst.tp?"checked":"")+'>':
'<input type="checkbox" id="seg'+i+'mi" onchange="setMi('+i+')" '+(inst.mi?"checked":"")+'>'}
<span class="checkmark"></span>
</label>
<div class="del">
@@ -1078,29 +1079,50 @@ function updateLen(s)
var start = parseInt(gId(`seg${s}s`).value);
var stop = parseInt(gId(`seg${s}e`).value) + (cfg.comp.seglen?start:0);
var len = stop - start;
let sY = gId(`seg${s}sY`);
let eY = gId(`seg${s}eY`);
let sX = gId(`seg${s}s`);
let eX = gId(`seg${s}e`);
let of = gId(`seg${s}of`);
let mySH = gId("mkSYH");
let mySD = gId("mkSYD");
if (isM) {
// matrix setup
let startY = parseInt(gId(`seg${s}sY`).value);
let stopY = parseInt(gId(`seg${s}eY`).value) + (cfg.comp.seglen?startY:0);
len *= (stopY-startY);
let tPL = gId(`seg${s}lbtm`);
if (stop-start>1 && stopY-startY>1) {
// 2D segment
if (tPL) tPL.classList.remove('hide'); // unhide transpose checkbox
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
if (sE) {
let sN = sE.querySelector(".lstIname").innerText;
let seg = gId(`seg${s}map2D`);
if (seg) {
if(sN.indexOf("\u25A6")<0) seg.classList.remove('hide'); // unhide mapping for 1D effects (| in name)
else seg.classList.add('hide'); // hide mapping otherwise
}
}
// do we have 1D segment *after* the matrix?
if (start >= mw*mh) {
if (sY) { sY.value = 0; sY.max = 0; sY.min = 0; }
if (eY) { eY.value = 1; eY.max = 1; eY.min = 0; }
sX.min = mw*mh; sX.max = ledCount-1;
eX.min = mw*mh+1; eX.max = ledCount;
if (mySH) mySH.classList.add("hide");
if (mySD) mySD.classList.add("hide");
if (of) of.classList.remove("hide");
} else {
// 1D segment in 2D set-up
if (tPL) {
tPL.classList.add('hide'); // hide transpose checkbox
gId(`seg${s}tp`).checked = false; // and uncheck it
// matrix setup
if (mySH) mySH.classList.remove("hide");
if (mySD) mySD.classList.remove("hide");
if (of) of.classList.add("hide");
let startY = parseInt(sY.value);
let stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
len *= (stopY-startY);
let tPL = gId(`seg${s}lbtm`);
if (stop-start>1 && stopY-startY>1) {
// 2D segment
if (tPL) tPL.classList.remove('hide'); // unhide transpose checkbox
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
if (sE) {
let sN = sE.querySelector(".lstIname").innerText;
let seg = gId(`seg${s}map2D`);
if (seg) {
if(sN.indexOf("\u25A6")<0) seg.classList.remove('hide'); // unhide mapping for 1D effects (| in name)
else seg.classList.add('hide'); // hide mapping otherwise
}
}
} else {
// 1D segment in 2D set-up
if (tPL) {
tPL.classList.add('hide'); // hide transpose checkbox
gId(`seg${s}tp`).checked = false; // and uncheck it
}
}
}
}
@@ -1119,6 +1141,7 @@ function updateLen(s)
var virt = Math.ceil(len/(grp + spc));
if (!isNaN(virt) && (grp > 1 || spc > 0)) out += ` (${virt} virtual)`;
}
if (isM && start >= mw*mh) out += " [strip]";
gId(`seg${s}len`).innerHTML = out;
draw();
@@ -1840,11 +1863,11 @@ function makeSeg()
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
<td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td>
</tr>
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td></tr>'+
'<tr>'+
'<td><input class="noslide segn" id="seg'+lu+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+0+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
'<td><input class="noslide segn" id="seg'+lu+'eY" type="number" min="0" max="'+mh+'" value="'+mh+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
'</tr>':''}
<tr id="mkSYH" class="${isM?"":"hide"}"><td>Start Y</td><td>${cfg.comp.seglen?'Height':'Stop Y'}</td></tr>
<tr id="mkSYD" class="${isM?"":"hide"}">
<td><input class="noslide segn" id="seg${lu}sY" type="number" min="0" max="${mh-1}" value="0" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
<td><input class="noslide segn" id="seg${lu}eY" type="number" min="0" max="${mh}" value="${isM?mh:1}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
</tr>
</table>
<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div>
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>
@@ -2174,25 +2197,26 @@ function setSeg(s)
let sX = gId(`seg${s}s`);
let eX = gId(`seg${s}e`);
var start = parseInt(sX.value);
var stop = parseInt(eX.value);
var stop = parseInt(eX.value) + (cfg.comp.seglen?start:0);
if (start<sX.min || start>sX.max) {sX.value=sX.min; return;} // prevent out of bounds
if (stop<eX.min || stop>eX.max) {eX.value=eX.max; return;} // prevent out of bounds
if (stop<eX.min || stop-(cfg.comp.seglen?start:0)>eX.max) {eX.value=eX.max; return;} // prevent out of bounds
if ((cfg.comp.seglen && stop == 0) || (!cfg.comp.seglen && stop <= start)) {delSeg(s); return;}
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
if (isM) {
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": stop}};
if (isM && start<mw*mh) {
let sY = gId(`seg${s}sY`);
let eY = gId(`seg${s}eY`);
var startY = parseInt(sY.value);
var stopY = parseInt(eY.value);
var stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
if (startY<sY.min || startY>sY.max) {sY.value=sY.min; return;} // prevent out of bounds
if (stopY<eY.min || stopY>eY.max) {eY.value=eY.max; return;} // prevent out of bounds
obj.seg.startY = startY;
obj.seg.stopY = (cfg.comp.seglen?startY:0)+stopY;
obj.seg.stopY = stopY;
}
if (gId(`seg${s}grp`)) { // advanced options, not present in new segment dialog (makeSeg())
var grp = parseInt(gId(`seg${s}grp`).value);
var spc = parseInt(gId(`seg${s}spc`).value);
var ofs = parseInt(gId(`seg${s}of` ).value);
let g = gId(`seg${s}grp`);
if (g) { // advanced options, not present in new segment dialog (makeSeg())
let grp = parseInt(g.value);
let spc = parseInt(gId(`seg${s}spc`).value);
let ofs = parseInt(gId(`seg${s}of` ).value);
obj.seg.grp = grp;
obj.seg.spc = spc;
obj.seg.of = ofs;

View File

@@ -7,7 +7,7 @@
<title>2D Set-up</title>
<script>
var d=document;
var loc = false, locip;
var loc = false, locip;
var maxPanels=64;
var ctx = null; // WLEDMM
var ledIndex = 0; // WLEDMM
@@ -38,15 +38,15 @@
});
}
function S() {
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
@@ -91,12 +91,12 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
p.insertAdjacentHTML("beforeend", b);
}
function remPanel() {
function remPanel() {
let p = gId("panels").children;
var i = p.length;
if (i <= 1) return;
p[i-1].remove();
}
var i = p.length;
if (i <= 1) return;
p[i-1].remove();
}
function resetPanels() {
d.Sf.MPC.value = 1;
@@ -350,7 +350,7 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0" oni
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
</div>
<h2>2D setup</h2>
Strip or panel:
Strip or panel:
<select id="somp" name="SOMP" onchange="resetPanels();addPanels();UI();" >
<option value="0">1D Strip</option>
<option value="1">2D Matrix</option>

View File

@@ -1,72 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=500">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8">
<title>DMX Settings</title>
<script>
var d=document;
var loc = false, locip;
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
function B(){window.history.back();}
function GCH(num) {
d.getElementById('dmxchannels').innerHTML += "";
for (i=0;i<num;i++) {
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
}
}
function mMap(){
numCh=document.Sf.CN.value;
numGap=document.Sf.CG.value;
if (parseInt(numCh)>parseInt(numGap)) {
d.getElementById("gapwarning").style.display="block";
} else {
d.getElementById("gapwarning").style.display="none";
}
for (i=0;i<15;i++) {
if (i>=numCh) {
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
d.getElementById("CH"+(i+1)).disabled = true;
} else {
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
d.getElementById("CH"+(i+1)).disabled = false;
}
}
}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GCH(15);GetV();mMap();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script>
<style>@import url("style.css");</style>
<meta name="viewport" content="width=500">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8">
<title>DMX Settings</title>
<script>
var d=document;
var loc = false, locip;
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
function B(){window.history.back();}
function GCH(num) {
d.getElementById('dmxchannels').innerHTML += "";
for (i=0;i<num;i++) {
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
}
}
function mMap(){
numCh=document.Sf.CN.value;
numGap=document.Sf.CG.value;
if (parseInt(numCh)>parseInt(numGap)) {
d.getElementById("gapwarning").style.display="block";
} else {
d.getElementById("gapwarning").style.display="none";
}
for (i=0;i<15;i++) {
if (i>=numCh) {
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
d.getElementById("CH"+(i+1)).disabled = true;
} else {
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
d.getElementById("CH"+(i+1)).disabled = false;
}
}
}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GCH(15);GetV();mMap();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script>
<style>@import url("style.css");</style>
</head>
<body onload="S()">
<form id="form_s" name="Sf" method="post">

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@
<form id="form_s" name="Sf" method="post">
<h2>Please enter settings PIN code</h2>
<input type="password" name="PIN" size="4" maxlength="4" minlength="4" pattern="[0-9]*" inputmode="numeric" autofocus>
<hr>
<hr>
<button type="button" onclick="B()">Back</button><button type="submit">Submit</button>
</form>
</body>

View File

@@ -53,7 +53,7 @@
req.send(formData);
fO.value = '';
return false;
}
}
function checkNum(o) {
const specialkeys = ["Backspace", "Tab", "Enter", "Shift", "Control", "Alt", "Pause", "CapsLock", "Escape", "Space", "PageUp", "PageDown", "End", "Home", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", "Insert", "Delete"];
// true if key is a number or a special key

View File

@@ -1,76 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=500">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8">
<title>Sync Settings</title>
<script>var d=document;
var loc = false, locip;
function gId(s){return d.getElementById(s);}
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
function hideNoDMX(){gId("dmxOnOff2").style.display="none";}
function hideNoLOX(){gId("loxOnOff2").style.display="none";}
function H(){window.open("https://mm.kno.wled.ge/interfaces/udp-notifier/");}
function B(){window.open("/settings","_self");}
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();SetVal();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function FC()
{
for(j=0;j<8;j++)
{
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
}
}
function GC()
{
var a=0, b=0;
<meta name="viewport" content="width=500">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8">
<title>Sync Settings</title>
<script>var d=document;
var loc = false, locip;
function gId(s){return d.getElementById(s);}
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
function hideNoDMX(){gId("dmxOnOff2").style.display="none";} //WLEDMM
function hideNoLOX(){gId("loxOnOff2").style.display="none";} //WLEDMM
function H(){window.open("https://mm.kno.wled.ge/interfaces/udp-notifier/");}
function B(){window.open("/settings","_self");}
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();SetVal();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function FC()
{
for(j=0;j<8;j++)
{
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
}
}
function GC()
{
var a=0, b=0;
var m=1;
for(j=0;j<8;j++)
{
a+=gId("G"+(j+1)).checked*m;
b+=gId("R"+(j+1)).checked*m;
m*=2;
}
gId("GS").value=a;
gId("GR").value=b;
}
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
var m=1;
for(j=0;j<8;j++)
{
a+=gId("G"+(j+1)).checked*m;
b+=gId("R"+(j+1)).checked*m;
m*=2;
}
gId("GS").value=a;
gId("GR").value=b;
}
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
function S(){
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script>
<style>@import url("style.css");</style>
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
</script>
<style>@import url("style.css");</style>
</head>
<body onload="S()">
<form id="form_s" name="Sf" method="post" onsubmit="GC()">
@@ -86,39 +86,39 @@ UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required
<input name="GS" id="GS" type="number" style="display: none;"><!-- hidden inputs for bitwise group checkboxes -->
<input name="GR" id="GR" type="number" style="display: none;">
<table style="margin: 0 auto;">
<tr>
<td></td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>Send:</td>
<td><input type="checkbox" id="G1" name="G1"></td>
<td><input type="checkbox" id="G2" name="G2"></td>
<td><input type="checkbox" id="G3" name="G3"></td>
<td><input type="checkbox" id="G4" name="G4"></td>
<td><input type="checkbox" id="G5" name="G5"></td>
<td><input type="checkbox" id="G6" name="G6"></td>
<td><input type="checkbox" id="G7" name="G7"></td>
<td><input type="checkbox" id="G8" name="G8"></td>
</tr>
<tr>
<td>Receive:</td>
<td><input type="checkbox" id="R1" name="R1"></td>
<td><input type="checkbox" id="R2" name="R2"></td>
<td><input type="checkbox" id="R3" name="R3"></td>
<td><input type="checkbox" id="R4" name="R4"></td>
<td><input type="checkbox" id="R5" name="R5"></td>
<td><input type="checkbox" id="R6" name="R6"></td>
<td><input type="checkbox" id="R7" name="R7"></td>
<td><input type="checkbox" id="R8" name="R8"></td>
</tr>
<tr>
<td></td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>Send:</td>
<td><input type="checkbox" id="G1" name="G1"></td>
<td><input type="checkbox" id="G2" name="G2"></td>
<td><input type="checkbox" id="G3" name="G3"></td>
<td><input type="checkbox" id="G4" name="G4"></td>
<td><input type="checkbox" id="G5" name="G5"></td>
<td><input type="checkbox" id="G6" name="G6"></td>
<td><input type="checkbox" id="G7" name="G7"></td>
<td><input type="checkbox" id="G8" name="G8"></td>
</tr>
<tr>
<td>Receive:</td>
<td><input type="checkbox" id="R1" name="R1"></td>
<td><input type="checkbox" id="R2" name="R2"></td>
<td><input type="checkbox" id="R3" name="R3"></td>
<td><input type="checkbox" id="R4" name="R4"></td>
<td><input type="checkbox" id="R5" name="R5"></td>
<td><input type="checkbox" id="R6" name="R6"></td>
<td><input type="checkbox" id="R7" name="R7"></td>
<td><input type="checkbox" id="R8" name="R8"></td>
</tr>
</table><br>
Receive: <nowrap><input type="checkbox" name="RB">Brightness,</nowrap> <nowrap><input type="checkbox" name="RC">Color,</nowrap> <nowrap>and <input type="checkbox" name="RX">Effects</nowrap><br>
<input type="checkbox" name="SO"> Segment options, <input type="checkbox" name="SG"> bounds<br>
@@ -170,13 +170,13 @@ Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
Force max brightness: <input type="checkbox" name="FB"><br>
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
<div id="dmxOnOff2">
<div id="dmxOnOff2"> <!--WLEDMM-->
<br><em style="color:darkorange">This firmware build does not include DMX output support. <br></em>
</div>
<hr class="sml">
<h3>Alexa Voice Assistant</h3>
<div id="NoAlexa" class="hide">
<em style="color:#fa0;">This firmware build does not include Alexa support.<br></em><br>
<em style="color:#fa0;">This firmware build does not include Alexa support.<br></em><br>
</div>
<div id="Alexa">
Emulate Alexa device: <input type="checkbox" name="AL"><br>
@@ -192,7 +192,7 @@ For best results, only use one of these services at a time.<br>
<hr class="sml">
<h3>Blynk</h3>
<div id="NoBlynk" class="hide">
<em style="color:#fa0;">This firmware build does not include Blynk support.<br></em>
<em style="color:#fa0;">This firmware build does not include Blynk support.<br></em>
</div>
<div id="Blynk">
Host: <input type="text" name="BH" maxlength="32">
@@ -202,7 +202,7 @@ Device Auth token: <input name="BK" maxlength="33"><br>
</div>
<h3>MQTT</h3>
<div id="NoMQTT" class="hide">
<em style="color:#fa0;">This firmware build does not include MQTT support.<br></em>
<em style="color:#fa0;">This firmware build does not include MQTT support.<br></em>
</div>
<div id="MQTT">
Enable MQTT: <input type="checkbox" name="MQ"><br>
@@ -220,7 +220,7 @@ Publish on button press: <input type="checkbox" name="BM"><br>
</div>
<h3>Philips Hue</h3>
<div id="NoHue" class="hide">
<em style="color:#fa0;">This firmware build does not include Philips Hue support.<br></em>
<em style="color:#fa0;">This firmware build does not include Philips Hue support.<br></em>
</div>
<div id="Hue">
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
@@ -235,7 +235,7 @@ Hue Bridge IP:<br>
(when first connecting)<br>
</div>
Hue status: <span class="sip"> Disabled in this build </span>
<div id="loxOnOff2">
<div id="loxOnOff2"> <!--WLEDMM-->>
<br><em style="color:darkorange">This firmware build does not include Loxone Lighting support. <br></em>
</div>
<h3>Serial</h3>

View File

@@ -6,8 +6,8 @@
<meta charset="utf-8">
<title>Time Settings</title>
<script>
var d=document;
var loc = false, locip;
var d=document;
var loc = false, locip;
var el=false;
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function H() { window.open("https://mm.kno.wled.ge/features/settings/#time-settings"); }
@@ -156,7 +156,7 @@
</div>
<h2>Time setup</h2>
Get time from NTP server: <input type="checkbox" name="NT"><br>
<input type="text" name="NS" maxlength="32"><br>
<input type="text" name="NS" maxlength="32"><br>
Use 24h format: <input type="checkbox" name="CF"><br>
Time zone:
<select name="TZ">

View File

@@ -6,234 +6,234 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>UI Settings</title>
<script>
var d = document;
var loc = false, locip;
var initial_ds, initial_st, initial_su;
var sett = null;
var l = {
"comp":{
"labels":"Show button labels",
"colors":{
"LABEL":"Color selection methods",
"picker": "Color Wheel",
"rgb": "RGB sliders",
"quick": "Quick color selectors",
"hex": "HEX color input"
},
"pcmbot": "Show bottom tab bar in PC mode",
"pid": "Show preset IDs",
"seglen": "Set segment length instead of stop LED",
"segpwr": "Hide segment power &amp; brightness",
"segexp" : "Always expand first segment",
"css": "Enable custom CSS",
"hdays": "Enable custom Holidays list"
var d = document;
var loc = false, locip;
var initial_ds, initial_st, initial_su;
var sett = null;
var l = {
"comp":{
"labels":"Show button labels",
"colors":{
"LABEL":"Color selection methods",
"picker": "Color Wheel",
"rgb": "RGB sliders",
"quick": "Quick color selectors",
"hex": "HEX color input"
},
"pcmbot": "Show bottom tab bar in PC mode",
"pid": "Show preset IDs",
"seglen": "Set segment length instead of stop LED",
"segpwr": "Hide segment power &amp; brightness",
"segexp" : "Always expand first segment",
"css": "Enable custom CSS",
"hdays": "Enable custom Holidays list"
},
"theme":{
"alpha": {
"bg":"Background opacity",
"tab":"Button opacity"
},
"theme":{
"alpha": {
"bg":"Background opacity",
"tab":"Button opacity"
},
"bg":{
"url":"BG image URL",
"random":"Random BG image"
},
"color":{
"bg":"BG HEX color"
}
"bg":{
"url":"BG image URL",
"random":"Random BG image"
},
"color":{
"bg":"BG HEX color"
}
};
function gId(s) { return d.getElementById(s); }
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
}
function set(path, obj, val) {
var tar = obj;
var pList = path.split('_');
var len = pList.length;
for(var i = 0; i < len-1; i++) {
var elem = pList[i];
if( !tar[elem] ) tar[elem] = {}
tar = tar[elem];
}
tar[pList[len-1]] = val;
};
function gId(s) { return d.getElementById(s); }
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
}
function set(path, obj, val) {
var tar = obj;
var pList = path.split('_');
var len = pList.length;
for(var i = 0; i < len-1; i++) {
var elem = pList[i];
if( !tar[elem] ) tar[elem] = {}
tar = tar[elem];
}
var timeout;
function showToast(text, error = false)
tar[pList[len-1]] = val;
}
var timeout;
function showToast(text, error = false)
{
var x = gId("toast");
x.innerHTML = text;
x.classList.add(error ? "error":"show");
clearTimeout(timeout);
x.style.animation = 'none';
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
}
function addRec(s, path = "", label = null)
{
var str = "";
for (i in s)
{
var x = gId("toast");
x.innerHTML = text;
x.classList.add(error ? "error":"show");
clearTimeout(timeout);
x.style.animation = 'none';
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
}
function addRec(s, path = "", label = null)
{
var str = "";
for (i in s)
{
var fk = path + (path?'_':'') + i;
if (isObject(s[i])) {
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
str += addRec(s[i], fk, label? label[i] : null);
} else {
var lb = fk;
if (label && label[i]) lb = label[i];
else if (s[i+'LABEL']) lb = s[i+'LABEL'];
if (i.indexOf('LABEL') > 0) continue;
var t = typeof s[i];
if (gId(fk)) { //already exists
if(t === 'boolean')
{
gId(fk).checked = s[i];
} else {
gId(fk).value = s[i];
}
if (gId(fk).previousElementSibling.matches('.l')) {
gId(fk).previousElementSibling.innerHTML = lb;
}
var fk = path + (path?'_':'') + i;
if (isObject(s[i])) {
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
str += addRec(s[i], fk, label? label[i] : null);
} else {
var lb = fk;
if (label && label[i]) lb = label[i];
else if (s[i+'LABEL']) lb = s[i+'LABEL'];
if (i.indexOf('LABEL') > 0) continue;
var t = typeof s[i];
if (gId(fk)) { //already exists
if(t === 'boolean')
{
gId(fk).checked = s[i];
} else {
if(t === 'boolean')
{
str += `${lb}: <input class="agi cb" type="checkbox" id=${fk} ${s[i]?"checked":""}><br>`;
} else if (t === 'number')
{
str += `${lb}: <input class="agi" type="number" id=${fk} value=${s[i]}><br>`;
} else if (t === 'string')
{
str += `${lb}:<br><input class="agi" id=${fk} value=${s[i]}><br>`;
}
gId(fk).value = s[i];
}
if (gId(fk).previousElementSibling.matches('.l')) {
gId(fk).previousElementSibling.innerHTML = lb;
}
} else {
if(t === 'boolean')
{
str += `${lb}: <input class="agi cb" type="checkbox" id=${fk} ${s[i]?"checked":""}><br>`;
} else if (t === 'number')
{
str += `${lb}: <input class="agi" type="number" id=${fk} value=${s[i]}><br>`;
} else if (t === 'string')
{
str += `${lb}:<br><input class="agi" id=${fk} value=${s[i]}><br>`;
}
}
}
return str;
}
return str;
}
function genForm(s) {
var str = "";
str = addRec(s,"",l);
gId('gen').innerHTML = str;
function genForm(s) {
var str = "";
str = addRec(s,"",l);
gId('gen').innerHTML = str;
}
function GetLS()
{
sett = localStorage.getItem('wledUiCfg');
if (!sett) gId('lserr').style.display = "inline";
try {
sett = JSON.parse(sett);
} catch (e) {
sett = {};
gId('lserr').style.display = "inline";
gId('lserr').innerHTML = "&#9888; Settings JSON parsing failed. (" + e + ")";
}
function GetLS()
{
sett = localStorage.getItem('wledUiCfg');
if (!sett) gId('lserr').style.display = "inline";
try {
sett = JSON.parse(sett);
} catch (e) {
sett = {};
gId('lserr').style.display = "inline";
gId('lserr').innerHTML = "&#9888; Settings JSON parsing failed. (" + e + ")";
}
genForm(sett);
gId('dm').checked = (gId('theme_base').value === 'light');
genForm(sett);
gId('dm').checked = (gId('theme_base').value === 'light');
}
function SetLS()
{
var l = d.querySelectorAll('.agi');
for (var i = 0; i < l.length; i++) {
var e = l[i];
var val = e.classList.contains('cb') ? e.checked : e.value;
set(e.id, sett, val);
console.log(`${e.id} set to ${val}`);
}
try {
localStorage.setItem('wledUiCfg', JSON.stringify(sett));
gId('lssuc').style.display = "inline";
} catch (e) {
gId('lssuc').style.display = "none";
gId('lserr').style.display = "inline";
gId('lserr').innerHTML = "&#9888; Settings JSON saving failed. (" + e + ")";
}
}
function cLS()
{
localStorage.removeItem('wledP');
localStorage.removeItem('wledPmt');
localStorage.removeItem('wledPalx');
showToast("Cleared.");
}
function SetLS()
{
var l = d.querySelectorAll('.agi');
for (var i = 0; i < l.length; i++) {
var e = l[i];
var val = e.classList.contains('cb') ? e.checked : e.value;
set(e.id, sett, val);
console.log(`${e.id} set to ${val}`);
}
try {
localStorage.setItem('wledUiCfg', JSON.stringify(sett));
gId('lssuc').style.display = "inline";
} catch (e) {
gId('lssuc').style.display = "none";
gId('lserr').style.display = "inline";
gId('lserr').innerHTML = "&#9888; Settings JSON saving failed. (" + e + ")";
function Save() {
SetLS();
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
initial_ds = d.Sf.DS.value;
initial_st = d.Sf.ST.checked;
initial_su = d.Sf.SU.checked;
GetLS();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S()
{
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
function H() { window.open("https://mm.kno.wled.ge/features/settings/#user-interface-settings"); }
function B() { window.open("/settings","_self"); }
function UI()
{
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
var f = gId('theme_base');
if (f) f.value = (gId('dm').checked) ? 'light':'dark';
}
function cLS()
{
localStorage.removeItem('wledP');
localStorage.removeItem('wledPmt');
localStorage.removeItem('wledPalx');
showToast("Cleared.");
// random BG image
function setRandomBg() {
if (gId("theme_bg_random").checked) {
gId("theme_bg_url").value = "https://picsum.photos/1920/1080";
} else {
gId("theme_bg_url").value = "";
}
function Save() {
SetLS();
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
}
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
function loadJS(FILE_URL, async = true) {
let scE = d.createElement("script");
scE.setAttribute("src", FILE_URL);
scE.setAttribute("type", "text/javascript");
scE.setAttribute("async", async);
d.body.appendChild(scE);
// success event
scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();
initial_ds = d.Sf.DS.value;
initial_st = d.Sf.ST.checked;
initial_su = d.Sf.SU.checked;
GetLS();
});
// error event
scE.addEventListener("error", (ev) => {
console.log("Error on loading file", ev);
alert("Loading of configuration script failed.\nIncomplete page data!");
});
}
function S()
{
if (window.location.protocol == "file:") {
loc = true;
locip = localStorage.getItem('locIp');
if (!locip) {
locip = prompt("File Mode. Please enter WLED IP!");
localStorage.setItem('locIp', locip);
}
}
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
}
function H() { window.open("https://mm.kno.wled.ge/features/settings/#user-interface-settings"); }
function B() { window.open("/settings","_self"); }
function UI()
{
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
var f = gId('theme_base');
if (f) f.value = (gId('dm').checked) ? 'light':'dark';
}
// random BG image
function setRandomBg() {
if (gId("theme_bg_random").checked) {
gId("theme_bg_url").value = "https://picsum.photos/1920/1080";
} else {
gId("theme_bg_url").value = "";
}
}
function checkRandomBg() {
if (gId("theme_bg_url").value === "https://picsum.photos/1920/1080") {
gId("theme_bg_random").checked = true;
} else {
gId("theme_bg_random").checked = false;
}
}
function uploadFile(fO,name) {
var req = new XMLHttpRequest();
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
req.addEventListener('error', function(e){showToast(e.stack,true);});
req.open("POST", "/upload");
var formData = new FormData();
formData.append("data", fO.files[0], name);
req.send(formData);
fO.value = '';
return false;
}
function checkRandomBg() {
if (gId("theme_bg_url").value === "https://picsum.photos/1920/1080") {
gId("theme_bg_random").checked = true;
} else {
gId("theme_bg_random").checked = false;
}
}
function uploadFile(fO,name) {
var req = new XMLHttpRequest();
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
req.addEventListener('error', function(e){showToast(e.stack,true);});
req.open("POST", "/upload");
var formData = new FormData();
formData.append("data", fO.files[0], name);
req.send(formData);
fO.value = '';
return false;
}
</script>
<style>@import url("style.css");</style>
</head>

View File

@@ -264,19 +264,20 @@ class Usermod {
virtual ~Usermod() { if (um_data) delete um_data; }
virtual void setup() = 0; // pure virtual, has to be overriden
virtual void loop() = 0; // pure virtual, has to be overriden
virtual void handleOverlayDraw() {}
virtual bool handleButton(uint8_t b) { return false; }
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; };
virtual void connected() {}
virtual void appendConfigData() {}
virtual void addToJsonState(JsonObject& obj) {}
virtual void addToJsonInfo(JsonObject& obj) {}
virtual void readFromJsonState(JsonObject& obj) {}
virtual void addToConfig(JsonObject& obj) {}
virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show()
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
virtual void connected() {} // called when WiFi is (re)connected
virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields
virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
virtual void addToConfig(JsonObject& obj) {} // add JSON entries that go to cfg.json
virtual bool readFromConfig(JsonObject& obj) { return true; } // Note as of 2021-06 readFromConfig() now needs to return a bool, see usermod_v2_example.h
virtual void onMqttConnect(bool sessionPresent) {}
virtual bool onMqttMessage(char* topic, char* payload) { return false; }
virtual void onUpdateBegin(bool) {}
virtual void onMqttConnect(bool sessionPresent) {} // fired when MQTT connection is established (so usermod can subscribe)
virtual bool onMqttMessage(char* topic, char* payload) { return false; } // fired upon MQTT message received (wled topic)
virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update
virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change
virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;}
};
@@ -301,6 +302,7 @@ class UsermodManager {
void onMqttConnect(bool sessionPresent);
bool onMqttMessage(char* topic, char* payload);
void onUpdateBegin(bool);
void onStateChange(uint8_t);
bool add(Usermod* um);
Usermod* lookup(uint16_t mod_id);
Usermod* lookupName(const char *mod_name); //WLEDMM

View File

@@ -287,481 +287,481 @@ const uint8_t PAGE_settings_wifi[] PROGMEM = {
// Autogenerated from wled00/data/settings_leds.htm, do not edit!!
const uint16_t PAGE_settings_leds_length = 7564;
const uint16_t PAGE_settings_leds_length = 7555;
const uint8_t PAGE_settings_leds[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xdd, 0x3c, 0xdb, 0x76, 0xe2, 0x48,
0x92, 0xef, 0x7c, 0x45, 0x3a, 0xbb, 0xc7, 0x25, 0x0d, 0x32, 0x48, 0x5c, 0xdc, 0x2e, 0x40, 0x78,
0x8d, 0xeb, 0xd2, 0x9e, 0xb1, 0xdb, 0x3e, 0xc6, 0xdd, 0x35, 0x73, 0xaa, 0xeb, 0x54, 0x09, 0x29,
0x01, 0x95, 0x85, 0xc4, 0x48, 0xc2, 0x36, 0x6b, 0x7b, 0xbf, 0x69, 0xbf, 0x61, 0xbf, 0x6c, 0x23,
0x32, 0x53, 0x37, 0x90, 0xb0, 0x7b, 0x66, 0xf6, 0x65, 0xfb, 0x9c, 0x2e, 0x83, 0x14, 0x19, 0x19,
0x19, 0x19, 0xf7, 0x8c, 0x64, 0xb0, 0xf7, 0xee, 0xf2, 0xf4, 0xe6, 0xef, 0x57, 0xef, 0xc9, 0x3c,
0x5e, 0x78, 0xc3, 0x01, 0xfe, 0x4b, 0x3c, 0xcb, 0x9f, 0x99, 0x94, 0xf9, 0x14, 0xbe, 0x33, 0xcb,
0x19, 0x0e, 0x16, 0x2c, 0xb6, 0x88, 0x3d, 0xb7, 0xc2, 0x88, 0xc5, 0x26, 0x5d, 0xc5, 0xd3, 0x83,
0x23, 0x2a, 0x9f, 0xd6, 0x7c, 0x6b, 0xc1, 0x4c, 0x7a, 0xe7, 0xb2, 0xfb, 0x65, 0x10, 0xc6, 0x94,
0xd8, 0x81, 0x1f, 0x33, 0x1f, 0xc0, 0xee, 0x5d, 0x27, 0x9e, 0x9b, 0x5d, 0x5d, 0x4f, 0x41, 0x37,
0x5e, 0x39, 0xec, 0xce, 0xb5, 0xd9, 0x01, 0xff, 0xa2, 0xb9, 0xbe, 0x1b, 0xbb, 0x96, 0x77, 0x10,
0xd9, 0x96, 0xc7, 0x4c, 0x43, 0x5b, 0x58, 0x0f, 0xee, 0x62, 0xb5, 0x48, 0xbf, 0xaf, 0x22, 0x16,
0xf2, 0x2f, 0xd6, 0x04, 0xbe, 0xfb, 0x01, 0xdd, 0x9a, 0x79, 0x38, 0x88, 0xdd, 0xd8, 0x63, 0xc3,
0xf3, 0xf7, 0xef, 0xc8, 0x98, 0xc5, 0xb1, 0xeb, 0xcf, 0xa2, 0x41, 0x53, 0x3c, 0x1b, 0x44, 0x76,
0xe8, 0x2e, 0xe3, 0x61, 0xed, 0xce, 0x0a, 0x89, 0x17, 0xd8, 0xee, 0x52, 0x8b, 0xdd, 0x05, 0x0b,
0x56, 0xb1, 0xe6, 0x98, 0x4e, 0x60, 0xaf, 0x16, 0x40, 0x97, 0xe6, 0x59, 0xcb, 0x90, 0xdd, 0x99,
0xdd, 0x2e, 0xce, 0x3e, 0x12, 0x44, 0xfc, 0x66, 0xea, 0xf8, 0xe7, 0xc2, 0xec, 0xb0, 0x36, 0x7e,
0xb8, 0x1a, 0x99, 0x1d, 0xfd, 0xed, 0x21, 0x7e, 0x3c, 0x37, 0x8d, 0x76, 0x9b, 0x3f, 0x3c, 0x9f,
0xfc, 0x63, 0x15, 0xc4, 0x00, 0x69, 0xaf, 0xa2, 0x38, 0x58, 0x8c, 0x63, 0x2b, 0x8c, 0x23, 0x73,
0xcf, 0xd0, 0x22, 0xfe, 0xe9, 0x9d, 0x1b, 0xc6, 0x6b, 0xf3, 0xf3, 0x17, 0x04, 0x3d, 0xbd, 0xbc,
0xbc, 0x63, 0x61, 0xe8, 0x3a, 0x2c, 0x32, 0xbb, 0x1a, 0x90, 0x02, 0x60, 0xfd, 0xe9, 0xca, 0xb7,
0x63, 0x37, 0xf0, 0xc9, 0xcf, 0x8a, 0xfa, 0x78, 0xef, 0xfa, 0x4e, 0x70, 0xdf, 0x08, 0x96, 0xcc,
0x57, 0xe8, 0x3c, 0x8e, 0x97, 0x51, 0xaf, 0xd9, 0x5c, 0x2c, 0x1a, 0xb7, 0x7e, 0xd0, 0xb8, 0xf7,
0x98, 0xd3, 0x98, 0xb1, 0xe6, 0x94, 0x59, 0xf1, 0x2a, 0x64, 0x51, 0x33, 0x92, 0x0b, 0x6d, 0xfe,
0x00, 0x6f, 0x0e, 0x92, 0x6f, 0x54, 0x7d, 0x4e, 0x51, 0x8e, 0x36, 0x51, 0xa6, 0x63, 0xa8, 0x46,
0xbf, 0x46, 0xcc, 0x9b, 0xe6, 0xa1, 0x67, 0x67, 0x8e, 0xc2, 0xd4, 0xc7, 0x90, 0x01, 0x7a, 0x9f,
0xe0, 0x5c, 0xf1, 0x7b, 0x8f, 0x21, 0x77, 0x46, 0x6b, 0xfe, 0x2a, 0x03, 0x9d, 0xc3, 0x1a, 0x7e,
0x09, 0xce, 0xae, 0x01, 0x3f, 0x8e, 0xa2, 0x6e, 0x78, 0xe9, 0x5f, 0x4e, 0xa7, 0x2d, 0xaa, 0x36,
0xa2, 0x78, 0xed, 0xb1, 0x86, 0xe3, 0x46, 0x4b, 0xcf, 0x5a, 0x9b, 0xd4, 0x0f, 0x7c, 0x46, 0xb3,
0x81, 0xc1, 0x74, 0x8a, 0x73, 0xe4, 0x91, 0x47, 0xa3, 0xf5, 0x2f, 0xb0, 0x9b, 0xf0, 0xf8, 0xb3,
0xfe, 0xa5, 0x71, 0x67, 0x79, 0x2b, 0x66, 0x1e, 0x18, 0xd9, 0x10, 0x2f, 0xb0, 0x9c, 0xbf, 0x8c,
0x15, 0xa6, 0xf9, 0xe6, 0x9e, 0xae, 0x3e, 0x7a, 0x2c, 0x26, 0xb1, 0xe9, 0x34, 0xec, 0x10, 0xf8,
0xc0, 0x24, 0x0e, 0x85, 0x8a, 0x4d, 0xa6, 0x6a, 0x3f, 0x6e, 0xc0, 0x1a, 0x4f, 0xe2, 0x38, 0x74,
0x27, 0xab, 0x98, 0xc1, 0x8b, 0xd0, 0xa6, 0x1a, 0x53, 0xb5, 0xcd, 0xe7, 0xf1, 0x7a, 0xc9, 0x80,
0x0b, 0x31, 0x7b, 0x88, 0x9b, 0xdf, 0xad, 0x3b, 0x2b, 0x41, 0xb0, 0x05, 0x68, 0x45, 0x6b, 0x1f,
0x50, 0xf8, 0xaa, 0xe6, 0x34, 0x26, 0x81, 0xb3, 0x6e, 0x58, 0x4b, 0xe0, 0xa5, 0x73, 0x3a, 0x77,
0x3d, 0x47, 0x89, 0x11, 0xde, 0x72, 0x9c, 0xf7, 0x77, 0x40, 0xc5, 0xb9, 0x1b, 0x81, 0x8c, 0xb3,
0x50, 0xa1, 0x48, 0x33, 0xd5, 0x14, 0xd5, 0x1c, 0x3e, 0x7e, 0x64, 0xf1, 0x6f, 0x8a, 0xaa, 0xd9,
0x73, 0x66, 0xdf, 0x8e, 0x5d, 0xf8, 0x84, 0xd8, 0x47, 0xe7, 0xf0, 0xe1, 0xc0, 0x30, 0x61, 0x1d,
0xab, 0xc5, 0xd7, 0x25, 0x2c, 0x7c, 0x7f, 0x5f, 0x7c, 0x6c, 0x44, 0x73, 0x77, 0x1a, 0x2b, 0xea,
0x73, 0x39, 0x62, 0x10, 0x9f, 0x20, 0x84, 0xf5, 0x00, 0x62, 0xd0, 0xa8, 0x28, 0x00, 0x56, 0x7b,
0xc1, 0x4c, 0xa1, 0xef, 0xf1, 0x39, 0x91, 0xdc, 0x82, 0x0d, 0x26, 0x53, 0xd7, 0x63, 0x7c, 0xdd,
0xa0, 0x42, 0x21, 0xf0, 0xe7, 0x5c, 0x3e, 0x0f, 0xa6, 0xa8, 0xa5, 0x53, 0x77, 0xb6, 0x0a, 0x2d,
0xce, 0x5e, 0xb1, 0x6e, 0x32, 0xb5, 0x5c, 0x94, 0xaf, 0xdf, 0xfd, 0x33, 0xdf, 0x0e, 0x16, 0x4b,
0xe0, 0x32, 0x23, 0x4b, 0x6b, 0xc6, 0x88, 0x63, 0xc5, 0xd6, 0x1e, 0x88, 0x49, 0x6e, 0xf7, 0xa3,
0x79, 0x70, 0x7f, 0x13, 0x58, 0x51, 0x2c, 0x36, 0xc5, 0x50, 0x1f, 0x51, 0xb5, 0x62, 0x93, 0x8b,
0x42, 0x8c, 0x2f, 0xf8, 0x3e, 0xb8, 0x3e, 0x90, 0xfc, 0xf3, 0xcd, 0xc5, 0xb9, 0xc9, 0x60, 0x2d,
0xb6, 0x67, 0x45, 0x11, 0x6e, 0xb4, 0xe9, 0x1f, 0xcb, 0x65, 0xf4, 0x28, 0x62, 0xa2, 0x9a, 0xed,
0x31, 0x2b, 0xbc, 0x11, 0x3a, 0xa9, 0x48, 0xdd, 0xe4, 0xfb, 0xc0, 0x45, 0xc9, 0xf2, 0xdd, 0x05,
0x27, 0x55, 0x0a, 0x53, 0xa2, 0xbd, 0x26, 0x30, 0x32, 0x19, 0xa4, 0x24, 0xb4, 0x81, 0x40, 0xe6,
0xa7, 0xca, 0x7d, 0x6e, 0x84, 0x0c, 0x24, 0xd2, 0x46, 0x89, 0xe0, 0x93, 0x52, 0x5c, 0x93, 0xd6,
0x7a, 0xab, 0xeb, 0xb9, 0x95, 0x4d, 0xce, 0xdd, 0x85, 0x1b, 0x47, 0xb8, 0x2e, 0x2d, 0xd6, 0x5c,
0xcd, 0x52, 0x1f, 0xb9, 0x39, 0x60, 0xc2, 0x1c, 0xf8, 0xc2, 0x1c, 0xb8, 0xd2, 0x18, 0xc4, 0xc2,
0x12, 0x58, 0xd9, 0xf8, 0xa5, 0xeb, 0x47, 0x97, 0x7f, 0x55, 0x04, 0x43, 0x98, 0xb9, 0x21, 0xe6,
0x37, 0xd6, 0x8c, 0x4b, 0x3a, 0x75, 0xfd, 0xe5, 0x0a, 0x79, 0x34, 0x0d, 0x42, 0xc5, 0x35, 0xf5,
0xbe, 0x3b, 0x80, 0x6d, 0x64, 0xfe, 0x2c, 0x9e, 0xf7, 0xdd, 0x7a, 0x5d, 0x8c, 0xf6, 0x4d, 0xf6,
0xd9, 0xfd, 0xd2, 0x40, 0x43, 0xd7, 0x88, 0x56, 0x93, 0x08, 0xe4, 0xd1, 0x9f, 0x29, 0xba, 0xd6,
0x52, 0xfb, 0xee, 0x14, 0xf6, 0x53, 0xa7, 0xa6, 0xe9, 0x3f, 0x3d, 0xd1, 0x73, 0x23, 0xf9, 0xd0,
0x4a, 0x3e, 0xb4, 0xf1, 0x43, 0xb2, 0x29, 0x65, 0x58, 0x04, 0x8e, 0x25, 0xda, 0xf4, 0x33, 0x50,
0x9e, 0x32, 0x6d, 0xa4, 0xe7, 0x37, 0xb4, 0x1e, 0x67, 0x2a, 0xa9, 0x19, 0xba, 0x3a, 0x34, 0x8f,
0x74, 0x15, 0x0d, 0xb9, 0xeb, 0xaf, 0xd8, 0x33, 0x60, 0x78, 0x05, 0x19, 0xf8, 0xa1, 0x23, 0x3f,
0x5c, 0x9f, 0xcb, 0x0f, 0xa3, 0x1b, 0xf9, 0xe1, 0xec, 0x9a, 0x93, 0xba, 0xbf, 0x4f, 0xe9, 0x9e,
0xa0, 0x94, 0x4f, 0x06, 0xdf, 0x0f, 0x8c, 0xc2, 0x13, 0xb1, 0x1a, 0x0b, 0x0c, 0x29, 0x67, 0xda,
0x2d, 0x30, 0xed, 0x76, 0xe0, 0x34, 0xc2, 0xe8, 0xce, 0x49, 0x38, 0x77, 0x0b, 0x9c, 0xb3, 0x1a,
0xcb, 0x55, 0x34, 0x57, 0xc4, 0x8b, 0xcf, 0xb7, 0x5f, 0xd4, 0x02, 0x34, 0xd7, 0xaf, 0x32, 0x68,
0xae, 0x83, 0x08, 0x0d, 0x6b, 0xb2, 0x1a, 0x51, 0x00, 0xeb, 0xf7, 0xcd, 0xa1, 0x6f, 0x9a, 0x29,
0x8b, 0x32, 0x4a, 0x90, 0x11, 0xaa, 0x2a, 0x8d, 0xa4, 0x50, 0xae, 0x6f, 0xe3, 0x20, 0x0c, 0xd7,
0x1a, 0xdf, 0x7d, 0xf2, 0xe3, 0xe3, 0x5f, 0xc6, 0x97, 0xbf, 0x34, 0x04, 0xa7, 0xdd, 0xe9, 0x5a,
0xb1, 0xd4, 0x67, 0x62, 0x5b, 0xfe, 0x9b, 0x98, 0x4c, 0x18, 0x01, 0x57, 0xe6, 0x34, 0xbe, 0xa9,
0x5a, 0x86, 0xcf, 0xa4, 0x54, 0x7c, 0x9b, 0x82, 0x2b, 0x8a, 0xc0, 0x2c, 0x80, 0x4f, 0xc0, 0x0d,
0x06, 0xd6, 0xec, 0x99, 0x3e, 0x70, 0x02, 0x98, 0xc5, 0x3f, 0xc0, 0xa2, 0x82, 0xaf, 0xb3, 0xa5,
0x1b, 0xfc, 0xbb, 0x09, 0x4c, 0x11, 0x03, 0xa1, 0x56, 0xc8, 0x08, 0x97, 0x4e, 0xb0, 0x25, 0xde,
0xfa, 0x65, 0x4a, 0x91, 0xbd, 0xdf, 0x4d, 0xb7, 0x6e, 0xf4, 0xbf, 0x67, 0x32, 0xfc, 0x3d, 0x91,
0xe1, 0x00, 0x76, 0xf0, 0xfb, 0x0b, 0x32, 0x1c, 0x24, 0xc2, 0x13, 0x24, 0xc2, 0x13, 0x24, 0xc2,
0x13, 0x24, 0xc2, 0x13, 0x24, 0xc2, 0x13, 0x24, 0xc2, 0x13, 0x24, 0xc2, 0x13, 0xa8, 0x8f, 0x1c,
0x15, 0x7c, 0x34, 0x83, 0xc2, 0x24, 0x86, 0x2a, 0x88, 0xf0, 0x4a, 0x89, 0x78, 0xad, 0x0a, 0x78,
0x2f, 0xa8, 0x80, 0x10, 0xdc, 0xef, 0xa9, 0xe0, 0xe6, 0xd8, 0x95, 0x7b, 0xbe, 0xb1, 0x1d, 0x57,
0xae, 0xcf, 0xad, 0xb0, 0xe7, 0xda, 0x28, 0x15, 0xf1, 0x3d, 0x63, 0x3e, 0xec, 0x4b, 0xaa, 0xaa,
0xcf, 0x4d, 0xfc, 0x22, 0x89, 0x7e, 0xde, 0xe3, 0xbb, 0xf0, 0xbd, 0xb0, 0x0b, 0xdf, 0xf3, 0xbb,
0xf0, 0x0c, 0xff, 0x89, 0x09, 0xf6, 0xf4, 0xcc, 0x16, 0xc5, 0xe1, 0x7a, 0xbc, 0x9a, 0x80, 0x39,
0x43, 0x87, 0x0b, 0x94, 0x3a, 0x8d, 0xf1, 0xb4, 0x81, 0xd6, 0x3c, 0x87, 0xa7, 0x81, 0x41, 0x0f,
0x2c, 0xf9, 0x1d, 0x9b, 0x5a, 0x2b, 0x2f, 0x46, 0x6c, 0x89, 0x09, 0x4b, 0x48, 0x06, 0xa6, 0xc5,
0xc1, 0xf2, 0x2a, 0x0c, 0xc0, 0x1b, 0x58, 0xc2, 0xc4, 0x4a, 0x11, 0xe5, 0x81, 0xcf, 0xd0, 0x00,
0x03, 0x2a, 0x0d, 0x16, 0xbd, 0x09, 0x02, 0xb2, 0xb0, 0xfc, 0x35, 0x81, 0x38, 0x2c, 0x22, 0x20,
0x1b, 0x64, 0xc1, 0x48, 0x1c, 0x90, 0xb9, 0xe5, 0x3b, 0x1e, 0xdb, 0xa3, 0x7d, 0x34, 0x9f, 0x03,
0x83, 0x75, 0xf6, 0xf7, 0x15, 0xbf, 0x6e, 0xd2, 0xdf, 0xfd, 0xdf, 0xc3, 0x53, 0x70, 0x63, 0x10,
0x4d, 0x84, 0xa0, 0x1a, 0xe8, 0x9f, 0x2c, 0x9f, 0xbc, 0x1f, 0x5f, 0xb5, 0x5b, 0x0d, 0x9a, 0xb8,
0x2e, 0x5f, 0x7d, 0xe6, 0xa4, 0x73, 0x0f, 0xfa, 0x9b, 0xe5, 0xb9, 0x8e, 0x1b, 0xaf, 0x15, 0x15,
0x15, 0x02, 0x9e, 0x46, 0x62, 0x89, 0x39, 0x1b, 0xce, 0x7c, 0xee, 0x5e, 0xa5, 0x09, 0xe6, 0x3e,
0x09, 0xe3, 0x46, 0x08, 0x4d, 0x38, 0x06, 0xe6, 0xf4, 0xf9, 0xc0, 0xf3, 0x13, 0xc9, 0x07, 0x76,
0x2c, 0x62, 0xbf, 0x9e, 0xae, 0x25, 0xc0, 0x5b, 0x61, 0x0c, 0x3b, 0x06, 0x9b, 0xed, 0xb9, 0xe0,
0x7d, 0x7a, 0xd2, 0x09, 0x71, 0xd0, 0x65, 0xb4, 0x6a, 0xbd, 0x02, 0xb6, 0x30, 0xdf, 0x50, 0xdf,
0xdf, 0x4f, 0x42, 0x80, 0x3c, 0xd1, 0xe7, 0x27, 0x39, 0xb7, 0xc1, 0xe1, 0x21, 0x3e, 0x13, 0x43,
0x36, 0x09, 0x16, 0x93, 0x9f, 0x9f, 0xc0, 0x8c, 0x5b, 0xb3, 0x77, 0x75, 0xb3, 0x84, 0x82, 0x5f,
0xcf, 0xf2, 0x93, 0x25, 0xd3, 0x3f, 0x46, 0xf7, 0x6e, 0x6c, 0xcf, 0x95, 0x12, 0x1e, 0x41, 0xa8,
0xa5, 0x6d, 0x92, 0x01, 0xb8, 0xb5, 0x9c, 0xc2, 0xe4, 0x48, 0x02, 0x4d, 0xb3, 0xad, 0x88, 0x11,
0xbd, 0x57, 0x8a, 0xca, 0xd0, 0xe4, 0x9e, 0xf4, 0x27, 0x10, 0xb4, 0xdd, 0xf6, 0x39, 0x6c, 0x5b,
0xef, 0x6d, 0x4d, 0xd0, 0xd6, 0x0b, 0x10, 0xdd, 0x12, 0x88, 0x6e, 0x1e, 0xa2, 0x5b, 0x02, 0xd1,
0x2d, 0x40, 0xb4, 0xca, 0x40, 0x5a, 0x29, 0x8c, 0x23, 0xe4, 0xbe, 0xb7, 0x83, 0xa1, 0x09, 0x2b,
0x9f, 0x39, 0xcc, 0xc2, 0x00, 0x80, 0x2c, 0xb0, 0x41, 0x79, 0xd6, 0x4a, 0x6d, 0xc7, 0x18, 0x42,
0x6b, 0xb4, 0x1c, 0xdb, 0x21, 0x9c, 0x90, 0x58, 0x08, 0x63, 0x12, 0xfd, 0x54, 0x37, 0xb6, 0x07,
0xb0, 0x5d, 0xb0, 0x05, 0xc6, 0x20, 0x49, 0xb4, 0xfb, 0x82, 0x99, 0x3a, 0xa5, 0x75, 0x3f, 0x33,
0x53, 0x6a, 0x5f, 0x6a, 0x6e, 0x5c, 0x7f, 0x61, 0xe0, 0xf8, 0xbc, 0x38, 0x50, 0x63, 0x83, 0x76,
0xeb, 0x38, 0xd3, 0xd1, 0xb6, 0x69, 0x96, 0x4f, 0xa8, 0x17, 0xc6, 0x1d, 0xb3, 0x61, 0xeb, 0xed,
0x71, 0x4b, 0xff, 0x73, 0xdc, 0x33, 0xba, 0xf0, 0x0f, 0x22, 0x18, 0x9a, 0x80, 0x41, 0xbc, 0x38,
0x82, 0x47, 0x87, 0xf0, 0x3f, 0xff, 0xd2, 0x81, 0x0f, 0x6d, 0xfe, 0xa5, 0x6d, 0x80, 0xb1, 0x1c,
0x74, 0x8e, 0x8e, 0xbb, 0xbd, 0x4e, 0x07, 0x64, 0xf6, 0xe9, 0xa9, 0xd3, 0x45, 0xd1, 0x95, 0x10,
0x19, 0x3b, 0x80, 0x39, 0x2c, 0x0d, 0x32, 0x31, 0xdc, 0xd4, 0x20, 0xdb, 0xea, 0x0b, 0x41, 0x5b,
0x2c, 0xef, 0xad, 0xd0, 0x07, 0xbb, 0xb1, 0xb5, 0x6d, 0x7c, 0xd3, 0x2f, 0x12, 0x9d, 0xfb, 0xa9,
0xa5, 0xeb, 0x5b, 0x4a, 0x01, 0x62, 0x60, 0x9a, 0x05, 0x39, 0x96, 0x96, 0xc0, 0x34, 0x5a, 0xbd,
0x2d, 0x9d, 0x55, 0xe4, 0xbb, 0xa2, 0xe0, 0xf7, 0x45, 0x58, 0x52, 0x15, 0xe8, 0x81, 0xcc, 0x31,
0xbb, 0x18, 0xe9, 0x59, 0xf9, 0x48, 0x8f, 0xbb, 0x2e, 0xf4, 0x67, 0x56, 0x45, 0xac, 0x97, 0xf8,
0x51, 0xab, 0x34, 0x8a, 0xd3, 0xbc, 0x6c, 0x87, 0xad, 0x42, 0x00, 0x20, 0xf8, 0xb3, 0xd4, 0x1d,
0x5a, 0x0f, 0xf2, 0x02, 0xeb, 0xa1, 0x03, 0xdb, 0xdf, 0xf7, 0x06, 0x6f, 0x0f, 0x8f, 0xe9, 0xd9,
0x15, 0x01, 0xf1, 0x84, 0x54, 0x32, 0xea, 0xd1, 0x9e, 0x37, 0xec, 0xbc, 0x3d, 0xa6, 0xef, 0xc0,
0x3f, 0x90, 0x8f, 0x57, 0x67, 0x97, 0xe2, 0x89, 0x71, 0x4c, 0xf1, 0x0b, 0xbe, 0xa7, 0xe2, 0xa9,
0x34, 0x7c, 0xc6, 0x36, 0xe2, 0xce, 0x5b, 0xc4, 0x7b, 0xd8, 0x39, 0xa6, 0xa7, 0xde, 0x6d, 0x82,
0x83, 0x52, 0xce, 0xa1, 0xa8, 0x42, 0x90, 0x0c, 0xc4, 0x02, 0x82, 0xc4, 0xf9, 0x03, 0xf2, 0x2a,
0x45, 0xdf, 0xd3, 0x02, 0x55, 0x9b, 0x9a, 0x10, 0x5e, 0x0c, 0xba, 0xfd, 0x29, 0x46, 0x13, 0x4a,
0x15, 0x06, 0x5a, 0x9f, 0x0a, 0x14, 0x2a, 0x6e, 0x51, 0xb6, 0xba, 0xfd, 0xfd, 0xe9, 0xa0, 0xf3,
0xf4, 0x24, 0xc8, 0x82, 0x44, 0x6b, 0xca, 0x3f, 0x1b, 0xf8, 0xb2, 0x0b, 0x20, 0xd3, 0x7a, 0x47,
0x1f, 0x78, 0xc7, 0x4a, 0x54, 0xa1, 0xed, 0x5a, 0x04, 0xf9, 0xc2, 0x3f, 0x56, 0x6e, 0xc8, 0x4d,
0xa1, 0xda, 0xdb, 0x06, 0x14, 0x32, 0x94, 0x07, 0x83, 0x94, 0x3f, 0x75, 0xad, 0xaa, 0xfa, 0x0c,
0xc1, 0x80, 0xb0, 0xac, 0xe1, 0x94, 0xf3, 0x2a, 0x31, 0x87, 0x25, 0xcf, 0x9e, 0x9e, 0xda, 0x40,
0xa2, 0xa7, 0x79, 0x5c, 0x2b, 0x3c, 0xd0, 0x0a, 0x18, 0x5b, 0xa9, 0xeb, 0x41, 0x2e, 0x51, 0x86,
0x20, 0x47, 0xcb, 0x23, 0x0c, 0x7c, 0x1b, 0x82, 0x8a, 0x5b, 0x93, 0xe3, 0x3b, 0xc6, 0x04, 0x74,
0xcf, 0xe8, 0xf1, 0x3c, 0xf4, 0x19, 0x52, 0xb5, 0x36, 0x38, 0x07, 0x4f, 0x4e, 0xc6, 0xf9, 0xc1,
0x99, 0xd5, 0x01, 0x66, 0x75, 0xda, 0x7b, 0xf8, 0xe8, 0xe8, 0x08, 0xc9, 0xe0, 0x08, 0xed, 0x80,
0x23, 0x2c, 0xae, 0x3a, 0xc7, 0x60, 0x1c, 0x6f, 0x4a, 0x04, 0x47, 0xc7, 0x82, 0x1d, 0xbd, 0x94,
0x7d, 0x1c, 0x85, 0xe3, 0xce, 0x00, 0x47, 0x9d, 0xde, 0x6f, 0x69, 0x67, 0x9e, 0x90, 0x2d, 0xbd,
0x6c, 0xeb, 0x40, 0x0b, 0x58, 0x1f, 0x83, 0xff, 0x29, 0xe7, 0xc3, 0xa7, 0xcb, 0x22, 0x1f, 0x74,
0xb5, 0x38, 0xa5, 0x4d, 0x4b, 0x48, 0x7f, 0x1d, 0xb5, 0x21, 0xdd, 0xb1, 0xea, 0xdd, 0x43, 0x23,
0xfa, 0xef, 0x61, 0xd8, 0xb4, 0x0c, 0x8f, 0x71, 0x88, 0x43, 0xdb, 0x2d, 0x8e, 0xa7, 0xab, 0x27,
0xca, 0x56, 0x16, 0x97, 0x24, 0x78, 0xac, 0x2d, 0x3c, 0x90, 0x47, 0x74, 0x90, 0xbd, 0xe5, 0xe3,
0xc0, 0xbe, 0x6d, 0xdb, 0x8b, 0x8c, 0xe4, 0x33, 0xff, 0x0e, 0x02, 0x32, 0xe6, 0x10, 0x48, 0xb9,
0x31, 0x81, 0xed, 0xd1, 0x6b, 0x88, 0x1e, 0xc1, 0xfe, 0x38, 0x44, 0x09, 0x83, 0xd8, 0xc2, 0x57,
0xc6, 0x91, 0xfe, 0x3f, 0xff, 0xad, 0xa6, 0xf1, 0x91, 0xb3, 0x1b, 0x9f, 0xc3, 0x1e, 0xd0, 0x48,
0xf0, 0xa2, 0x59, 0x8f, 0x3e, 0xa3, 0xa9, 0x08, 0x41, 0xd1, 0xff, 0xb1, 0x62, 0xe0, 0x1c, 0xb9,
0xed, 0x0c, 0xc2, 0x13, 0xcf, 0x53, 0x68, 0xe3, 0x1e, 0x76, 0x54, 0x5b, 0x9a, 0x61, 0x62, 0x3d,
0x33, 0x83, 0xba, 0xe4, 0x96, 0x34, 0x44, 0xf3, 0xb7, 0xb1, 0xd6, 0xcd, 0x45, 0x72, 0x53, 0xb4,
0x7a, 0x29, 0x2b, 0xd7, 0x16, 0xa6, 0xae, 0xdd, 0x61, 0x41, 0x0f, 0xd0, 0x67, 0xd3, 0xac, 0xb6,
0x32, 0xf4, 0x99, 0xb9, 0xaa, 0xca, 0xd0, 0x83, 0xd2, 0x57, 0x49, 0xda, 0x73, 0x0a, 0x39, 0xc3,
0x4c, 0xe6, 0x2d, 0x98, 0x02, 0xcd, 0x92, 0x14, 0x68, 0xa6, 0xbe, 0xa0, 0xf4, 0xe0, 0x5a, 0x4d,
0x5e, 0x7b, 0xe8, 0x97, 0x0c, 0x4e, 0xf2, 0xa7, 0x59, 0x92, 0x3f, 0x89, 0x39, 0x14, 0xcf, 0x7c,
0x39, 0xcd, 0xc9, 0xe9, 0x92, 0x2a, 0x92, 0x9c, 0x47, 0xbe, 0x02, 0x9c, 0x10, 0xfc, 0xa4, 0x26,
0xbe, 0xb8, 0x3e, 0xb0, 0x65, 0x95, 0x71, 0xda, 0x0e, 0xbc, 0x20, 0x34, 0xe9, 0x0f, 0xd3, 0xe9,
0x94, 0xf6, 0xd3, 0xac, 0x28, 0x1d, 0xe8, 0xe0, 0xbf, 0x3c, 0xb3, 0xcc, 0xc6, 0x1f, 0x18, 0xb9,
0xc2, 0xc1, 0x2e, 0xda, 0x93, 0xdc, 0x6f, 0x96, 0xe4, 0x7e, 0xb3, 0x24, 0xf7, 0x9b, 0x25, 0xb9,
0xdf, 0x4c, 0x16, 0x0e, 0x56, 0x5b, 0x85, 0x83, 0xd5, 0x46, 0xe1, 0x60, 0xfa, 0x52, 0xe1, 0x60,
0xfa, 0x87, 0x0a, 0x07, 0xd3, 0xad, 0xc2, 0x81, 0xc8, 0x83, 0x75, 0xc8, 0x82, 0x57, 0xf9, 0x2c,
0x18, 0x96, 0xea, 0xee, 0x99, 0xdf, 0x05, 0x11, 0x6b, 0x20, 0xeb, 0xa5, 0x6c, 0x78, 0x9d, 0x70,
0x64, 0x9d, 0x70, 0x64, 0x9d, 0x70, 0x64, 0x9d, 0x70, 0x64, 0x9d, 0x70, 0x64, 0x9d, 0x70, 0x64,
0x9d, 0x70, 0x64, 0x9d, 0xcb, 0x86, 0xd7, 0xa5, 0xd9, 0xf0, 0x79, 0x29, 0x11, 0xaf, 0xcd, 0x86,
0xcf, 0x77, 0x65, 0xc3, 0x62, 0x2b, 0xbe, 0x6f, 0x6d, 0x45, 0xf6, 0x44, 0xf2, 0x2d, 0x9d, 0x27,
0x7b, 0xc7, 0x8b, 0x16, 0xcf, 0xcf, 0x53, 0x51, 0xdb, 0x60, 0xe6, 0x90, 0xe5, 0x6a, 0x1b, 0xab,
0x62, 0x6d, 0xe3, 0x78, 0x5b, 0x02, 0xc1, 0xff, 0xd2, 0xde, 0xd6, 0xe3, 0x8d, 0x8a, 0xc9, 0x0b,
0x58, 0x69, 0x10, 0x5a, 0xfe, 0x0c, 0x8d, 0x05, 0x97, 0xe7, 0x67, 0x51, 0x81, 0x99, 0x25, 0x15,
0x18, 0xfc, 0x00, 0x5c, 0xdf, 0x43, 0xf1, 0x53, 0x5e, 0x10, 0x71, 0x70, 0xfe, 0x5e, 0xc4, 0x38,
0xbf, 0xcf, 0xaa, 0x26, 0xec, 0xe7, 0xcf, 0x0b, 0x20, 0x25, 0xcc, 0x4e, 0x0b, 0x3e, 0x07, 0x5f,
0x60, 0x0a, 0x6e, 0x40, 0xbd, 0x88, 0xdb, 0x4f, 0xe1, 0xe3, 0x16, 0xd2, 0xc7, 0xc9, 0x87, 0x60,
0xe6, 0x30, 0xd1, 0x82, 0xc0, 0x23, 0x8f, 0x49, 0x3b, 0x03, 0x97, 0xa9, 0x58, 0xd9, 0xac, 0x5b,
0x78, 0x54, 0xb5, 0x7e, 0x36, 0x5c, 0x00, 0xd4, 0xc2, 0xb4, 0xea, 0x67, 0xaa, 0x76, 0x36, 0xb4,
0xe1, 0x8b, 0x6d, 0xc2, 0xc7, 0x3f, 0x6e, 0x2a, 0x06, 0xe8, 0xdd, 0x94, 0xbb, 0x3a, 0x8c, 0x86,
0xed, 0x13, 0x73, 0xa1, 0xef, 0xc5, 0xb2, 0xfa, 0xa9, 0x3c, 0xf2, 0x59, 0x48, 0x67, 0xb0, 0xf5,
0xdc, 0x34, 0xef, 0x8e, 0x29, 0xf0, 0x5b, 0xa1, 0xf5, 0xbb, 0x3a, 0x25, 0xcb, 0xf9, 0x3a, 0x72,
0x6d, 0xcb, 0x4b, 0xbc, 0xc7, 0x42, 0x2f, 0xe4, 0x5a, 0xb1, 0x26, 0x4e, 0x5a, 0xe2, 0x26, 0x26,
0x18, 0x7f, 0x36, 0x74, 0x99, 0xaf, 0x3b, 0x13, 0x2b, 0x73, 0xd9, 0x13, 0xcb, 0xbe, 0x9d, 0x85,
0xc1, 0xca, 0x77, 0xcc, 0x6f, 0x68, 0xfa, 0xad, 0xf0, 0x60, 0x16, 0x5a, 0x8e, 0x8b, 0x67, 0x04,
0x6f, 0x75, 0x87, 0xcd, 0x34, 0xf2, 0xe3, 0xa3, 0x28, 0x5c, 0x1c, 0xea, 0xc7, 0xe2, 0xc3, 0x5b,
0x48, 0x0d, 0xb8, 0x00, 0xe5, 0x24, 0xc0, 0xb6, 0x6d, 0xfa, 0x4c, 0xf4, 0x04, 0xf8, 0xf9, 0x4f,
0x1a, 0xf9, 0xa1, 0xd3, 0xe9, 0x64, 0xdf, 0x09, 0xcc, 0xff, 0x27, 0xf5, 0x9b, 0xdc, 0x11, 0xe6,
0x54, 0xe5, 0x21, 0xf6, 0xf0, 0xc2, 0x8a, 0xe7, 0x28, 0x17, 0x0a, 0x37, 0xdc, 0xda, 0x91, 0xae,
0xab, 0x4f, 0x4f, 0x62, 0xe6, 0x23, 0xbd, 0xdc, 0x0f, 0x97, 0xe0, 0x13, 0x12, 0x9d, 0x60, 0xb3,
0x1e, 0x4a, 0xb0, 0x19, 0xfa, 0xe6, 0x42, 0x04, 0xb6, 0x7b, 0x48, 0x75, 0xa3, 0xc0, 0x2f, 0x30,
0x33, 0x9b, 0xff, 0x48, 0xff, 0x13, 0x1e, 0x0a, 0x00, 0xba, 0x06, 0x96, 0x6d, 0xc8, 0x82, 0x2d,
0x82, 0x70, 0x4d, 0xeb, 0x59, 0x79, 0xe7, 0xf8, 0x1b, 0x51, 0x06, 0x93, 0xe1, 0xfb, 0xeb, 0xeb,
0xcb, 0xeb, 0x1e, 0xf9, 0x95, 0x97, 0x69, 0x02, 0xf0, 0xfb, 0xc0, 0x0c, 0xdc, 0x89, 0xe7, 0xd1,
0xde, 0xa0, 0x39, 0x19, 0xaa, 0xdf, 0x20, 0xd8, 0x57, 0x7b, 0x80, 0x4f, 0x17, 0xe5, 0x9f, 0x25,
0x40, 0xc8, 0x40, 0x81, 0x3b, 0xde, 0xb9, 0xc9, 0x69, 0xb7, 0x99, 0xeb, 0x29, 0x0a, 0xa0, 0xad,
0xdf, 0xfd, 0x59, 0xa4, 0x54, 0x6a, 0xb3, 0x0b, 0xab, 0x68, 0xb6, 0xfa, 0x73, 0x73, 0x3e, 0xec,
0x1e, 0x67, 0x50, 0x73, 0xb5, 0x37, 0xef, 0x5b, 0xa6, 0xcc, 0x21, 0x46, 0x3c, 0x6a, 0xdc, 0x4c,
0xe6, 0xb5, 0x89, 0x99, 0xcf, 0xe3, 0xb2, 0x9a, 0xc9, 0x7c, 0x60, 0x34, 0xf4, 0xd6, 0xfe, 0xfe,
0xde, 0x08, 0xfe, 0x9f, 0x1c, 0x03, 0x9a, 0xf7, 0xe3, 0x2b, 0xd2, 0xfd, 0x0d, 0x8b, 0xa0, 0xe4,
0xde, 0x8d, 0xe7, 0xc4, 0x38, 0x21, 0xbf, 0x8e, 0x47, 0x24, 0x5a, 0x2d, 0x97, 0xde, 0x9a, 0xf6,
0x14, 0xab, 0x6e, 0x8e, 0x8e, 0xa9, 0xd1, 0xfa, 0x8d, 0xd0, 0xde, 0xe4, 0x98, 0x7e, 0x1a, 0xb7,
0x8e, 0x8c, 0x2e, 0x11, 0xdf, 0x29, 0x0c, 0xa4, 0x1a, 0x40, 0xcc, 0xf1, 0x1f, 0x7a, 0x22, 0x47,
0x61, 0x15, 0xcf, 0x87, 0x28, 0x05, 0x02, 0x9f, 0x38, 0xe0, 0xcb, 0xa6, 0x22, 0x25, 0x1c, 0x57,
0x2f, 0xd6, 0x10, 0xab, 0xd5, 0x1e, 0x4c, 0xaa, 0xf0, 0x12, 0x59, 0x10, 0xc5, 0x84, 0x4d, 0xa7,
0x80, 0x26, 0xd2, 0xc8, 0x7f, 0xd1, 0xfe, 0x43, 0xdd, 0x1c, 0x9b, 0xe3, 0x02, 0x27, 0xc6, 0x6a,
0x6f, 0xac, 0x3d, 0xf0, 0x89, 0xdd, 0x88, 0x30, 0x3f, 0x58, 0xcd, 0xe6, 0xea, 0x60, 0x12, 0x0e,
0xb3, 0x42, 0x54, 0x61, 0x7b, 0xad, 0x42, 0x7d, 0x2a, 0xb7, 0xed, 0xa8, 0x6f, 0x0f, 0xe2, 0xe5,
0x77, 0x21, 0x13, 0x45, 0x71, 0x3d, 0x92, 0x9c, 0x3c, 0xbb, 0x91, 0x19, 0x31, 0x4d, 0x24, 0x33,
0x77, 0x20, 0x67, 0x45, 0xf1, 0x7b, 0xdf, 0x91, 0x65, 0x45, 0x36, 0x30, 0x92, 0x52, 0xa1, 0xde,
0xbf, 0x7b, 0xc9, 0x7e, 0x8c, 0x41, 0xb0, 0x18, 0x18, 0xc8, 0x9c, 0x0d, 0xa9, 0xbf, 0x5c, 0xdd,
0xd8, 0x1c, 0xd2, 0x17, 0xa5, 0x80, 0x97, 0x6d, 0xd5, 0xd6, 0x40, 0x49, 0xa9, 0xcf, 0x13, 0x2d,
0x5f, 0x24, 0x5a, 0x90, 0xef, 0xab, 0x9a, 0x1b, 0xfd, 0x62, 0xfd, 0xa2, 0xdc, 0xa9, 0xc7, 0x7a,
0xef, 0x2e, 0x5b, 0x2a, 0xa4, 0xc7, 0xb8, 0xa9, 0xe9, 0xe1, 0xa3, 0x38, 0x52, 0xd9, 0x98, 0xee,
0x34, 0x39, 0x62, 0x82, 0x10, 0x72, 0x7c, 0x03, 0x01, 0xa4, 0x6b, 0xc6, 0x69, 0xb0, 0x38, 0x55,
0xf6, 0x14, 0xc8, 0x72, 0xc0, 0xf9, 0xb9, 0x43, 0x0c, 0xdd, 0x46, 0x75, 0x3c, 0x49, 0x7a, 0x7a,
0x3a, 0x10, 0x0f, 0x41, 0xa2, 0x5d, 0x35, 0x39, 0xdc, 0x10, 0x56, 0x0f, 0x16, 0xcc, 0xbd, 0x31,
0x02, 0x24, 0xe9, 0xff, 0xb7, 0x81, 0xe3, 0xde, 0x11, 0x7e, 0x96, 0x65, 0xf2, 0x49, 0x86, 0xbf,
0xfb, 0x83, 0x79, 0x98, 0x3c, 0x89, 0x16, 0x1e, 0x3e, 0xf9, 0xf1, 0xd1, 0xad, 0x1b, 0xcf, 0x3d,
0x78, 0x25, 0xea, 0x0e, 0x44, 0x9c, 0x92, 0x9f, 0xdf, 0xc0, 0x8b, 0x67, 0x4a, 0x20, 0x37, 0x9c,
0xa3, 0x59, 0x30, 0xe9, 0xaf, 0x67, 0x4a, 0x1c, 0x02, 0x3b, 0xe8, 0x10, 0xde, 0x08, 0xb2, 0x70,
0xa3, 0xdf, 0x0c, 0x82, 0x25, 0x5f, 0xb6, 0xcc, 0x62, 0x5b, 0x2d, 0x4a, 0x04, 0x26, 0xe6, 0x0c,
0xb9, 0x3a, 0x3c, 0x0c, 0x9a, 0x02, 0x64, 0xb8, 0x01, 0xda, 0xd6, 0xe9, 0x70, 0xfc, 0xd7, 0xc3,
0x23, 0xa3, 0x45, 0xae, 0x3f, 0x8e, 0x3e, 0x55, 0x82, 0x19, 0x74, 0x78, 0x73, 0x61, 0x1c, 0x19,
0x9d, 0x2a, 0x88, 0x56, 0x87, 0x42, 0x5a, 0xaa, 0xdf, 0xfe, 0xfc, 0x9f, 0x95, 0x10, 0x5d, 0x81,
0xa3, 0xf5, 0xb6, 0x0a, 0xa2, 0x0b, 0xc4, 0x20, 0xb9, 0xba, 0x51, 0x09, 0x01, 0x74, 0x9c, 0x5c,
0x9d, 0x18, 0x7a, 0xab, 0x12, 0xa2, 0x45, 0x87, 0xe7, 0x57, 0xef, 0x8e, 0x8e, 0xf4, 0xc3, 0x4a,
0x90, 0x0e, 0x07, 0x39, 0x3c, 0xd2, 0xdb, 0x95, 0x20, 0x6d, 0x3a, 0xbc, 0x7a, 0x7b, 0x64, 0x54,
0x02, 0x74, 0x80, 0xd4, 0x4b, 0xbf, 0x79, 0x39, 0x9d, 0x56, 0x42, 0x00, 0xa9, 0x57, 0x9f, 0x2e,
0xc8, 0xa7, 0xb9, 0x1b, 0xb3, 0x4a, 0xa0, 0x96, 0x00, 0x3a, 0x3d, 0xbd, 0xa9, 0x04, 0x69, 0x0b,
0x10, 0xd8, 0x9e, 0x4a, 0x90, 0x4e, 0x0a, 0x52, 0xb9, 0x83, 0x9d, 0x6e, 0x0a, 0x53, 0xcf, 0xcf,
0xf6, 0xfb, 0x43, 0xdb, 0xde, 0x3b, 0x38, 0xd8, 0x00, 0x3e, 0xcc, 0x80, 0xdf, 0xe5, 0xa0, 0x0f,
0x0e, 0x00, 0x9c, 0xbd, 0x79, 0x06, 0x49, 0x2d, 0x0e, 0x38, 0x02, 0x76, 0xbc, 0x7b, 0x77, 0x85,
0x03, 0x88, 0xe2, 0xb3, 0xf8, 0x3e, 0x08, 0x6f, 0xd5, 0x6c, 0x0e, 0xbf, 0x74, 0x96, 0x23, 0xe0,
0xd0, 0x7b, 0xa3, 0xd1, 0x36, 0xca, 0x87, 0x89, 0xc9, 0xaa, 0xc6, 0x02, 0xe3, 0x4e, 0xc2, 0xf8,
0x17, 0x16, 0xef, 0x1e, 0xbc, 0x49, 0xe7, 0x51, 0x4a, 0xe7, 0xa7, 0x52, 0x42, 0x07, 0x4d, 0xa1,
0x38, 0x43, 0x34, 0xd2, 0xf0, 0x15, 0xd5, 0xd7, 0x75, 0x4c, 0x6a, 0x07, 0x42, 0x17, 0xb9, 0xd5,
0x35, 0xa9, 0x34, 0xbb, 0x3d, 0x19, 0x04, 0x0c, 0x4f, 0xd1, 0xcb, 0x93, 0xcb, 0xd0, 0x61, 0xe1,
0x96, 0x1a, 0x9f, 0x5e, 0xf2, 0xa1, 0xc3, 0x2d, 0x62, 0x80, 0x67, 0x1f, 0xaf, 0x47, 0xf9, 0xc9,
0x8b, 0xef, 0x81, 0x3d, 0xf9, 0x4d, 0xdf, 0x7a, 0x0f, 0x2c, 0x18, 0x5d, 0x7f, 0xac, 0x7e, 0x0f,
0x82, 0x73, 0x3d, 0xda, 0xf1, 0x1e, 0xa4, 0x66, 0xf4, 0xf1, 0xba, 0xfa, 0x3d, 0x48, 0xcc, 0xc7,
0xd1, 0x75, 0x29, 0x73, 0x9a, 0xc0, 0x97, 0x3c, 0x7b, 0x1c, 0x77, 0x86, 0x8b, 0xbc, 0xdf, 0x62,
0x10, 0x77, 0x41, 0xc3, 0xf1, 0xbd, 0xb5, 0xec, 0x91, 0x22, 0x5b, 0x3e, 0x49, 0xb6, 0x6c, 0x33,
0xe5, 0x17, 0x18, 0x53, 0x25, 0xc6, 0xc0, 0x93, 0x4f, 0x64, 0x9f, 0x54, 0xaa, 0x42, 0x4b, 0xbc,
0xff, 0x58, 0x69, 0xc8, 0xc4, 0xfb, 0x6c, 0x55, 0xa5, 0x6b, 0xc2, 0x3f, 0xd1, 0xd2, 0xf2, 0xf9,
0xda, 0x96, 0x91, 0x23, 0x28, 0x15, 0xd5, 0x0e, 0x18, 0x00, 0x6f, 0x86, 0x64, 0x20, 0x8e, 0x5b,
0xb1, 0x1d, 0xc5, 0xa4, 0xfe, 0x6a, 0x31, 0x61, 0x21, 0x4d, 0x0c, 0xf7, 0x58, 0x08, 0x0b, 0x8e,
0xf6, 0x22, 0xf1, 0x59, 0x5a, 0x7c, 0x8f, 0x88, 0x84, 0x81, 0x12, 0xcc, 0x38, 0x60, 0xb5, 0x18,
0xc0, 0xa1, 0x2a, 0xbc, 0x35, 0x68, 0x42, 0xe3, 0x8f, 0x8f, 0x89, 0xa7, 0x76, 0x55, 0x6e, 0xfe,
0xf9, 0x4c, 0xe0, 0x2d, 0x72, 0xa9, 0x06, 0x22, 0xfd, 0x62, 0xa2, 0x33, 0xe8, 0xe3, 0x21, 0x44,
0x9f, 0x92, 0xa4, 0x9e, 0x49, 0x9a, 0xc3, 0x7d, 0x7f, 0x12, 0x2d, 0xfb, 0xdb, 0xdb, 0x63, 0x57,
0xca, 0xef, 0x39, 0xf7, 0x7a, 0xbd, 0x9d, 0x8b, 0x3a, 0x2d, 0x2e, 0x44, 0xae, 0xc0, 0x90, 0x2b,
0xe0, 0x31, 0xe5, 0xd5, 0xe8, 0x99, 0x66, 0x3b, 0x95, 0x91, 0x94, 0x2e, 0x01, 0x69, 0xa5, 0x40,
0xa1, 0x60, 0xb6, 0xd4, 0xb1, 0xe6, 0x16, 0xc7, 0x75, 0xc9, 0x71, 0x5e, 0x8c, 0x7e, 0x0d, 0xc3,
0x75, 0x41, 0x5b, 0x81, 0xa7, 0x9d, 0xa3, 0x1c, 0x05, 0x89, 0xc3, 0xdd, 0xf0, 0xa6, 0x2a, 0x6d,
0x16, 0x67, 0x36, 0xe4, 0xcc, 0x72, 0xd2, 0x5d, 0x73, 0x1a, 0x15, 0x73, 0xbe, 0x76, 0xaa, 0xd6,
0xeb, 0xa7, 0x6a, 0xfd, 0x8b, 0x53, 0xb5, 0x5f, 0x3f, 0x55, 0xfb, 0x5f, 0x9c, 0xaa, 0xf3, 0xfa,
0xa9, 0x3a, 0xff, 0xd4, 0x54, 0x1b, 0x32, 0x1d, 0x56, 0xca, 0x34, 0x4a, 0x57, 0x46, 0x18, 0x84,
0xf0, 0x82, 0xb0, 0xa4, 0xf4, 0x29, 0x09, 0xdc, 0x90, 0x79, 0x5e, 0xd8, 0x9f, 0x04, 0x0f, 0x09,
0x91, 0xa7, 0xbf, 0x25, 0xcb, 0x29, 0xb7, 0x78, 0xd1, 0xce, 0xe9, 0xc7, 0xb7, 0xee, 0x92, 0x4c,
0xdd, 0x10, 0x12, 0x05, 0x0c, 0x47, 0x77, 0xea, 0xd7, 0xf8, 0xbc, 0x84, 0x1d, 0x90, 0x22, 0xd1,
0xcc, 0x32, 0x6e, 0xe8, 0x51, 0x25, 0x51, 0xd3, 0x9d, 0x44, 0x41, 0xcc, 0x42, 0xae, 0xd9, 0x34,
0x64, 0x51, 0xa6, 0xf0, 0x9c, 0x43, 0x53, 0x41, 0x40, 0x39, 0x23, 0xae, 0x3f, 0xec, 0x66, 0x84,
0xb5, 0x73, 0xce, 0x93, 0x55, 0x1c, 0x1c, 0xd8, 0x96, 0x67, 0xaf, 0x3c, 0x2b, 0x66, 0xe4, 0x1e,
0x63, 0x22, 0x6c, 0x4e, 0x85, 0x04, 0xc7, 0x23, 0xd3, 0x30, 0x58, 0xa0, 0x47, 0xee, 0x89, 0x1d,
0xcb, 0x3b, 0x89, 0x93, 0x4f, 0x65, 0x4e, 0x42, 0xdf, 0xe5, 0x22, 0x8c, 0xe1, 0x28, 0x74, 0x67,
0xf3, 0x98, 0x85, 0x15, 0x00, 0xad, 0xe1, 0x89, 0x6d, 0x63, 0x17, 0x5d, 0x15, 0x86, 0xf6, 0xf0,
0xdd, 0xca, 0xf2, 0xb6, 0x3d, 0x84, 0x30, 0xab, 0x29, 0x03, 0xf8, 0xdf, 0x6f, 0x7d, 0x0b, 0xd2,
0xb4, 0x88, 0x85, 0xf1, 0x89, 0xf3, 0xdd, 0xb2, 0x21, 0xb1, 0xc0, 0x7c, 0x4d, 0xa1, 0x13, 0x06,
0x29, 0x22, 0x63, 0xbe, 0x43, 0xb5, 0x40, 0x7d, 0x96, 0x49, 0x83, 0x12, 0x7f, 0x3e, 0x38, 0x70,
0xbf, 0x34, 0x42, 0x48, 0xd5, 0xef, 0x18, 0x76, 0x12, 0x1e, 0xb8, 0xb2, 0x36, 0x54, 0xdf, 0xca,
0xe8, 0xdc, 0x41, 0x9a, 0x75, 0x1c, 0x18, 0xe5, 0xe5, 0x86, 0x83, 0xed, 0x41, 0xc3, 0xed, 0xca,
0x84, 0xff, 0xf4, 0xc4, 0xcf, 0xa9, 0x0b, 0xd9, 0xd1, 0xe9, 0xe5, 0x85, 0x02, 0x8c, 0x84, 0xf4,
0x88, 0x1f, 0xcb, 0x8a, 0x7c, 0xc5, 0xdd, 0x91, 0x21, 0xd9, 0xc1, 0xe2, 0x2b, 0x3c, 0x0c, 0xd7,
0x30, 0x67, 0x3e, 0x47, 0x82, 0x34, 0x04, 0xab, 0x70, 0x32, 0x13, 0x2a, 0xe4, 0x3b, 0xd9, 0x90,
0x5d, 0x59, 0x0f, 0x11, 0x6e, 0x75, 0x97, 0x6a, 0xfc, 0x2d, 0xe7, 0x4f, 0x1f, 0x5e, 0xe5, 0x4f,
0x0f, 0xbb, 0xdd, 0x76, 0x37, 0xe7, 0x50, 0xd9, 0xf3, 0x86, 0xf2, 0xe4, 0x1c, 0xa6, 0x49, 0x69,
0xea, 0x31, 0x5f, 0xe1, 0x07, 0xff, 0x76, 0x9a, 0x23, 0xc6, 0xde, 0xe9, 0x13, 0x37, 0xa9, 0xf0,
0x9f, 0x0b, 0xb3, 0x6e, 0xaa, 0xb3, 0x54, 0xaa, 0x3f, 0x14, 0x62, 0x72, 0x2a, 0x64, 0x6c, 0x2a,
0xe9, 0xfb, 0xff, 0x17, 0x6e, 0x26, 0xca, 0xc6, 0xed, 0x83, 0x54, 0x3b, 0x79, 0xd6, 0x29, 0x24,
0xcc, 0x65, 0x11, 0x2f, 0x97, 0xec, 0xd4, 0x43, 0x4b, 0xaa, 0xda, 0x43, 0x40, 0xeb, 0x6e, 0x52,
0x9b, 0x8d, 0xb5, 0x49, 0xec, 0xa3, 0x32, 0x80, 0x2c, 0xca, 0x7e, 0x8e, 0x4c, 0x4f, 0x40, 0x4f,
0xf1, 0x55, 0x45, 0x57, 0x68, 0xb9, 0x72, 0x80, 0x46, 0xa5, 0xfd, 0x74, 0xfa, 0x9e, 0x89, 0x07,
0x77, 0x0a, 0xfb, 0xec, 0x1f, 0x18, 0x39, 0xb5, 0x97, 0x53, 0xc2, 0x43, 0x31, 0xa5, 0x9a, 0x9f,
0x32, 0x62, 0x31, 0x57, 0x4e, 0xf5, 0x11, 0x2d, 0xc6, 0x46, 0xf7, 0x39, 0x13, 0x27, 0x16, 0xd8,
0x5d, 0xc2, 0xb0, 0xfa, 0xf7, 0x2a, 0x92, 0x54, 0x96, 0x4e, 0xdd, 0x97, 0x53, 0x17, 0x7a, 0x67,
0xc5, 0x23, 0x26, 0x5b, 0xc2, 0x71, 0x20, 0x18, 0x88, 0xed, 0xf6, 0xa8, 0x41, 0x91, 0x96, 0x72,
0x93, 0x84, 0xa3, 0x61, 0xb2, 0xed, 0xd1, 0xdb, 0x86, 0xa9, 0x60, 0x8f, 0x46, 0xb1, 0x2f, 0x9a,
0x77, 0x13, 0x4b, 0xc4, 0xb1, 0x01, 0x69, 0x51, 0xbe, 0x0e, 0xa6, 0x59, 0x26, 0x16, 0xf5, 0xeb,
0x63, 0x7e, 0xfa, 0xd1, 0x40, 0xc7, 0x71, 0x3a, 0xb7, 0xc2, 0xd3, 0xc0, 0x61, 0x0a, 0x16, 0xb4,
0xf4, 0xe3, 0xce, 0x51, 0xaf, 0xdb, 0x55, 0xeb, 0xc0, 0x27, 0xb7, 0x6e, 0x7e, 0x1b, 0xad, 0xe2,
0x38, 0xe0, 0x1d, 0x7a, 0xcf, 0xa2, 0xb1, 0xa1, 0x5c, 0xb1, 0xb9, 0xd2, 0x1e, 0x18, 0xb9, 0x10,
0x44, 0xa8, 0xd2, 0x8f, 0x8f, 0xd6, 0xf3, 0x56, 0x10, 0x92, 0x28, 0xfb, 0x43, 0x54, 0xd4, 0xec,
0xe1, 0x37, 0x0d, 0xa7, 0x94, 0x4e, 0xa2, 0xe0, 0xc5, 0x7e, 0x7c, 0xa4, 0xa3, 0xf7, 0xaf, 0xa2,
0x3a, 0x45, 0xb3, 0xa5, 0xbb, 0xb0, 0x08, 0xdd, 0x34, 0xe3, 0x63, 0x9a, 0x14, 0x76, 0xb0, 0x47,
0xe3, 0x79, 0xf8, 0x4e, 0x1e, 0x26, 0xa4, 0x6a, 0x53, 0x3a, 0xbc, 0x85, 0xc3, 0x5b, 0x25, 0xc3,
0xaf, 0x56, 0xd1, 0x7c, 0xc2, 0x99, 0xb4, 0x1b, 0x41, 0x1b, 0x11, 0xb4, 0x2b, 0x10, 0x10, 0x57,
0x9e, 0x2f, 0xef, 0xc6, 0xd1, 0x41, 0x1c, 0x9d, 0x12, 0x1c, 0x63, 0xde, 0xcd, 0xb6, 0x7b, 0x70,
0x17, 0x07, 0x77, 0xcb, 0x08, 0x38, 0xbb, 0x26, 0x11, 0xf3, 0xa3, 0x20, 0xdc, 0x8d, 0xe0, 0x10,
0x11, 0x1c, 0x96, 0x20, 0xb8, 0x09, 0x56, 0x2f, 0x4d, 0xfe, 0x13, 0x8e, 0xfd, 0xa9, 0x64, 0xec,
0x89, 0x6f, 0x79, 0xc1, 0x6c, 0xf7, 0xe0, 0x23, 0x1c, 0x7c, 0x54, 0x39, 0xb8, 0x82, 0x79, 0x34,
0x35, 0x7e, 0x54, 0x20, 0xe5, 0x81, 0xac, 0x74, 0x0d, 0x10, 0xbd, 0xc0, 0x7a, 0x7b, 0x64, 0x19,
0xb8, 0x3e, 0xc4, 0x39, 0x7d, 0x2e, 0xa3, 0xbc, 0x7d, 0x84, 0xe2, 0x3d, 0x8d, 0x37, 0x28, 0xb7,
0x6f, 0xd4, 0xc4, 0xab, 0xed, 0xff, 0xf0, 0xd0, 0xfa, 0xc9, 0xe8, 0xf6, 0x93, 0x88, 0x1c, 0x8c,
0xa8, 0x3c, 0xfe, 0xd8, 0x54, 0x2f, 0xd3, 0xcd, 0x75, 0xa1, 0xce, 0xbc, 0xb1, 0x8b, 0x46, 0x41,
0x29, 0xdc, 0x8f, 0x61, 0xea, 0xd3, 0x93, 0x52, 0xbc, 0x21, 0xb3, 0xd9, 0x06, 0x97, 0xde, 0x98,
0x78, 0x44, 0x53, 0x25, 0x4c, 0xe7, 0x9e, 0x81, 0x91, 0x46, 0x1f, 0x1c, 0xdc, 0xee, 0x12, 0x6c,
0x62, 0x39, 0x7d, 0x3c, 0xab, 0xdf, 0x3e, 0x0a, 0xe3, 0x26, 0x53, 0xfd, 0x03, 0xf5, 0x67, 0xbf,
0x58, 0x46, 0xde, 0x2b, 0x39, 0x5e, 0xf3, 0x13, 0x7c, 0x68, 0xa8, 0xb1, 0x7d, 0x32, 0x9f, 0x66,
0xfb, 0x5f, 0xb0, 0x7c, 0x2c, 0xcf, 0xc7, 0x22, 0x9d, 0x02, 0x90, 0xbe, 0x8d, 0x04, 0xcf, 0xbb,
0xaa, 0x71, 0xe8, 0x1c, 0x87, 0xe0, 0x78, 0xe4, 0xe6, 0xfa, 0x2b, 0x99, 0x96, 0x30, 0x39, 0x63,
0xde, 0x6a, 0x89, 0x17, 0x41, 0x3e, 0xb8, 0x1e, 0xde, 0xab, 0x91, 0x9d, 0x73, 0x3e, 0xbb, 0x27,
0x7f, 0xbb, 0x38, 0xff, 0x39, 0x8e, 0x97, 0xd7, 0x10, 0x3d, 0xb0, 0x28, 0xee, 0xfb, 0xd5, 0x77,
0x57, 0x72, 0x37, 0x2a, 0xb2, 0xfb, 0x1e, 0xf1, 0xdc, 0xc5, 0x8e, 0xa7, 0x68, 0x19, 0x80, 0x8f,
0xbc, 0x61, 0x0f, 0xb1, 0xc6, 0x9f, 0x00, 0x99, 0xf1, 0x2a, 0xc2, 0xd6, 0x0e, 0x58, 0xa4, 0x0a,
0xbe, 0xab, 0xfa, 0xe6, 0x4a, 0x86, 0x97, 0xe5, 0x11, 0x63, 0x97, 0xb1, 0x65, 0xdf, 0x6a, 0x7b,
0x09, 0x02, 0x71, 0x5f, 0xe9, 0xea, 0x12, 0x76, 0x53, 0xa3, 0x4d, 0xb1, 0x1c, 0x79, 0xb6, 0x12,
0xf3, 0x95, 0x7c, 0x08, 0xc2, 0x05, 0x76, 0xab, 0xa5, 0xdd, 0x8e, 0xf2, 0x5e, 0x8e, 0x42, 0xb1,
0xc7, 0x59, 0x36, 0xdd, 0xf2, 0x76, 0x67, 0xbc, 0x0a, 0x13, 0x01, 0xfb, 0xf0, 0x36, 0x8c, 0xdf,
0x88, 0x10, 0x26, 0x56, 0xb5, 0x92, 0x76, 0xe8, 0xbd, 0x8d, 0x5b, 0x47, 0xa7, 0xd3, 0x59, 0xca,
0x3d, 0x2d, 0xee, 0xd3, 0xe4, 0x25, 0x05, 0x2d, 0x04, 0xc3, 0x0f, 0x7e, 0x53, 0x5e, 0xae, 0x42,
0x3e, 0x5f, 0x33, 0x0b, 0x42, 0xaa, 0x63, 0x58, 0x09, 0x9f, 0xef, 0x98, 0xa5, 0xf3, 0x1e, 0x2b,
0xe8, 0xcb, 0x53, 0x2a, 0x14, 0x49, 0x7f, 0x3a, 0x06, 0xbb, 0xb6, 0x70, 0x3a, 0x33, 0xcf, 0x1a,
0x74, 0xcd, 0x38, 0x0c, 0x04, 0x00, 0x84, 0x12, 0x79, 0xbe, 0xf2, 0x62, 0xb9, 0x7c, 0xde, 0xbf,
0xcf, 0x85, 0x47, 0xf1, 0xf9, 0x51, 0x41, 0xdc, 0x98, 0xdf, 0xf3, 0xc3, 0x18, 0xfc, 0x00, 0xb2,
0xef, 0x64, 0x3a, 0x23, 0x9a, 0x57, 0x0c, 0x9d, 0xb7, 0xad, 0x24, 0xc7, 0x19, 0x20, 0xcd, 0xfd,
0x04, 0x14, 0xc3, 0x9d, 0x06, 0x40, 0xbf, 0xb7, 0xec, 0xb9, 0x22, 0x7d, 0xa7, 0x39, 0x7c, 0x4c,
0x40, 0x0d, 0x11, 0x29, 0x64, 0xa8, 0x58, 0x63, 0xe9, 0xfa, 0xf9, 0x5e, 0x98, 0x32, 0xad, 0xf9,
0xc6, 0x93, 0x50, 0xf4, 0x67, 0xdf, 0x72, 0x4d, 0x5a, 0x7c, 0xe8, 0x67, 0xf7, 0x4b, 0xbf, 0xf2,
0xbc, 0xc6, 0x2f, 0x40, 0x23, 0x93, 0xb5, 0xca, 0x73, 0xa4, 0x22, 0x2c, 0xd7, 0x14, 0xed, 0x35,
0xfd, 0xb1, 0x22, 0xae, 0x2a, 0x07, 0x3d, 0xbd, 0xdc, 0x04, 0x0d, 0x30, 0x50, 0xd6, 0x5e, 0xd3,
0x3e, 0x8b, 0x44, 0x40, 0x9e, 0x5e, 0x0e, 0x7b, 0xfd, 0x21, 0x81, 0x4d, 0xb5, 0x16, 0xf6, 0x74,
0x5a, 0x41, 0xc5, 0x6f, 0x65, 0xc0, 0x77, 0xcf, 0xea, 0x73, 0xb2, 0xc5, 0x10, 0x1e, 0x81, 0x89,
0x48, 0x83, 0x3c, 0xbc, 0x2c, 0x25, 0x9e, 0xa6, 0x3b, 0xc9, 0xc4, 0x1e, 0xf2, 0x88, 0x4c, 0x32,
0x47, 0xac, 0x5b, 0x2e, 0x89, 0xab, 0x19, 0x1f, 0x05, 0xd6, 0x3b, 0x49, 0xbb, 0x92, 0xef, 0xfd,
0x93, 0x30, 0xb4, 0xd6, 0x0d, 0x37, 0xe2, 0x7f, 0x15, 0x9e, 0x9a, 0xaa, 0x49, 0x3b, 0xe3, 0x96,
0xb5, 0xa7, 0xd8, 0xaa, 0x5f, 0x2d, 0x46, 0x18, 0x92, 0xe1, 0xb4, 0xb8, 0xf7, 0xa8, 0x84, 0x7c,
0x5b, 0xf1, 0xee, 0x55, 0xe9, 0xda, 0x6f, 0x6e, 0x68, 0x8e, 0xa5, 0x56, 0x23, 0x8e, 0x9f, 0x39,
0x55, 0x6e, 0x58, 0xd5, 0x0a, 0x78, 0x76, 0x9d, 0x1f, 0x21, 0x81, 0x71, 0xb6, 0xf2, 0x09, 0xce,
0x6e, 0xca, 0xc0, 0x39, 0x4d, 0x82, 0x1f, 0x21, 0x83, 0x40, 0xb3, 0x6a, 0xb2, 0xeb, 0xf3, 0xad,
0xd1, 0x1c, 0xbe, 0x7a, 0xbe, 0xeb, 0x0b, 0x5a, 0xd8, 0xca, 0xdc, 0x18, 0x70, 0xd9, 0x49, 0xae,
0xa0, 0xa1, 0x8a, 0x5b, 0xce, 0x49, 0x84, 0x46, 0x15, 0xb4, 0x5a, 0xed, 0xc9, 0x7b, 0x7b, 0x57,
0x1e, 0xc3, 0x3e, 0x76, 0x19, 0x07, 0x5a, 0x04, 0x75, 0x9f, 0x5f, 0xee, 0x13, 0xf5, 0xa0, 0x3d,
0x9a, 0x42, 0xde, 0x80, 0x25, 0x26, 0x93, 0x30, 0xb8, 0x87, 0xec, 0x85, 0x38, 0x01, 0x8b, 0xf0,
0xca, 0x11, 0x1e, 0x53, 0x07, 0x21, 0x04, 0xaa, 0x73, 0x46, 0xbe, 0x71, 0x13, 0xf4, 0x8d, 0x2c,
0x43, 0x30, 0xae, 0xe0, 0x51, 0x30, 0xf0, 0xe7, 0x98, 0x78, 0x2c, 0x1b, 0xe1, 0x8d, 0x0b, 0x96,
0x35, 0xb0, 0x66, 0x68, 0x99, 0x80, 0x3a, 0xb9, 0x3a, 0x23, 0x6e, 0x1e, 0x29, 0x2f, 0xc8, 0x92,
0x38, 0x3f, 0xed, 0x1a, 0x4c, 0x55, 0xfe, 0x4a, 0xe9, 0x18, 0xbc, 0x07, 0xc5, 0xd1, 0x3d, 0xb0,
0x99, 0xd2, 0x58, 0x7a, 0x81, 0xcd, 0xef, 0x91, 0x34, 0x80, 0x8e, 0x38, 0xb0, 0x03, 0xec, 0xf1,
0xe4, 0x77, 0x61, 0x75, 0x4d, 0xe1, 0xd7, 0x73, 0x4d, 0x84, 0xf0, 0xc6, 0x71, 0x10, 0x5a, 0x33,
0x86, 0x2c, 0x3d, 0x8b, 0xd9, 0x02, 0xfd, 0x92, 0x7d, 0xb6, 0x84, 0x2c, 0x04, 0x02, 0x07, 0x01,
0x06, 0xe3, 0x17, 0x4b, 0xa0, 0x10, 0x2d, 0x29, 0xb9, 0x80, 0x28, 0xb8, 0x41, 0x24, 0xb7, 0x18,
0x86, 0x33, 0xe4, 0x13, 0xb6, 0x33, 0x9c, 0x5d, 0x01, 0x8b, 0xb4, 0x02, 0xc6, 0xa8, 0x88, 0x51,
0xe3, 0xd8, 0x54, 0x15, 0xa1, 0xf8, 0x4d, 0x53, 0x44, 0x7f, 0xcc, 0x6f, 0xdf, 0xf6, 0x9a, 0x4d,
0x5a, 0xe7, 0xaf, 0xb1, 0xb7, 0xa1, 0x9e, 0x5d, 0x9f, 0x6d, 0x46, 0x8d, 0xef, 0xd1, 0xf1, 0xd2,
0x6c, 0xa1, 0xd3, 0xc0, 0xfb, 0x29, 0xd8, 0x08, 0x86, 0xb7, 0x7c, 0x45, 0x03, 0x99, 0xfc, 0x24,
0x9a, 0x8f, 0xc4, 0x97, 0xa4, 0x4d, 0xc8, 0x6c, 0xbf, 0xad, 0x41, 0x04, 0x25, 0xae, 0x24, 0x0f,
0x78, 0x20, 0x36, 0xfc, 0x0f, 0x77, 0xc1, 0x37, 0x69, 0x15, 0x7a, 0xe0, 0xda, 0x45, 0xbb, 0x47,
0x84, 0x9d, 0x04, 0x00, 0xc8, 0x01, 0x06, 0x4d, 0x71, 0x17, 0x1b, 0xaf, 0x9f, 0x12, 0xe9, 0x2c,
0xe8, 0x98, 0x97, 0xee, 0x40, 0xe5, 0x16, 0x35, 0x9e, 0xbe, 0xe3, 0xa7, 0xaf, 0x51, 0x5a, 0x06,
0x9c, 0x42, 0x1a, 0xc2, 0xe2, 0x79, 0x80, 0xc5, 0xd4, 0x20, 0xc2, 0x2b, 0xd2, 0xb9, 0x92, 0x4a,
0x1c, 0x00, 0xf3, 0xee, 0x8b, 0xcf, 0xe6, 0xcc, 0x5b, 0x8e, 0xe8, 0xb0, 0x36, 0x10, 0x81, 0xbc,
0xcc, 0x6d, 0xc4, 0x97, 0x5c, 0x64, 0xf8, 0x33, 0x4e, 0x7b, 0x3c, 0x68, 0x8a, 0x17, 0x69, 0x05,
0xbe, 0x6c, 0x4c, 0x2d, 0x1d, 0x34, 0xc2, 0x41, 0x23, 0x70, 0xf0, 0xd9, 0xb8, 0xc2, 0x08, 0x79,
0x27, 0x62, 0x38, 0xb6, 0xee, 0x58, 0x06, 0x32, 0x4f, 0xd2, 0xf4, 0xc1, 0xbc, 0x35, 0xac, 0xe1,
0x6e, 0xee, 0x5b, 0x8b, 0x65, 0x9f, 0xfc, 0x6c, 0x85, 0xd8, 0x1f, 0x83, 0x5a, 0x11, 0xaf, 0x96,
0xc0, 0x9c, 0x16, 0x44, 0xdf, 0xb1, 0xe5, 0x25, 0xc5, 0xd1, 0xb4, 0x58, 0xeb, 0xd9, 0x9c, 0x54,
0x59, 0xf7, 0xcf, 0x8a, 0xcb, 0x36, 0x2e, 0x33, 0x0b, 0x63, 0x07, 0xee, 0xf0, 0x9a, 0x81, 0xf1,
0x04, 0xbd, 0x75, 0x40, 0xa8, 0x97, 0xc1, 0x3d, 0x48, 0x8f, 0x6c, 0xf0, 0xc0, 0x0e, 0x8d, 0x89,
0x28, 0x04, 0x46, 0xb1, 0x28, 0x38, 0xf6, 0x06, 0x4d, 0x57, 0x8c, 0x9b, 0xc8, 0xc2, 0x70, 0x4d,
0x9c, 0xef, 0xac, 0xb2, 0xd9, 0xb0, 0x23, 0xa6, 0x58, 0x38, 0xe6, 0xbd, 0x18, 0xb2, 0xf4, 0x90,
0xce, 0x5c, 0x7b, 0xef, 0x63, 0xda, 0x45, 0xac, 0x15, 0x84, 0xc6, 0xa0, 0x15, 0xb6, 0x9c, 0xcb,
0x67, 0x51, 0x44, 0x3c, 0xbc, 0x8b, 0xca, 0xc2, 0x17, 0x2a, 0xcb, 0x27, 0x23, 0x26, 0x59, 0x2d,
0xb3, 0x4b, 0x79, 0xd7, 0x46, 0x54, 0x96, 0xf8, 0x55, 0x1c, 0x31, 0x6b, 0x52, 0x68, 0xc5, 0xfb,
0x4d, 0xc3, 0x0b, 0x71, 0xc5, 0x9e, 0x9c, 0xae, 0xc2, 0x10, 0xb4, 0x25, 0x9d, 0x43, 0x5e, 0xac,
0xbf, 0x38, 0xa1, 0x1b, 0xb9, 0xed, 0x46, 0x69, 0xaa, 0xd5, 0xcd, 0x4a, 0x64, 0xba, 0xbe, 0x55,
0x52, 0x4e, 0xcb, 0x53, 0xc3, 0x1a, 0x59, 0x9c, 0x14, 0xa7, 0xcf, 0xee, 0x6c, 0xa4, 0x79, 0x08,
0x96, 0xa4, 0x7a, 0xa2, 0x67, 0xa9, 0x5f, 0x3c, 0xf1, 0xab, 0xed, 0xff, 0xf0, 0xf6, 0xe8, 0xe8,
0xa8, 0x4f, 0xfe, 0x1e, 0xac, 0xc2, 0xe2, 0xce, 0x80, 0x04, 0xdf, 0x61, 0x01, 0x81, 0xcc, 0x81,
0x63, 0xc4, 0x16, 0x0b, 0x69, 0x70, 0xae, 0xde, 0x04, 0x04, 0x54, 0x0a, 0xde, 0x33, 0x6e, 0xf8,
0x22, 0x6b, 0xca, 0x84, 0xb9, 0x5b, 0x23, 0x16, 0x2e, 0x35, 0x1a, 0x02, 0x2e, 0x85, 0xb9, 0x58,
0x45, 0x08, 0x07, 0x82, 0x4a, 0x6c, 0xe4, 0x57, 0xc4, 0xdf, 0xd5, 0x16, 0x10, 0x70, 0xb9, 0x00,
0x21, 0x67, 0x75, 0xfd, 0xef, 0x4c, 0x5e, 0xf2, 0xc5, 0x74, 0x29, 0x22, 0x96, 0xef, 0x80, 0x3d,
0x9e, 0xc2, 0xe0, 0xbd, 0xac, 0xa0, 0x04, 0xa2, 0x54, 0x3b, 0x49, 0x36, 0xd3, 0xf2, 0x80, 0x4c,
0xbe, 0x8b, 0x51, 0x7e, 0x5f, 0xe3, 0x00, 0x8b, 0x8d, 0x6b, 0x60, 0x69, 0x10, 0xf1, 0xeb, 0x71,
0x48, 0x23, 0x07, 0x13, 0xd4, 0xff, 0x95, 0xb1, 0x25, 0xb1, 0x62, 0xb2, 0x0f, 0x01, 0x9f, 0x71,
0x42, 0xdc, 0xa9, 0xa0, 0x00, 0xdb, 0xae, 0x78, 0x63, 0x95, 0x03, 0x8c, 0xb5, 0x63, 0x94, 0x4d,
0x2c, 0x78, 0xe3, 0xe0, 0xac, 0xb3, 0x89, 0x93, 0x52, 0x3b, 0xe3, 0x2b, 0xe5, 0x97, 0x39, 0xd3,
0x5b, 0x75, 0xe0, 0x57, 0x58, 0x08, 0xa9, 0x62, 0x81, 0x89, 0x9a, 0x34, 0x95, 0x48, 0x21, 0xde,
0x07, 0xf7, 0x67, 0x82, 0x04, 0x45, 0xca, 0x05, 0x01, 0xa1, 0xc7, 0xdb, 0xd7, 0xa0, 0x15, 0xab,
0x08, 0x6c, 0x67, 0xa2, 0x5c, 0x52, 0x1a, 0x96, 0x68, 0x43, 0x56, 0xfe, 0xad, 0x1f, 0xdc, 0xfb,
0x52, 0xaa, 0xd5, 0x4c, 0x39, 0x42, 0xa1, 0xb3, 0x77, 0x81, 0x17, 0xe3, 0x45, 0x72, 0xe5, 0x02,
0x5b, 0xcc, 0xe4, 0x3e, 0x71, 0xbd, 0xb2, 0x08, 0x12, 0x07, 0x1c, 0x06, 0x30, 0xb5, 0xa4, 0x6a,
0xcf, 0xdb, 0xb9, 0x36, 0x64, 0x1b, 0xaf, 0xc9, 0x6d, 0x1d, 0xf6, 0xe2, 0xe9, 0x46, 0x92, 0x14,
0x9b, 0x59, 0x7a, 0x3c, 0x04, 0x9e, 0xc8, 0x1b, 0x5e, 0x44, 0xe9, 0x76, 0x17, 0x27, 0x6a, 0xad,
0xf2, 0x3c, 0xb7, 0xcb, 0xa1, 0xd9, 0x74, 0xea, 0xda, 0xd8, 0x2c, 0x48, 0x94, 0x36, 0xc2, 0xef,
0x6a, 0x77, 0xa9, 0x61, 0x67, 0x98, 0xd2, 0xd6, 0x77, 0x80, 0xe1, 0xb1, 0xcb, 0x50, 0xf6, 0x91,
0x29, 0x46, 0x6b, 0x07, 0x24, 0xb6, 0xac, 0xd4, 0x4e, 0x79, 0x86, 0x5c, 0x72, 0xa4, 0x5c, 0x30,
0x24, 0xe2, 0x9a, 0x5a, 0xf9, 0x01, 0xb9, 0x44, 0x21, 0xba, 0xf9, 0x12, 0x56, 0x63, 0x23, 0x1e,
0x70, 0x38, 0xd5, 0xf1, 0x84, 0xb9, 0xb4, 0xac, 0x7c, 0x55, 0x38, 0x31, 0xe2, 0x76, 0xcd, 0xb3,
0xaa, 0xb5, 0x3b, 0x51, 0xee, 0xe4, 0x90, 0x2e, 0x13, 0xde, 0x84, 0xef, 0x6e, 0x4e, 0x14, 0xfd,
0x68, 0x05, 0x7f, 0xac, 0x49, 0x00, 0x44, 0x70, 0x4d, 0xc4, 0xf9, 0x51, 0x2d, 0x51, 0xac, 0x1b,
0xa9, 0xe0, 0x48, 0x93, 0xdf, 0x1e, 0xd6, 0xb6, 0x0c, 0x7d, 0x3b, 0xb3, 0x23, 0xd8, 0x27, 0xc5,
0x7f, 0xef, 0x43, 0xf4, 0x18, 0x46, 0xbd, 0x64, 0x5c, 0xf1, 0x7c, 0x20, 0xf1, 0x33, 0xb5, 0xa2,
0x6b, 0x42, 0x0c, 0xf5, 0x9c, 0x57, 0x4b, 0xd3, 0x1d, 0xf4, 0xe7, 0x74, 0x58, 0x4f, 0x9d, 0x10,
0xa9, 0x70, 0x6d, 0x88, 0xe0, 0xa0, 0x04, 0xc1, 0x81, 0xc4, 0x70, 0x90, 0xf3, 0x74, 0x21, 0xa7,
0xf3, 0x82, 0x37, 0x56, 0x92, 0x5f, 0xf3, 0x7a, 0xc4, 0x17, 0x02, 0x5b, 0xaf, 0x27, 0xee, 0x88,
0x34, 0xf3, 0x6f, 0x8c, 0x9c, 0xfb, 0x1a, 0x15, 0xac, 0x28, 0x6f, 0x7a, 0x25, 0xb5, 0xd2, 0x1a,
0xff, 0xc1, 0x04, 0x42, 0x96, 0xdb, 0x3e, 0xff, 0x6d, 0x95, 0x9e, 0xa1, 0xeb, 0xcb, 0x87, 0xfe,
0x9c, 0xa1, 0xf5, 0x81, 0x2f, 0xf0, 0x79, 0xc2, 0xe3, 0xff, 0x03, 0xec, 0x8a, 0x5d, 0x45, 0xbd,
0x16, 0x3c, 0x4a, 0x4e, 0xe3, 0x6a, 0x85, 0x29, 0x72, 0x4d, 0xa8, 0x7f, 0xd0, 0x50, 0x83, 0x24,
0xc1, 0x6c, 0x24, 0x5c, 0xc1, 0x32, 0x7c, 0x61, 0xed, 0x26, 0xae, 0xe7, 0xa2, 0x09, 0x0e, 0x89,
0x67, 0xcd, 0x20, 0x8c, 0x8c, 0x56, 0x2c, 0xe2, 0xa6, 0xe6, 0x57, 0x30, 0x81, 0x1e, 0xb7, 0x8a,
0xa0, 0xe2, 0x24, 0xe7, 0x4e, 0x93, 0xae, 0xd5, 0x61, 0x49, 0x43, 0x69, 0xc2, 0x13, 0x34, 0x22,
0x68, 0xff, 0x26, 0xe8, 0x9b, 0xd9, 0x03, 0x00, 0x80, 0xee, 0xda, 0x05, 0x7b, 0x0c, 0xe2, 0x50,
0xcb, 0xcb, 0xc3, 0x85, 0x75, 0xcb, 0xd0, 0xf0, 0xb0, 0xd9, 0x22, 0x31, 0x43, 0x0c, 0x52, 0x16,
0x89, 0xf8, 0x05, 0x5f, 0x7b, 0x31, 0xa6, 0x82, 0x49, 0x52, 0xcd, 0x26, 0xab, 0x48, 0x9c, 0x1b,
0xc1, 0x3a, 0x1d, 0xd7, 0x66, 0x51, 0xe5, 0xf8, 0x9c, 0x0d, 0x13, 0xc5, 0x1a, 0x5e, 0x37, 0x91,
0x39, 0x81, 0xf4, 0xd5, 0x91, 0x2b, 0x3c, 0x35, 0xb2, 0x64, 0xe6, 0x05, 0x13, 0x11, 0xd0, 0xc0,
0x24, 0xd3, 0x69, 0x2e, 0x0a, 0xa8, 0x95, 0x93, 0x76, 0xfe, 0x8e, 0x26, 0xb1, 0x4c, 0x0d, 0x03,
0xdf, 0x8b, 0x8b, 0x1e, 0xc9, 0x07, 0x35, 0xb8, 0x50, 0x6c, 0xda, 0xf5, 0xac, 0xe5, 0x12, 0x3d,
0x82, 0x64, 0x40, 0x44, 0x14, 0xbd, 0x61, 0xb4, 0xc5, 0x06, 0x67, 0xb6, 0x7b, 0x93, 0x6b, 0xb9,
0xfe, 0x25, 0x90, 0x80, 0xaf, 0x5c, 0x82, 0xbe, 0x2e, 0x04, 0xaa, 0xc2, 0x91, 0x12, 0x49, 0xea,
0xfa, 0x3d, 0x3e, 0xa4, 0x26, 0xc6, 0x64, 0xa7, 0x2b, 0xc3, 0xdd, 0x5a, 0xba, 0xad, 0xa4, 0xc9,
0x31, 0x42, 0x2e, 0x98, 0x94, 0x69, 0xed, 0x6b, 0xd4, 0x34, 0xc1, 0x80, 0x47, 0x09, 0x39, 0x0c,
0xc9, 0x81, 0xcc, 0xa6, 0x9a, 0x56, 0x10, 0x97, 0x2c, 0x9e, 0x67, 0xbe, 0x89, 0xae, 0xc8, 0x8a,
0x39, 0xe1, 0xa5, 0x53, 0xee, 0x57, 0x57, 0x9e, 0x77, 0xb0, 0x5a, 0x36, 0x21, 0xc7, 0xf1, 0x5f,
0x90, 0xa3, 0xb3, 0x2b, 0xb1, 0x59, 0x35, 0x5e, 0x34, 0x06, 0x11, 0xc6, 0x43, 0xf4, 0xc0, 0x73,
0x2a, 0xce, 0x15, 0xb2, 0x46, 0x86, 0x82, 0x89, 0x36, 0x30, 0xee, 0x12, 0x08, 0x21, 0x6b, 0x26,
0xb5, 0xd4, 0x2a, 0x17, 0xd4, 0x38, 0xfd, 0x69, 0x9e, 0xe1, 0x80, 0x2d, 0x8a, 0x8a, 0xfc, 0xc3,
0x74, 0x7a, 0x64, 0xe3, 0x6f, 0x34, 0xd5, 0x78, 0xee, 0x08, 0x09, 0xe5, 0x82, 0x5b, 0xdb, 0xc9,
0xca, 0xf5, 0x1c, 0x9e, 0x42, 0x12, 0x3f, 0x40, 0xd9, 0xb6, 0xbd, 0x95, 0xc3, 0xc8, 0xd9, 0x35,
0x48, 0xd4, 0x22, 0x88, 0x59, 0x92, 0x00, 0x36, 0x04, 0xcf, 0xd8, 0x42, 0xf2, 0x04, 0x00, 0xc4,
0xe9, 0x48, 0xed, 0x0f, 0x1d, 0x8f, 0x40, 0x02, 0xbf, 0xe3, 0x70, 0x04, 0x14, 0xae, 0x10, 0x14,
0x40, 0xfe, 0xbe, 0x09, 0x5d, 0xd2, 0xfb, 0x25, 0x09, 0x75, 0x36, 0x8f, 0x35, 0x6a, 0xdb, 0x87,
0x95, 0xad, 0xce, 0xc1, 0x2d, 0x5b, 0xef, 0xea, 0x8b, 0x6c, 0xa5, 0x40, 0xbc, 0x6f, 0x3c, 0xd7,
0xf5, 0x58, 0xdb, 0x3e, 0xbb, 0xec, 0xe8, 0x1c, 0x72, 0x02, 0xdf, 0x2b, 0x7b, 0x28, 0x01, 0x6a,
0x7b, 0xd2, 0xda, 0xf6, 0x39, 0x66, 0xcb, 0x78, 0x89, 0xb4, 0x43, 0x3a, 0x3c, 0x94, 0xf3, 0xf1,
0xec, 0xaa, 0x02, 0xd7, 0x4f, 0x74, 0xf8, 0x96, 0x83, 0x85, 0x39, 0x5e, 0x6c, 0x1d, 0x30, 0x0c,
0x79, 0x71, 0x21, 0xe4, 0xac, 0xcb, 0xa1, 0x4a, 0xc3, 0x90, 0x92, 0xb3, 0x03, 0x79, 0x74, 0x90,
0x39, 0xc2, 0x37, 0x78, 0x72, 0xc0, 0x6b, 0x32, 0x6f, 0xca, 0xcf, 0x0d, 0xb8, 0xfd, 0x3c, 0xe1,
0x11, 0x3c, 0xc8, 0x8b, 0xd8, 0x47, 0x0c, 0x82, 0x17, 0x96, 0xeb, 0xa7, 0x66, 0x19, 0x7f, 0x7c,
0xe4, 0x45, 0x5b, 0x7c, 0x29, 0x95, 0x28, 0x15, 0x75, 0xde, 0xd1, 0x5e, 0x1e, 0x18, 0xa5, 0x65,
0x93, 0x0d, 0xac, 0xfc, 0x67, 0x92, 0x24, 0x46, 0x5e, 0x37, 0x26, 0x35, 0xcb, 0xb6, 0xd9, 0x12,
0x42, 0x9d, 0x06, 0x47, 0x57, 0x61, 0x9a, 0x72, 0xf6, 0x21, 0xb3, 0x2b, 0x6f, 0x72, 0x55, 0x77,
0xda, 0x74, 0x43, 0x81, 0x01, 0x18, 0xf1, 0x2b, 0x7f, 0x5e, 0x66, 0x6a, 0x2c, 0x52, 0x03, 0xe5,
0x9f, 0x9a, 0x55, 0x3f, 0xf6, 0xc5, 0xb9, 0x3b, 0xb5, 0xc0, 0xb5, 0xc0, 0xc7, 0x69, 0x08, 0xda,
0xe9, 0x34, 0x21, 0x6e, 0xe3, 0x45, 0x61, 0x93, 0x7e, 0x85, 0x5d, 0xf7, 0x6f, 0x29, 0x2a, 0x1e,
0xbc, 0x0d, 0x06, 0x4d, 0x4b, 0xb0, 0xf7, 0x1a, 0xcb, 0x4b, 0xff, 0xcc, 0x49, 0xe5, 0xf5, 0x79,
0xc1, 0x55, 0x6d, 0xe9, 0x22, 0x11, 0x57, 0x40, 0x77, 0xef, 0xcc, 0xf5, 0x05, 0x4d, 0xf2, 0xe2,
0x57, 0x09, 0x0b, 0xd6, 0xd4, 0xde, 0x54, 0x1f, 0x32, 0x6d, 0x3b, 0x23, 0x08, 0x03, 0xe5, 0x0f,
0x96, 0x44, 0x3c, 0x26, 0xbc, 0xc1, 0xfa, 0x3f, 0x0f, 0x11, 0xf0, 0x10, 0x78, 0x8a, 0x09, 0x8d,
0x48, 0x72, 0xc0, 0x1a, 0xf3, 0x1a, 0xe9, 0x4b, 0xce, 0x73, 0x24, 0x45, 0x49, 0x62, 0xcd, 0x25,
0x6b, 0x1b, 0x41, 0xf3, 0x29, 0x04, 0xcd, 0xb5, 0x52, 0xe3, 0xbc, 0x28, 0x8b, 0x9f, 0xb3, 0x38,
0x59, 0xd1, 0x0f, 0xe0, 0x89, 0x9a, 0x24, 0x46, 0x27, 0x32, 0x83, 0x45, 0xe2, 0x52, 0x6b, 0x29,
0x69, 0xb9, 0xaa, 0x48, 0xbd, 0xb7, 0x67, 0xd0, 0x0b, 0x79, 0x36, 0x04, 0xdd, 0x93, 0x00, 0xcc,
0xb5, 0xa2, 0x63, 0x42, 0x1b, 0x25, 0x11, 0x78, 0x94, 0x4e, 0x8a, 0x71, 0xc5, 0x47, 0x6b, 0xb1,
0xb0, 0x88, 0x1d, 0x84, 0xa1, 0x4c, 0x66, 0x31, 0x2e, 0x10, 0xde, 0xe0, 0x05, 0x1e, 0x7d, 0x84,
0x70, 0x9b, 0x28, 0x51, 0x1c, 0x06, 0x90, 0xb2, 0xa1, 0x21, 0x49, 0x63, 0x0b, 0x3e, 0x41, 0xad,
0x12, 0x7b, 0x09, 0x33, 0x2b, 0x66, 0xc0, 0xea, 0x13, 0x51, 0xd0, 0xe5, 0x6c, 0x62, 0xc7, 0xff,
0x47, 0x59, 0x06, 0x0d, 0x0a, 0x11, 0xe7, 0x28, 0x96, 0x8c, 0xfb, 0xb0, 0xc9, 0xb8, 0xda, 0x06,
0xe7, 0x8c, 0xf2, 0xbd, 0xf9, 0x13, 0x0a, 0xd4, 0x0d, 0x04, 0xb5, 0x91, 0x8b, 0x44, 0x0b, 0x99,
0x3a, 0x0d, 0x83, 0x28, 0x9a, 0x5a, 0x0e, 0x7b, 0x89, 0x2f, 0x37, 0x1f, 0x84, 0xec, 0x64, 0x08,
0x08, 0xfe, 0x2a, 0xd9, 0x06, 0x71, 0x37, 0xef, 0xaa, 0x88, 0x7b, 0xf0, 0xb6, 0x7b, 0x8e, 0xd0,
0x27, 0x93, 0x45, 0x84, 0x68, 0x65, 0x81, 0xe8, 0xca, 0xf2, 0x58, 0x0c, 0x0e, 0x2d, 0xce, 0xc8,
0x7c, 0x89, 0xb0, 0xab, 0x0f, 0x42, 0x55, 0x90, 0x1a, 0x87, 0x78, 0xc8, 0x3c, 0xbe, 0xb2, 0x44,
0xc8, 0xdf, 0xc9, 0x5f, 0x80, 0xdb, 0xac, 0xfd, 0xdc, 0x9c, 0xbf, 0x20, 0x80, 0x15, 0x6c, 0x84,
0x77, 0x5c, 0x10, 0x12, 0xfc, 0x37, 0xdc, 0x48, 0x55, 0xeb, 0xd2, 0xcd, 0xe8, 0x65, 0x41, 0xaf,
0x95, 0x4c, 0x84, 0x93, 0x60, 0xb5, 0x77, 0xb3, 0x11, 0xfc, 0xe6, 0x53, 0x59, 0x20, 0xf0, 0xc9,
0x72, 0x63, 0x5e, 0xaa, 0x01, 0x4d, 0xab, 0xed, 0xe8, 0x06, 0xff, 0x00, 0x5b, 0xbd, 0xc3, 0xff,
0xe3, 0x6b, 0xc2, 0xe3, 0xdc, 0x5d, 0xbe, 0x7f, 0xbc, 0xf2, 0x43, 0x37, 0x62, 0x25, 0x19, 0x3c,
0xf0, 0x9d, 0x5f, 0xe0, 0xc0, 0x9f, 0x47, 0x82, 0xfc, 0x0f, 0x9d, 0x1c, 0xdf, 0x8c, 0x9a, 0x78,
0x3a, 0xb2, 0xc0, 0x90, 0xdb, 0x2c, 0xa7, 0x3a, 0x2f, 0xf5, 0x93, 0x9e, 0xde, 0xe4, 0x3b, 0x53,
0x13, 0x61, 0xba, 0xb7, 0xe9, 0xf0, 0xa3, 0x48, 0x1d, 0x02, 0x19, 0x88, 0x73, 0x1d, 0x2c, 0xeb,
0x9b, 0x2c, 0x6d, 0x93, 0xa4, 0x5b, 0xcb, 0xe2, 0x35, 0x8c, 0xad, 0xf6, 0x90, 0x57, 0x76, 0xdb,
0xd7, 0x32, 0x06, 0xbf, 0xd0, 0x4d, 0x89, 0x4c, 0x7e, 0xa1, 0x9f, 0x12, 0x39, 0x5c, 0x2b, 0x6f,
0xa9, 0xe4, 0x39, 0x59, 0xba, 0x3c, 0x60, 0x4e, 0xd6, 0x0c, 0x5a, 0x99, 0x91, 0x49, 0x46, 0x5e,
0x0b, 0x3e, 0xe2, 0x18, 0x48, 0x2c, 0x40, 0xb5, 0xee, 0x20, 0x00, 0xf6, 0xc0, 0xf4, 0x40, 0x6a,
0xf3, 0xea, 0x78, 0xbc, 0xb6, 0x19, 0x90, 0x9f, 0x8e, 0x8a, 0x16, 0x46, 0xba, 0x33, 0xd8, 0xf1,
0x13, 0xe7, 0x0e, 0xb7, 0xda, 0xe1, 0xdb, 0x9f, 0xa8, 0x75, 0x6e, 0x42, 0xb1, 0xa2, 0x5a, 0xa2,
0xc4, 0xa3, 0x32, 0xa1, 0x3e, 0xe7, 0x37, 0x5b, 0x89, 0x72, 0x1f, 0x5a, 0x4b, 0xac, 0xb0, 0x2c,
0x82, 0x3b, 0x18, 0xac, 0xee, 0x10, 0xef, 0x5a, 0x32, 0xc4, 0xf2, 0xee, 0xad, 0x75, 0x44, 0x70,
0xa4, 0xba, 0x63, 0x2b, 0x12, 0x70, 0x1f, 0xbb, 0x9c, 0x37, 0xa0, 0x4b, 0x04, 0x1f, 0x37, 0xbf,
0xc4, 0x72, 0x97, 0xee, 0x53, 0x4d, 0x1a, 0x86, 0x50, 0xf4, 0x0e, 0x63, 0xdd, 0x91, 0xbd, 0x8e,
0xd1, 0x89, 0xe1, 0x31, 0x5a, 0x29, 0x9f, 0x3f, 0x5c, 0xe7, 0x13, 0x1f, 0xf2, 0xe1, 0x6a, 0x5c,
0x99, 0xbd, 0xd9, 0x53, 0x9e, 0xaa, 0xe2, 0x6f, 0x5f, 0x92, 0x98, 0x2d, 0x96, 0xde, 0xf6, 0xbc,
0x22, 0x1a, 0xac, 0x65, 0xe1, 0x60, 0x8b, 0x92, 0x7f, 0x3e, 0x1c, 0xa4, 0x49, 0x0f, 0x41, 0xda,
0x6a, 0xd0, 0x82, 0x5c, 0x85, 0xbb, 0xfe, 0xf2, 0xac, 0xf3, 0xff, 0xe8, 0x18, 0xa5, 0x89, 0x27,
0x43, 0xc3, 0x2c, 0x1f, 0x17, 0xbf, 0xd0, 0x99, 0x4c, 0xdb, 0xc4, 0x43, 0x25, 0x3c, 0x61, 0xc2,
0xdf, 0x00, 0xfe, 0x5f, 0x64, 0xb1, 0x62, 0x92, 0x13, 0x58, 0x00, 0x00
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xdd, 0x3c, 0xed, 0x72, 0xe2, 0x48,
0x92, 0xff, 0x79, 0x8a, 0x72, 0xcd, 0xac, 0x5b, 0x5a, 0x64, 0x90, 0xf8, 0xe8, 0x71, 0x03, 0xc2,
0x67, 0xdc, 0xee, 0x1e, 0xef, 0xda, 0x63, 0x87, 0xf1, 0x4c, 0xef, 0x45, 0x4f, 0xc7, 0xb4, 0x90,
0x0a, 0x50, 0x5b, 0x48, 0xac, 0x24, 0xec, 0xe6, 0x6c, 0xee, 0x99, 0xee, 0x19, 0xee, 0xc9, 0x2e,
0xb3, 0xaa, 0xf4, 0x05, 0x12, 0xf6, 0x5c, 0xec, 0xfd, 0xb9, 0x89, 0xe8, 0x31, 0x48, 0x59, 0x59,
0x59, 0x59, 0xf9, 0x5d, 0x59, 0x0c, 0x0e, 0xde, 0x5f, 0x9f, 0xdd, 0xfd, 0xfb, 0xcd, 0x39, 0x99,
0xc7, 0x0b, 0x6f, 0x38, 0xc0, 0xff, 0x13, 0xcf, 0xf2, 0x67, 0x26, 0x65, 0x3e, 0x85, 0xef, 0xcc,
0x72, 0x86, 0x83, 0x05, 0x8b, 0x2d, 0x62, 0xcf, 0xad, 0x30, 0x62, 0xb1, 0x49, 0x57, 0xf1, 0xf4,
0xe8, 0x98, 0xca, 0xa7, 0x35, 0xdf, 0x5a, 0x30, 0x93, 0x3e, 0xb8, 0xec, 0x71, 0x19, 0x84, 0x31,
0x25, 0x76, 0xe0, 0xc7, 0xcc, 0x07, 0xb0, 0x47, 0xd7, 0x89, 0xe7, 0x66, 0x57, 0xd7, 0x53, 0xd0,
0xad, 0x57, 0x0e, 0x7b, 0x70, 0x6d, 0x76, 0xc4, 0xbf, 0x68, 0xae, 0xef, 0xc6, 0xae, 0xe5, 0x1d,
0x45, 0xb6, 0xe5, 0x31, 0xd3, 0xd0, 0x16, 0xd6, 0x77, 0x77, 0xb1, 0x5a, 0xa4, 0xdf, 0x57, 0x11,
0x0b, 0xf9, 0x17, 0x6b, 0x02, 0xdf, 0xfd, 0x80, 0xee, 0xcc, 0x3c, 0x1c, 0xc4, 0x6e, 0xec, 0xb1,
0xe1, 0xe5, 0xf9, 0x7b, 0x32, 0x66, 0x71, 0xec, 0xfa, 0xb3, 0x68, 0xd0, 0x14, 0xcf, 0x06, 0x91,
0x1d, 0xba, 0xcb, 0x78, 0x58, 0x7b, 0xb0, 0x42, 0xe2, 0x98, 0x4e, 0x60, 0xaf, 0x16, 0x40, 0x89,
0xe6, 0x59, 0xcb, 0x90, 0x3d, 0x98, 0xdd, 0x2e, 0xce, 0x37, 0x12, 0xd3, 0xfe, 0x66, 0xea, 0xf8,
0xe7, 0xca, 0xec, 0xb0, 0x36, 0x7e, 0xb8, 0x19, 0x99, 0x1d, 0xfd, 0xdd, 0x5b, 0xfc, 0x78, 0x69,
0x1a, 0xed, 0x36, 0x7f, 0x78, 0x39, 0xf9, 0xe7, 0x2a, 0x88, 0x4d, 0xbd, 0xef, 0x34, 0x56, 0x8b,
0x3f, 0x96, 0xe6, 0xe7, 0x2f, 0x9a, 0xd3, 0x08, 0xa3, 0x07, 0x47, 0x7e, 0x0a, 0xfe, 0x98, 0x2d,
0xdd, 0x40, 0x7c, 0x01, 0x70, 0xf1, 0xad, 0xfd, 0xae, 0x8f, 0xf3, 0x7b, 0x81, 0xed, 0x2e, 0xb5,
0xd8, 0x5d, 0xb0, 0x60, 0x15, 0x6b, 0xf6, 0x2a, 0x8a, 0x83, 0xc5, 0x38, 0xb6, 0xc2, 0x38, 0x32,
0x0f, 0x0c, 0x2d, 0xe2, 0x9f, 0xde, 0xbb, 0x61, 0xbc, 0xc6, 0xe1, 0x30, 0xf8, 0xec, 0xfa, 0xfa,
0x81, 0x85, 0xa1, 0xeb, 0xb0, 0xc8, 0xec, 0x6a, 0x30, 0x1a, 0xc0, 0xfa, 0xd3, 0x95, 0x6f, 0xc7,
0x6e, 0xe0, 0x93, 0x9f, 0x15, 0xf5, 0xe9, 0xd1, 0xf5, 0x9d, 0xe0, 0xb1, 0x11, 0x2c, 0x99, 0xaf,
0xd0, 0x79, 0x1c, 0x2f, 0xa3, 0x5e, 0xb3, 0xb9, 0x58, 0x34, 0xee, 0xfd, 0xa0, 0xf1, 0xe8, 0x31,
0xa7, 0x31, 0x63, 0xcd, 0x29, 0xb3, 0xe2, 0x55, 0xc8, 0xa2, 0x66, 0x24, 0x79, 0xd3, 0xfc, 0x01,
0xde, 0x1c, 0x25, 0xdf, 0xa8, 0xba, 0x49, 0x51, 0x8e, 0xb6, 0x51, 0xa6, 0x63, 0xa8, 0x46, 0xff,
0x88, 0x98, 0x37, 0xcd, 0x43, 0xcf, 0x2e, 0x1c, 0x85, 0xa9, 0x4f, 0x21, 0x03, 0xf4, 0x3e, 0xc1,
0xb9, 0xe2, 0x73, 0x8f, 0x21, 0x7b, 0x47, 0x6b, 0xfe, 0x2a, 0x03, 0x9d, 0xc3, 0x1a, 0x7e, 0x09,
0x2e, 0x6e, 0x01, 0x3f, 0x8e, 0xa2, 0x6e, 0x78, 0xed, 0x5f, 0x4f, 0xa7, 0x2d, 0xaa, 0x36, 0xa2,
0x78, 0xed, 0xb1, 0x86, 0xe3, 0x46, 0x4b, 0xcf, 0x5a, 0x9b, 0xd4, 0x0f, 0x7c, 0x46, 0xb3, 0x81,
0xc1, 0x74, 0x8a, 0x73, 0xe4, 0x91, 0x47, 0xa3, 0xf5, 0x2f, 0x20, 0x00, 0xf0, 0xf8, 0xb3, 0xfe,
0xa5, 0xf1, 0x60, 0x79, 0x2b, 0x66, 0x1e, 0x19, 0xd9, 0x10, 0x2f, 0xb0, 0x9c, 0xbf, 0x8d, 0x15,
0xa6, 0xf9, 0xe6, 0x81, 0xae, 0x3e, 0x79, 0x2c, 0x26, 0xb1, 0xe9, 0x34, 0xec, 0x10, 0xf8, 0xc0,
0x24, 0x0e, 0x85, 0x0a, 0xb9, 0xa0, 0x6a, 0x3f, 0x6e, 0xc0, 0x1a, 0x4f, 0xe3, 0x38, 0x74, 0x27,
0xab, 0x98, 0xc1, 0x8b, 0xd0, 0xa6, 0x1a, 0x53, 0xb5, 0xed, 0xe7, 0xf1, 0x7a, 0xc9, 0x80, 0x0b,
0x31, 0xfb, 0x1e, 0x37, 0xbf, 0x59, 0x0f, 0x56, 0x82, 0x60, 0x07, 0xd0, 0x8a, 0xd6, 0x3e, 0xa0,
0xf0, 0x55, 0x90, 0x80, 0x49, 0xe0, 0xac, 0x1b, 0xd6, 0x12, 0x78, 0xe9, 0x9c, 0xcd, 0x5d, 0xcf,
0x51, 0x62, 0x84, 0xb7, 0x1c, 0xe7, 0xfc, 0x01, 0xa8, 0xb8, 0x74, 0x23, 0x50, 0x0b, 0x16, 0x2a,
0x14, 0x69, 0xa6, 0x9a, 0xa2, 0x9a, 0xc3, 0xa7, 0x8f, 0x2c, 0xfe, 0x4d, 0x51, 0x35, 0x7b, 0xce,
0xec, 0xfb, 0xb1, 0x0b, 0x9f, 0x10, 0xfb, 0xe8, 0x12, 0x3e, 0x1c, 0x19, 0xa6, 0x29, 0xa4, 0x0e,
0x16, 0x7e, 0x78, 0x28, 0x3e, 0x36, 0xa2, 0xb9, 0x3b, 0x8d, 0x15, 0x75, 0x53, 0x8e, 0x18, 0xc4,
0x27, 0x08, 0x61, 0x3d, 0x80, 0x18, 0x94, 0x30, 0x0a, 0x80, 0xd5, 0x5e, 0x30, 0x53, 0xe8, 0x39,
0x3e, 0x27, 0x92, 0x5b, 0xb0, 0xc1, 0x64, 0xea, 0x7a, 0x8c, 0xaf, 0x1b, 0xb4, 0x2e, 0x04, 0xfe,
0x5c, 0xca, 0xe7, 0xc1, 0x14, 0x15, 0x7b, 0xea, 0xce, 0x56, 0xa1, 0xc5, 0xd9, 0x2b, 0xd6, 0x4d,
0xa6, 0x96, 0x8b, 0xf2, 0xf5, 0xbb, 0x7f, 0xe1, 0xdb, 0xc1, 0x62, 0x09, 0x5c, 0x66, 0x64, 0x69,
0xcd, 0x18, 0x71, 0xac, 0xd8, 0x3a, 0x00, 0x31, 0xc9, 0xed, 0x7e, 0x34, 0x0f, 0x1e, 0xef, 0x02,
0x2b, 0x8a, 0xc5, 0xa6, 0x18, 0xea, 0x13, 0x6a, 0x43, 0x6c, 0x72, 0x51, 0x88, 0xf1, 0x05, 0xdf,
0x07, 0xd7, 0x07, 0x92, 0x7f, 0xbe, 0xbb, 0xba, 0x34, 0x19, 0xac, 0xc5, 0xf6, 0xac, 0x28, 0xc2,
0x8d, 0x36, 0xfd, 0x13, 0xb9, 0x8c, 0x1e, 0x45, 0x4c, 0x54, 0xb3, 0x3d, 0x66, 0x85, 0x77, 0x42,
0x8d, 0x14, 0xa9, 0x4e, 0x7c, 0x1f, 0xb8, 0x28, 0x59, 0xbe, 0xbb, 0xe0, 0xa4, 0x4a, 0x61, 0x4a,
0x14, 0xce, 0x04, 0x46, 0x26, 0x83, 0x94, 0x84, 0x36, 0x10, 0xc8, 0xfc, 0x54, 0xb9, 0xcf, 0x8d,
0x90, 0x81, 0x44, 0xda, 0x28, 0x11, 0x7c, 0x52, 0x8a, 0x6b, 0xd2, 0x5a, 0xef, 0x74, 0x3d, 0xb7,
0xb2, 0xc9, 0xa5, 0xbb, 0x70, 0xe3, 0x08, 0xd7, 0xa5, 0xc5, 0x9a, 0xab, 0x59, 0xea, 0x13, 0xb7,
0x27, 0x4c, 0xd8, 0x13, 0x5f, 0xd8, 0x13, 0x57, 0x5a, 0x93, 0x58, 0x98, 0x12, 0x2b, 0x1b, 0xbf,
0x74, 0xfd, 0xe8, 0xfa, 0xef, 0x8a, 0x60, 0x08, 0x33, 0xb7, 0xc4, 0xfc, 0xce, 0x9a, 0x71, 0x49,
0xa7, 0xae, 0xbf, 0x5c, 0x21, 0x8f, 0xa6, 0x41, 0xa8, 0xb8, 0x60, 0x7b, 0xdc, 0x01, 0x6c, 0x23,
0xf3, 0x67, 0xf1, 0xbc, 0xef, 0xd6, 0xeb, 0x62, 0xb4, 0x6f, 0xb2, 0xcf, 0xee, 0x97, 0x06, 0xda,
0xc6, 0x46, 0xb4, 0x9a, 0x44, 0x20, 0x8f, 0xfe, 0x4c, 0xd1, 0xb5, 0x96, 0xda, 0x77, 0xa7, 0xb0,
0x9f, 0x3a, 0x35, 0x4d, 0xff, 0xf9, 0x99, 0x5e, 0x1a, 0xc9, 0x87, 0x56, 0xf2, 0xa1, 0x8d, 0x1f,
0x92, 0x4d, 0x29, 0xc3, 0x22, 0x70, 0x2c, 0xd1, 0x0d, 0x5c, 0x80, 0xf2, 0x94, 0x69, 0x23, 0xbd,
0xbc, 0xa3, 0xf5, 0x38, 0x53, 0x49, 0xcd, 0xd0, 0xd5, 0xa1, 0x79, 0xac, 0xab, 0x68, 0xfb, 0x5d,
0x7f, 0xc5, 0x36, 0x80, 0xe1, 0x15, 0x64, 0xe0, 0x87, 0x8e, 0xfc, 0x70, 0x7b, 0x29, 0x3f, 0x8c,
0xee, 0xe4, 0x87, 0x8b, 0x5b, 0x4e, 0xea, 0xe1, 0x21, 0xa5, 0x07, 0x82, 0x52, 0x3e, 0x19, 0x7c,
0x3f, 0x32, 0x0a, 0x4f, 0xc4, 0x6a, 0x2c, 0x30, 0xa4, 0x9c, 0x69, 0xf7, 0xc0, 0xb4, 0xfb, 0x81,
0x30, 0xd4, 0x09, 0xe7, 0xee, 0x81, 0x73, 0x56, 0x63, 0xb9, 0x8a, 0xe6, 0x8a, 0x78, 0xf1, 0xf9,
0xfe, 0x8b, 0x5a, 0x80, 0xe6, 0xfa, 0x55, 0x06, 0xcd, 0x75, 0x10, 0xa1, 0x61, 0x4d, 0x56, 0x23,
0x0a, 0x60, 0xfd, 0xbe, 0x39, 0xf4, 0x4d, 0x33, 0x65, 0x51, 0x46, 0x09, 0x32, 0x42, 0x55, 0xa5,
0x91, 0x14, 0xca, 0xf5, 0x75, 0x1c, 0x84, 0xe1, 0x5a, 0xe3, 0xbb, 0x4f, 0x7e, 0x7c, 0xfa, 0xdb,
0xf8, 0xfa, 0x97, 0x86, 0xe0, 0xb4, 0x3b, 0x5d, 0x2b, 0x96, 0xba, 0x21, 0xb6, 0xe5, 0xbf, 0x89,
0xc9, 0x84, 0x11, 0xf0, 0x7e, 0x4e, 0xe3, 0xab, 0xaa, 0x65, 0xf8, 0x4c, 0x4a, 0xc5, 0xb7, 0x29,
0xf8, 0xb2, 0x08, 0xcc, 0x02, 0xf8, 0x04, 0xdc, 0x60, 0x60, 0xcd, 0x81, 0xe9, 0x03, 0x27, 0x80,
0x59, 0xfc, 0x43, 0xea, 0x8c, 0xfe, 0xd5, 0x04, 0xa6, 0x88, 0x81, 0x50, 0x2b, 0x64, 0x84, 0x4b,
0x27, 0xd8, 0x12, 0x6f, 0xfd, 0x32, 0xa5, 0xc8, 0xde, 0x6f, 0xa6, 0x5b, 0x37, 0xfa, 0xdf, 0x32,
0x19, 0xfe, 0x96, 0xc8, 0x70, 0x00, 0x3b, 0xf8, 0xed, 0x05, 0x19, 0x0e, 0x12, 0xe1, 0x09, 0x12,
0xe1, 0x09, 0x12, 0xe1, 0x09, 0x12, 0xe1, 0x09, 0x12, 0xe1, 0x09, 0x12, 0xe1, 0x09, 0x12, 0xe1,
0x09, 0xd4, 0x27, 0x8e, 0x0a, 0x3e, 0x9a, 0x41, 0x61, 0x12, 0x43, 0x15, 0x44, 0x78, 0xa5, 0x44,
0xbc, 0x56, 0x05, 0xbc, 0x17, 0x54, 0x40, 0x08, 0xee, 0xb7, 0x54, 0x70, 0x73, 0xec, 0xca, 0x3d,
0xdf, 0xda, 0x8e, 0x1b, 0xd7, 0xe7, 0x56, 0xd8, 0x73, 0x6d, 0x94, 0x8a, 0xf8, 0x91, 0x31, 0x1f,
0xf6, 0x25, 0x55, 0xd5, 0x4d, 0x13, 0xbf, 0x48, 0xa2, 0x37, 0x07, 0x7c, 0x17, 0xbe, 0x15, 0x76,
0xe1, 0x5b, 0x7e, 0x17, 0x36, 0xf0, 0x9f, 0x98, 0xe0, 0x40, 0xcf, 0x6c, 0x51, 0x1c, 0xae, 0xc7,
0xab, 0x09, 0x98, 0x33, 0x74, 0xb8, 0x40, 0xa9, 0xd3, 0x18, 0x4f, 0x1b, 0x68, 0xcd, 0x73, 0x78,
0x1a, 0x18, 0x35, 0xc1, 0x92, 0xdf, 0xb3, 0xa9, 0xb5, 0xf2, 0x62, 0xc4, 0x96, 0x98, 0xb0, 0x84,
0x64, 0x60, 0x5a, 0x1c, 0x2c, 0x6f, 0xc2, 0x00, 0xbc, 0x81, 0x25, 0x4c, 0xac, 0x14, 0x51, 0x1e,
0x39, 0x0d, 0x0d, 0x30, 0xa0, 0xd2, 0x60, 0xd1, 0xbb, 0x20, 0x20, 0x0b, 0xcb, 0x5f, 0x13, 0x08,
0xdd, 0x22, 0x02, 0xb2, 0x41, 0x16, 0x8c, 0xc4, 0x01, 0x99, 0x5b, 0xbe, 0xe3, 0xb1, 0x03, 0xda,
0x47, 0xf3, 0x39, 0x30, 0x58, 0xe7, 0xf0, 0x50, 0xf1, 0xeb, 0x26, 0xfd, 0xdd, 0xff, 0x3d, 0x3c,
0x03, 0x37, 0x06, 0xd1, 0x44, 0x08, 0xaa, 0x81, 0xfe, 0xc9, 0xf2, 0xc9, 0xf9, 0xf8, 0xa6, 0xdd,
0x6a, 0xd0, 0xc4, 0x75, 0xf9, 0xea, 0x86, 0x93, 0xce, 0x3d, 0xe8, 0x6f, 0x96, 0xe7, 0x3a, 0x6e,
0xbc, 0x56, 0x54, 0x54, 0x08, 0x78, 0x1a, 0x89, 0x25, 0xe6, 0x6c, 0x38, 0xf3, 0xb9, 0x7b, 0x95,
0x26, 0x98, 0xfb, 0x24, 0x0c, 0x35, 0x21, 0x34, 0xe1, 0x18, 0x98, 0xd3, 0xe7, 0x03, 0x2f, 0x4f,
0x25, 0x1f, 0xd8, 0x89, 0x08, 0x1e, 0x7b, 0xba, 0x96, 0x00, 0xef, 0x84, 0x31, 0xec, 0x04, 0x6c,
0xb6, 0xe7, 0x82, 0xf7, 0xe9, 0x49, 0x27, 0xc4, 0x41, 0x97, 0xd1, 0xaa, 0xf5, 0x0a, 0xd8, 0xc2,
0x7c, 0x43, 0xfd, 0xf0, 0x30, 0x09, 0x01, 0xf2, 0x44, 0x5f, 0x9e, 0xe6, 0xdc, 0x06, 0x87, 0x87,
0xf8, 0x4c, 0x0c, 0xd9, 0x26, 0x58, 0x4c, 0x7e, 0x79, 0x0a, 0x33, 0xee, 0xcc, 0xde, 0xd5, 0xcd,
0x12, 0x0a, 0x7e, 0xbd, 0xc8, 0x4f, 0x96, 0x4c, 0xff, 0x14, 0x3d, 0xba, 0xb1, 0x3d, 0x57, 0x4a,
0x78, 0x04, 0xa1, 0x96, 0xb6, 0x4d, 0x06, 0xe0, 0xd6, 0x72, 0x0a, 0x93, 0x23, 0x09, 0x34, 0xcd,
0xb6, 0x22, 0x46, 0xf4, 0x5e, 0x29, 0x2a, 0x43, 0x93, 0x7b, 0xd2, 0x9f, 0x40, 0xd0, 0x76, 0xdf,
0xe7, 0xb0, 0x6d, 0xbd, 0xb7, 0x33, 0x41, 0x5b, 0x2f, 0x40, 0x74, 0x4b, 0x20, 0xba, 0x79, 0x88,
0x6e, 0x09, 0x44, 0xb7, 0x00, 0xd1, 0x2a, 0x03, 0x69, 0xa5, 0x30, 0x8e, 0x90, 0xfb, 0xde, 0x1e,
0x86, 0x26, 0xac, 0xdc, 0x70, 0x98, 0x85, 0x01, 0x00, 0x59, 0x60, 0x83, 0xf2, 0xac, 0x95, 0xda,
0x8e, 0x31, 0x84, 0xd6, 0x68, 0x39, 0x76, 0x43, 0x38, 0x21, 0xb1, 0x10, 0xc6, 0x24, 0xfa, 0xa9,
0x6e, 0x6d, 0x0f, 0x60, 0xbb, 0x62, 0x0b, 0x8c, 0x41, 0x92, 0x68, 0xf7, 0x05, 0x33, 0x75, 0x46,
0xeb, 0x7e, 0x66, 0xa6, 0xd4, 0xbe, 0xd4, 0xdc, 0xb8, 0xfe, 0xc2, 0xc0, 0xf1, 0x65, 0x71, 0xa0,
0xc6, 0x06, 0xed, 0xd6, 0x49, 0xa6, 0xa3, 0x6d, 0xd3, 0x2c, 0x9f, 0x50, 0x2f, 0x8c, 0x3b, 0x61,
0xc3, 0xd6, 0xbb, 0x93, 0x96, 0xfe, 0xd7, 0xb8, 0x67, 0x74, 0xe1, 0x7f, 0x88, 0x60, 0x68, 0x02,
0x06, 0xf1, 0xe2, 0x18, 0x1e, 0xbd, 0x85, 0x7f, 0xfc, 0x4b, 0x07, 0x3e, 0xb4, 0xf9, 0x97, 0xb6,
0x01, 0xc6, 0x72, 0xd0, 0x39, 0x3e, 0xe9, 0xf6, 0x3a, 0x1d, 0x90, 0xd9, 0xe7, 0xe7, 0x4e, 0x17,
0x45, 0x57, 0x42, 0x64, 0xec, 0x00, 0xe6, 0xb0, 0x34, 0xc8, 0xc4, 0x70, 0x53, 0xc3, 0x74, 0x4d,
0x08, 0xda, 0x62, 0xf9, 0x68, 0x85, 0x3e, 0xd8, 0x8d, 0x9d, 0x6d, 0xe3, 0x9b, 0x7e, 0x95, 0xe8,
0xdc, 0x4f, 0x2d, 0x5d, 0xdf, 0x51, 0x0a, 0x10, 0x03, 0xd3, 0x2c, 0xc8, 0xb1, 0xb4, 0x04, 0xa6,
0xd1, 0xea, 0xed, 0xe8, 0xac, 0x22, 0xdf, 0x15, 0x05, 0xbf, 0x2f, 0xc2, 0x92, 0xaa, 0x40, 0x0f,
0x64, 0x8e, 0xd9, 0xc5, 0x48, 0xcf, 0xca, 0x47, 0x7a, 0xdc, 0x75, 0xa1, 0x3f, 0xb3, 0x2a, 0x62,
0xbd, 0xc4, 0x8f, 0x5a, 0xa5, 0x51, 0x9c, 0xe6, 0x65, 0x3b, 0x6c, 0x15, 0x02, 0x00, 0xc1, 0x9f,
0xa5, 0xee, 0xd0, 0x7a, 0x90, 0x17, 0x58, 0x0f, 0x1d, 0xd8, 0xe1, 0xa1, 0x37, 0x78, 0xf7, 0xf6,
0x84, 0x5e, 0xdc, 0x10, 0x10, 0x4f, 0x48, 0x25, 0xa3, 0x1e, 0xed, 0x79, 0xc3, 0xce, 0xbb, 0x13,
0xfa, 0x1e, 0xfc, 0x03, 0xf9, 0x78, 0x73, 0x71, 0x2d, 0x9e, 0x18, 0x27, 0x14, 0xbf, 0xe0, 0x7b,
0x2a, 0x9e, 0x4a, 0xc3, 0x67, 0xec, 0x22, 0xee, 0xbc, 0x43, 0xbc, 0x6f, 0x3b, 0x27, 0xf4, 0xcc,
0xbb, 0x4f, 0x70, 0x50, 0xca, 0x39, 0x14, 0x55, 0x08, 0x92, 0x81, 0x58, 0x40, 0x90, 0x38, 0x7f,
0x40, 0x5e, 0xa5, 0xe8, 0x7b, 0x5a, 0xa0, 0x6a, 0x53, 0x13, 0xc2, 0x8b, 0x41, 0xb7, 0x3f, 0xc5,
0x68, 0x42, 0xa9, 0xc2, 0x40, 0xeb, 0x53, 0x81, 0x42, 0xc5, 0x2d, 0xca, 0x56, 0x77, 0x78, 0x38,
0x1d, 0x74, 0x9e, 0x9f, 0x05, 0x59, 0x90, 0x68, 0x4d, 0xf9, 0x67, 0x03, 0x5f, 0x76, 0x01, 0x64,
0x5a, 0xef, 0xe8, 0x03, 0xef, 0x44, 0x89, 0x2a, 0xb4, 0x5d, 0x8b, 0x20, 0x5f, 0xf8, 0xe7, 0xca,
0x0d, 0xb9, 0x29, 0x54, 0x7b, 0xbb, 0x80, 0x42, 0x86, 0xf2, 0x60, 0x90, 0xf2, 0xa7, 0xae, 0x55,
0x55, 0x37, 0x10, 0x0c, 0x08, 0xcb, 0x1a, 0x4e, 0x39, 0xaf, 0x12, 0x73, 0x58, 0xf2, 0xec, 0xf9,
0xb9, 0x0d, 0x24, 0x7a, 0x9a, 0xc7, 0xb5, 0xc2, 0x03, 0xad, 0x80, 0xb1, 0x95, 0xba, 0x1e, 0xe4,
0x12, 0x65, 0x08, 0x72, 0xb4, 0x3c, 0xc2, 0xc0, 0xb7, 0x21, 0xa8, 0xb8, 0x37, 0x39, 0xbe, 0x13,
0x4c, 0x40, 0x0f, 0x8c, 0x1e, 0xcf, 0x43, 0x37, 0x90, 0xaa, 0xb5, 0xc1, 0x39, 0x78, 0x72, 0x32,
0xce, 0x0f, 0xce, 0xac, 0x0e, 0x30, 0xab, 0xd3, 0x3e, 0xc0, 0x47, 0xc7, 0xc7, 0x48, 0x06, 0x47,
0x68, 0x07, 0x1c, 0x61, 0x71, 0xd5, 0x39, 0x06, 0xe3, 0x78, 0x53, 0x22, 0x38, 0x3e, 0x11, 0xec,
0xe8, 0xa5, 0xec, 0xe3, 0x28, 0x1c, 0x77, 0x06, 0x38, 0xea, 0xf4, 0x71, 0x47, 0x3b, 0xf3, 0x84,
0xec, 0xe8, 0x65, 0x5b, 0x07, 0x5a, 0xc0, 0xfa, 0x18, 0xfc, 0x4f, 0x39, 0x1f, 0x3e, 0x5d, 0x17,
0xf9, 0xa0, 0xab, 0xc5, 0x29, 0x6d, 0x5a, 0x42, 0xfa, 0xeb, 0xa8, 0x0d, 0xe9, 0x9e, 0x55, 0xef,
0x1f, 0x1a, 0xd1, 0x7f, 0x0d, 0xc3, 0xa6, 0x65, 0x78, 0x8c, 0xb7, 0x38, 0xb4, 0xdd, 0xe2, 0x78,
0xba, 0x7a, 0xa2, 0x6c, 0x65, 0x71, 0x49, 0x82, 0xc7, 0xda, 0xc1, 0x03, 0x79, 0x44, 0x07, 0xd9,
0x5b, 0x3e, 0x0e, 0xec, 0xdb, 0xae, 0xbd, 0xc8, 0x48, 0xbe, 0xf0, 0x1f, 0x20, 0x20, 0x63, 0x0e,
0x81, 0x94, 0x1b, 0x13, 0xd8, 0x1e, 0xbd, 0x85, 0xe8, 0x11, 0xec, 0x8f, 0x43, 0x94, 0x30, 0x88,
0x2d, 0x7c, 0x65, 0x1c, 0xeb, 0xff, 0xfd, 0x5f, 0x6a, 0x1a, 0x1f, 0x39, 0xfb, 0xf1, 0x39, 0xec,
0x3b, 0x1a, 0x09, 0x5e, 0x34, 0xeb, 0xd1, 0x0d, 0x9a, 0x8a, 0x10, 0x14, 0xfd, 0x9f, 0x2b, 0x06,
0xce, 0x91, 0xdb, 0xce, 0x20, 0x3c, 0xf5, 0x3c, 0x85, 0x36, 0x1e, 0x61, 0x47, 0xb5, 0xa5, 0x19,
0x26, 0xd6, 0x33, 0x33, 0xa8, 0x4b, 0x6e, 0x49, 0x43, 0x34, 0x7f, 0x5b, 0x6b, 0xdd, 0x5e, 0x24,
0x37, 0x45, 0xab, 0x97, 0xb2, 0x72, 0x6d, 0x61, 0xea, 0xda, 0x03, 0xfc, 0xb3, 0x01, 0x7d, 0x36,
0xcd, 0x6a, 0x27, 0x43, 0x9f, 0x99, 0xab, 0xaa, 0x0c, 0x3d, 0x28, 0x7d, 0x95, 0xa4, 0x3d, 0x67,
0x90, 0x33, 0xcc, 0x64, 0xde, 0x82, 0x29, 0xd0, 0x2c, 0x49, 0x81, 0x66, 0xea, 0x0b, 0x4a, 0x0f,
0xae, 0xd5, 0xe4, 0xb5, 0x87, 0x7e, 0xc9, 0xe0, 0x24, 0x7f, 0x9a, 0x25, 0xf9, 0x93, 0x98, 0x43,
0xf1, 0xcc, 0x97, 0xd3, 0x9c, 0x9c, 0x2e, 0xa9, 0x22, 0xc9, 0x79, 0xe2, 0x2b, 0xc0, 0x09, 0xc1,
0x4f, 0x6a, 0xe2, 0x8b, 0xeb, 0x03, 0x5b, 0x56, 0x19, 0xa7, 0xed, 0xc0, 0x0b, 0x42, 0x93, 0xfe,
0x30, 0x9d, 0x4e, 0x69, 0x3f, 0xcd, 0x8a, 0xd2, 0x81, 0x59, 0xc5, 0x34, 0x1b, 0x7f, 0x64, 0xe4,
0x0a, 0x07, 0xfb, 0x68, 0x4f, 0x72, 0xbf, 0x59, 0x92, 0xfb, 0xcd, 0x92, 0xdc, 0x6f, 0x96, 0xe4,
0x7e, 0x33, 0x59, 0x38, 0x58, 0xed, 0x14, 0x0e, 0x56, 0x5b, 0x85, 0x83, 0xe9, 0x4b, 0x85, 0x83,
0xe9, 0x9f, 0x2a, 0x1c, 0x4c, 0x77, 0x0a, 0x07, 0x22, 0x0f, 0xd6, 0x21, 0x0b, 0x5e, 0xe5, 0xb3,
0x60, 0x58, 0xaa, 0x7b, 0x60, 0x7e, 0x13, 0x44, 0xac, 0x81, 0xac, 0x97, 0xb2, 0xe1, 0x75, 0xc2,
0x91, 0x75, 0xc2, 0x91, 0x75, 0xc2, 0x91, 0x75, 0xc2, 0x91, 0x75, 0xc2, 0x91, 0x75, 0xc2, 0x91,
0x75, 0xc2, 0x91, 0x75, 0x2e, 0x1b, 0x5e, 0x97, 0x66, 0xc3, 0x97, 0xa5, 0x44, 0xbc, 0x36, 0x1b,
0xbe, 0xdc, 0x97, 0x0d, 0x8b, 0xad, 0xf8, 0xb6, 0xb3, 0x15, 0xd9, 0x13, 0xc9, 0xb7, 0x74, 0x9e,
0xec, 0x1d, 0x2f, 0x5a, 0x6c, 0x36, 0x53, 0x51, 0xdb, 0x60, 0xe6, 0x90, 0xe5, 0x6a, 0x1b, 0xab,
0x62, 0x6d, 0xe3, 0x64, 0x57, 0x02, 0xc1, 0xff, 0xd2, 0xde, 0xce, 0xe3, 0xad, 0x8a, 0xc9, 0x0b,
0x58, 0x69, 0x10, 0x5a, 0xfe, 0x0c, 0x8d, 0x05, 0x97, 0xe7, 0x8d, 0xa8, 0xc0, 0xcc, 0x92, 0x0a,
0x0c, 0x7e, 0x00, 0xae, 0x1f, 0xa0, 0xf8, 0x29, 0x2f, 0x88, 0x38, 0x38, 0x7f, 0x2f, 0x62, 0x9c,
0xdf, 0x17, 0x55, 0x13, 0xf6, 0xf3, 0xe7, 0x05, 0x90, 0x12, 0x66, 0xa7, 0x05, 0x9f, 0x83, 0x2f,
0x30, 0x05, 0x37, 0xa0, 0x5e, 0xc4, 0xed, 0xa7, 0xf0, 0x71, 0x0b, 0xe9, 0xe3, 0xe4, 0x43, 0x30,
0x73, 0x98, 0x68, 0x41, 0xe0, 0x91, 0xc7, 0xa4, 0x5d, 0x80, 0xcb, 0x54, 0xac, 0x6c, 0xd6, 0x1d,
0x3c, 0xaa, 0x5a, 0xbf, 0x18, 0x2e, 0x00, 0x6a, 0x61, 0x5a, 0xf5, 0x0b, 0x55, 0xbb, 0x18, 0xda,
0xf0, 0xc5, 0x36, 0xe1, 0xe3, 0x9f, 0x37, 0x15, 0x03, 0xf4, 0x6e, 0xca, 0x43, 0x1d, 0x46, 0xc3,
0xf6, 0x89, 0xb9, 0xd0, 0xf7, 0x62, 0x59, 0xfd, 0x4c, 0x9e, 0x12, 0x2d, 0xa4, 0x33, 0xd8, 0x79,
0x6e, 0x9a, 0x0f, 0x27, 0x14, 0xf8, 0xad, 0xd0, 0xfa, 0x43, 0x9d, 0x92, 0xe5, 0x7c, 0x1d, 0xb9,
0xb6, 0xe5, 0x25, 0xde, 0x63, 0xa1, 0x17, 0x72, 0xad, 0x58, 0x13, 0x47, 0x35, 0x71, 0x13, 0x13,
0x8c, 0xbf, 0x1a, 0xba, 0xcc, 0xd7, 0x9d, 0x89, 0x95, 0xb9, 0xec, 0x89, 0x65, 0xdf, 0xcf, 0xc2,
0x60, 0xe5, 0x3b, 0xe6, 0x57, 0x34, 0xfd, 0x56, 0x78, 0x34, 0x0b, 0x2d, 0xc7, 0xc5, 0x33, 0x82,
0x77, 0xba, 0xc3, 0x66, 0x1a, 0xf9, 0xf1, 0x49, 0x14, 0x2e, 0xde, 0xea, 0x27, 0xe2, 0xc3, 0x3b,
0x48, 0x0d, 0xb8, 0x00, 0xe5, 0x24, 0xc0, 0xb6, 0x6d, 0xba, 0x21, 0x7a, 0x02, 0xbc, 0xf9, 0x8b,
0x46, 0x7e, 0xe8, 0x74, 0x3a, 0xd9, 0x77, 0x02, 0xf3, 0xff, 0x45, 0xfd, 0x2a, 0x77, 0x84, 0x39,
0x55, 0x79, 0x88, 0x3d, 0xbc, 0xb2, 0xe2, 0x39, 0xca, 0x85, 0xc2, 0x0d, 0xb7, 0x76, 0xac, 0xeb,
0xea, 0xf3, 0xb3, 0x98, 0xf9, 0x58, 0x2f, 0xf7, 0xc3, 0x25, 0xf8, 0x84, 0x44, 0x27, 0xd8, 0xac,
0xef, 0x25, 0xd8, 0x0c, 0x7d, 0x7b, 0x21, 0x02, 0xdb, 0x23, 0xa4, 0xba, 0x51, 0xe0, 0x17, 0x98,
0x99, 0xcd, 0x7f, 0xac, 0xff, 0x05, 0x0f, 0x05, 0x00, 0x5d, 0x03, 0xcb, 0x36, 0x64, 0xc1, 0x16,
0x41, 0xb8, 0xa6, 0xf5, 0xac, 0xbc, 0x73, 0xf2, 0x95, 0x28, 0x83, 0xc9, 0xf0, 0xfc, 0xf6, 0xf6,
0xfa, 0xb6, 0x47, 0x7e, 0xe5, 0x65, 0x9a, 0x00, 0xfc, 0x3e, 0x30, 0x03, 0x77, 0x62, 0x33, 0x3a,
0x18, 0x34, 0x27, 0x43, 0xf5, 0x2b, 0x04, 0xfb, 0x6a, 0x0f, 0xf0, 0xe9, 0xa2, 0xfc, 0xb3, 0x04,
0x08, 0x19, 0x28, 0x70, 0xc7, 0x3b, 0x37, 0x39, 0xed, 0x36, 0x73, 0x3d, 0x45, 0x01, 0xb4, 0xf5,
0x87, 0xbf, 0x8a, 0x94, 0x4a, 0x6d, 0x76, 0x61, 0x15, 0xcd, 0x56, 0x7f, 0x6e, 0xce, 0x87, 0xdd,
0x93, 0x0c, 0x6a, 0xae, 0xf6, 0xe6, 0x7d, 0xcb, 0x94, 0x39, 0xc4, 0x88, 0x47, 0x8d, 0xdb, 0xc9,
0xbc, 0x36, 0x31, 0xf3, 0x79, 0x5c, 0x56, 0x33, 0x99, 0x0f, 0x8c, 0x86, 0xde, 0x3a, 0x3c, 0x3c,
0x18, 0xc1, 0xbf, 0xc9, 0x09, 0xa0, 0x39, 0x1f, 0xdf, 0x90, 0xee, 0x6f, 0x58, 0x04, 0x25, 0x8f,
0x6e, 0x3c, 0x27, 0xc6, 0x29, 0xf9, 0x75, 0x3c, 0x22, 0xd1, 0x6a, 0xb9, 0xf4, 0xd6, 0xb4, 0xa7,
0x58, 0x75, 0x73, 0x74, 0x42, 0x8d, 0xd6, 0x6f, 0x84, 0xf6, 0x26, 0x27, 0xf4, 0xd3, 0xb8, 0x75,
0x6c, 0x74, 0x89, 0xf8, 0x4e, 0x61, 0x20, 0xd5, 0x00, 0x62, 0x8e, 0xff, 0xa3, 0xa7, 0x72, 0x14,
0x56, 0xf1, 0x7c, 0x88, 0x52, 0x20, 0xf0, 0x89, 0x03, 0xbe, 0x6c, 0x2a, 0x52, 0xc2, 0x71, 0xf5,
0x62, 0x0d, 0xb1, 0x5a, 0xed, 0xdc, 0xa4, 0x0a, 0x2f, 0x91, 0x05, 0x51, 0x4c, 0xd8, 0x74, 0x0a,
0x68, 0x22, 0x8d, 0xfc, 0x27, 0xed, 0x9f, 0xd7, 0xcd, 0xb1, 0x39, 0x2e, 0x70, 0x62, 0xac, 0xf6,
0xc6, 0xda, 0x39, 0x9f, 0xd8, 0x8d, 0x08, 0xf3, 0x83, 0xd5, 0x6c, 0xae, 0x0e, 0x26, 0xe1, 0x30,
0x2b, 0x44, 0x15, 0xb6, 0xd7, 0x2a, 0xd4, 0xa7, 0x72, 0xdb, 0x8e, 0xfa, 0x76, 0x2e, 0x5e, 0x7e,
0x13, 0x32, 0x51, 0x14, 0xd7, 0x63, 0xc9, 0xc9, 0x8b, 0x3b, 0x99, 0x11, 0xd3, 0x44, 0x32, 0x73,
0x07, 0x72, 0x56, 0x14, 0x9f, 0xfb, 0x8e, 0x2c, 0x2b, 0xb2, 0x81, 0x91, 0x94, 0x0a, 0xf5, 0xfe,
0xc3, 0x4b, 0xf6, 0x63, 0x0c, 0x82, 0xc5, 0xc0, 0x40, 0xe6, 0x6c, 0x48, 0xfd, 0xe5, 0xea, 0xc6,
0xf6, 0x90, 0xbe, 0x28, 0x05, 0xbc, 0x6c, 0xab, 0x76, 0x06, 0x4a, 0x4a, 0x7d, 0x9e, 0x68, 0xf9,
0x22, 0xd1, 0x82, 0x7c, 0x5f, 0xd5, 0xdc, 0xe8, 0x17, 0xeb, 0x17, 0xe5, 0x41, 0x3d, 0xd1, 0x7b,
0x0f, 0xd9, 0x52, 0x21, 0x3d, 0xc6, 0x4d, 0x4d, 0x0f, 0x1f, 0xc5, 0x91, 0xca, 0xd6, 0x74, 0x67,
0xc9, 0x11, 0x13, 0x84, 0x90, 0xe3, 0x3b, 0x08, 0x20, 0x5d, 0x33, 0x4e, 0x83, 0xc5, 0xa9, 0x72,
0xa0, 0x40, 0x96, 0x03, 0xce, 0xcf, 0x1d, 0x62, 0xe8, 0x36, 0xaa, 0xe3, 0x49, 0xd2, 0xf3, 0xf3,
0x91, 0x78, 0x08, 0x12, 0xed, 0xaa, 0xc9, 0xe1, 0x86, 0xb0, 0x7a, 0xb0, 0x60, 0xee, 0x8d, 0x11,
0x20, 0x49, 0xff, 0xbf, 0x0e, 0x1c, 0xf7, 0x81, 0xf0, 0xb3, 0x2c, 0x93, 0x4f, 0x32, 0xfc, 0xdd,
0x1f, 0xcc, 0xc3, 0xe4, 0x49, 0xb4, 0xf0, 0xf0, 0xc9, 0x8f, 0x4f, 0x6e, 0xdd, 0xd8, 0xf4, 0xe0,
0x95, 0xa8, 0x3b, 0x10, 0x71, 0xb0, 0x7e, 0x79, 0x07, 0x2f, 0x36, 0x94, 0x40, 0x6e, 0x38, 0x47,
0xb3, 0x60, 0xd2, 0x5f, 0x2f, 0x94, 0x38, 0x04, 0x76, 0xd0, 0x21, 0xbc, 0x11, 0x64, 0xe1, 0x46,
0xbf, 0x19, 0x04, 0x4b, 0xbe, 0x6c, 0x99, 0xc5, 0xb6, 0x5a, 0x94, 0x08, 0x4c, 0xcc, 0x19, 0x72,
0x75, 0xf8, 0x3e, 0x68, 0x0a, 0x90, 0xe1, 0x16, 0x68, 0x5b, 0xa7, 0xc3, 0xf1, 0xdf, 0xdf, 0x1e,
0x1b, 0x2d, 0x72, 0xfb, 0x71, 0xf4, 0xa9, 0x12, 0xcc, 0xa0, 0xc3, 0xbb, 0x2b, 0xe3, 0xd8, 0xe8,
0x54, 0x41, 0xb4, 0x3a, 0x14, 0xd2, 0x52, 0xfd, 0xfe, 0xe7, 0xff, 0xa8, 0x84, 0xe8, 0x0a, 0x1c,
0xad, 0x77, 0x55, 0x10, 0x5d, 0x20, 0x06, 0xc9, 0xd5, 0x8d, 0x4a, 0x08, 0xa0, 0xe3, 0xf4, 0xe6,
0xd4, 0xd0, 0x5b, 0x95, 0x10, 0x2d, 0x3a, 0xbc, 0xbc, 0x79, 0x7f, 0x7c, 0xac, 0xbf, 0xad, 0x04,
0xe9, 0x70, 0x90, 0xb7, 0xc7, 0x7a, 0xbb, 0x12, 0xa4, 0x4d, 0x87, 0x37, 0xef, 0x8e, 0x8d, 0x4a,
0x80, 0x0e, 0x90, 0x7a, 0xed, 0x37, 0xaf, 0xa7, 0xd3, 0x4a, 0x08, 0x20, 0xf5, 0xe6, 0xd3, 0x15,
0xf9, 0x34, 0x77, 0x63, 0x56, 0x09, 0xd4, 0x12, 0x40, 0x67, 0x67, 0x77, 0x95, 0x20, 0x6d, 0x01,
0x02, 0xdb, 0x53, 0x09, 0xd2, 0x49, 0x41, 0x2a, 0x77, 0xb0, 0xd3, 0x4d, 0x61, 0xea, 0xf9, 0xd9,
0x7e, 0xff, 0xde, 0xb6, 0x0f, 0x8e, 0x8e, 0xb6, 0x80, 0xdf, 0x66, 0xc0, 0xef, 0x73, 0xd0, 0x47,
0x47, 0x00, 0xce, 0xde, 0x6c, 0x40, 0x52, 0x8b, 0x03, 0x8e, 0x81, 0x1d, 0xef, 0xdf, 0xdf, 0xe0,
0x00, 0xa2, 0xf8, 0x2c, 0x7e, 0x0c, 0xc2, 0x7b, 0x35, 0x9b, 0xc3, 0x2f, 0x9d, 0xe5, 0x18, 0x38,
0x74, 0x6e, 0x34, 0xda, 0x46, 0xf9, 0x30, 0x31, 0x59, 0xd5, 0x58, 0x60, 0xdc, 0x69, 0x18, 0xff,
0xc2, 0xe2, 0xfd, 0x83, 0xb7, 0xe9, 0x3c, 0x4e, 0xe9, 0xfc, 0x54, 0x4a, 0xe8, 0xa0, 0x29, 0x14,
0x67, 0x88, 0x46, 0x1a, 0xbe, 0xa2, 0xfa, 0xba, 0x8e, 0x49, 0xed, 0x40, 0xe8, 0x22, 0xb7, 0xba,
0x26, 0x95, 0x66, 0xb7, 0x27, 0x83, 0x80, 0xe1, 0x19, 0x7a, 0x79, 0x72, 0x1d, 0x3a, 0x2c, 0xdc,
0x51, 0xe3, 0xb3, 0x6b, 0x3e, 0x74, 0xb8, 0x43, 0x0c, 0xf0, 0xec, 0xe3, 0xed, 0x28, 0x3f, 0x79,
0xf1, 0x3d, 0xb0, 0x27, 0xbf, 0xe9, 0x3b, 0xef, 0x81, 0x05, 0xa3, 0xdb, 0x8f, 0xd5, 0xef, 0x41,
0x70, 0x6e, 0x47, 0x7b, 0xde, 0x83, 0xd4, 0x8c, 0x3e, 0xde, 0x56, 0xbf, 0x07, 0x89, 0xf9, 0x38,
0xba, 0x2d, 0x65, 0x4e, 0x13, 0xf8, 0x92, 0x67, 0x8f, 0xe3, 0xce, 0x70, 0x91, 0x8f, 0x3b, 0x0c,
0xe2, 0x2e, 0x68, 0x38, 0x7e, 0xb4, 0x96, 0x3d, 0x52, 0x64, 0xcb, 0x27, 0xc9, 0x96, 0x5d, 0xa6,
0xfc, 0x02, 0x63, 0xaa, 0xc4, 0x18, 0x78, 0xf2, 0x89, 0x1c, 0x92, 0x4a, 0x55, 0x68, 0x89, 0xf7,
0x1f, 0x2b, 0x0d, 0x99, 0x78, 0x9f, 0xad, 0xaa, 0x74, 0x4d, 0xf8, 0x27, 0x5a, 0x5a, 0x3e, 0x5f,
0xdb, 0x32, 0x72, 0x04, 0xa5, 0xa2, 0xda, 0x01, 0x03, 0xe0, 0xcd, 0x90, 0x0c, 0xc4, 0x71, 0x2b,
0xb6, 0xa3, 0x98, 0xd4, 0x5f, 0x2d, 0x26, 0x2c, 0xa4, 0x89, 0xe1, 0x1e, 0x0b, 0x61, 0xc1, 0xd1,
0x5e, 0x24, 0x3e, 0x4b, 0x8b, 0xef, 0x11, 0x91, 0x30, 0x50, 0x82, 0x19, 0x07, 0xac, 0x16, 0x03,
0x38, 0x54, 0x85, 0x77, 0x06, 0x4d, 0x68, 0xfc, 0xf1, 0x29, 0xf1, 0xd4, 0xae, 0xca, 0xcd, 0x3f,
0x9f, 0x09, 0xbc, 0x45, 0x2e, 0xd5, 0x40, 0xa4, 0x5f, 0x4c, 0x74, 0x06, 0x7d, 0x3c, 0x84, 0xe8,
0x53, 0x92, 0xd4, 0x33, 0x49, 0x73, 0x78, 0xe8, 0x4f, 0xa2, 0x65, 0x7f, 0x77, 0x7b, 0xec, 0x4a,
0xf9, 0xbd, 0xe4, 0x5e, 0xaf, 0xb7, 0x77, 0x51, 0x67, 0xc5, 0x85, 0xc8, 0x15, 0x18, 0x72, 0x05,
0x3c, 0xa6, 0xbc, 0x19, 0x6d, 0x68, 0xb6, 0x53, 0x19, 0x49, 0xe9, 0x12, 0x90, 0x56, 0x0a, 0x14,
0x0a, 0x66, 0x4b, 0x1d, 0x6b, 0xee, 0x70, 0x5c, 0x97, 0x1c, 0xe7, 0xc5, 0xe8, 0xd7, 0x30, 0x5c,
0x17, 0xb4, 0xa5, 0x13, 0x26, 0xfe, 0x75, 0xcb, 0x79, 0xaa, 0xb4, 0x59, 0x9c, 0xc8, 0x90, 0x13,
0xc9, 0x39, 0xf6, 0x4d, 0x61, 0x14, 0x96, 0xff, 0x22, 0xe6, 0xd6, 0xeb, 0x31, 0xb7, 0xfe, 0x1c,
0xe6, 0xf6, 0xeb, 0x31, 0xb7, 0xff, 0x1c, 0xe6, 0xce, 0xeb, 0x31, 0x77, 0x5e, 0x83, 0x79, 0x4b,
0xfc, 0xc2, 0x4a, 0xf1, 0x43, 0x41, 0xc8, 0xe8, 0x80, 0x68, 0x5b, 0xd0, 0x91, 0x54, 0x29, 0x25,
0x3d, 0x5b, 0xe2, 0xc9, 0x6b, 0xf0, 0x93, 0xe0, 0x7b, 0x42, 0xd3, 0xd9, 0x6f, 0x09, 0xf5, 0xe5,
0xc6, 0x29, 0xda, 0x3b, 0xfd, 0xf8, 0xde, 0x5d, 0x92, 0xa9, 0x1b, 0x42, 0x4c, 0x8f, 0x91, 0xe3,
0x5e, 0x55, 0x18, 0x5f, 0x8a, 0xd5, 0x17, 0x54, 0x18, 0xb2, 0x19, 0x9a, 0x19, 0xb1, 0x2d, 0x91,
0xaf, 0x24, 0x6a, 0xba, 0x97, 0x28, 0x08, 0x2f, 0xc8, 0x2d, 0x9b, 0x86, 0x2c, 0xca, 0x74, 0x93,
0x73, 0x68, 0x2a, 0x08, 0x28, 0x67, 0xc4, 0xed, 0x87, 0xfd, 0x8c, 0xb0, 0xf6, 0xce, 0x79, 0xba,
0x8a, 0x83, 0x23, 0xc8, 0xe6, 0xed, 0x95, 0x67, 0xc5, 0x8c, 0x3c, 0x62, 0xf8, 0x82, 0xad, 0xa7,
0x90, 0x8b, 0x78, 0x64, 0x1a, 0x06, 0x0b, 0x74, 0x9e, 0x3d, 0xb1, 0x63, 0x79, 0x7b, 0x7e, 0xfa,
0xa9, 0xcc, 0x9e, 0xeb, 0xfb, 0xac, 0xb9, 0x31, 0x1c, 0x85, 0xee, 0x6c, 0x1e, 0xb3, 0xb0, 0x02,
0xa0, 0x35, 0x3c, 0xb5, 0x6d, 0x6c, 0x78, 0xab, 0xc2, 0xd0, 0x1e, 0xbe, 0x5f, 0x59, 0xde, 0xae,
0x31, 0x17, 0x16, 0x30, 0x65, 0x00, 0xff, 0xfb, 0xb5, 0x6f, 0x41, 0x46, 0x15, 0xb1, 0x30, 0x3e,
0x75, 0xbe, 0x59, 0x36, 0xe4, 0x00, 0x98, 0x5a, 0x29, 0x74, 0xc2, 0x20, 0x9b, 0x63, 0xcc, 0x77,
0xa8, 0x16, 0xa8, 0x1b, 0x19, 0xdf, 0x2b, 0xf1, 0xe7, 0xa3, 0x23, 0xf7, 0x4b, 0x23, 0x84, 0xac,
0xfa, 0x81, 0x61, 0xd3, 0xdf, 0x91, 0x2b, 0xcb, 0x38, 0xf5, 0x9d, 0xe4, 0xcb, 0x1d, 0xa4, 0x09,
0xc2, 0x91, 0x51, 0x5e, 0x19, 0x38, 0xda, 0x1d, 0x34, 0xdc, 0x2d, 0x22, 0xf8, 0xcf, 0xcf, 0xfc,
0x48, 0xb9, 0x90, 0xc8, 0x9c, 0x5d, 0x5f, 0x29, 0xc0, 0x48, 0xc8, 0x64, 0xf8, 0x09, 0xaa, 0x48,
0x2d, 0xdc, 0x3d, 0xc9, 0x8c, 0x1d, 0x2c, 0xfe, 0x80, 0x87, 0xe1, 0x1a, 0xe6, 0xcc, 0xa7, 0x33,
0x90, 0x31, 0x60, 0xc1, 0x4c, 0x26, 0x2d, 0x85, 0xd4, 0x24, 0x1b, 0xb2, 0x2f, 0x41, 0x21, 0xc2,
0x03, 0xee, 0x53, 0x8d, 0x7f, 0xe4, 0x5c, 0xdf, 0xf7, 0x57, 0xb9, 0xbe, 0xb7, 0xdd, 0x6e, 0xbb,
0x9b, 0xf3, 0x7d, 0x6c, 0xb3, 0xa5, 0x3c, 0x39, 0xdf, 0x66, 0x52, 0x9a, 0x3a, 0xb7, 0x57, 0xb8,
0xac, 0x7f, 0x9c, 0xe5, 0x88, 0xb1, 0xf7, 0xba, 0xaf, 0x6d, 0x2a, 0xfc, 0x4d, 0x61, 0xd6, 0x6d,
0x75, 0x96, 0x4a, 0xf5, 0xa7, 0xa2, 0x41, 0x4e, 0x85, 0x0c, 0x23, 0x25, 0x7d, 0xff, 0xff, 0x22,
0xc3, 0x44, 0xd9, 0xb8, 0x7d, 0x90, 0x6a, 0x27, 0x8f, 0x25, 0x85, 0x84, 0xb9, 0x2c, 0xe2, 0x95,
0x8d, 0xbd, 0x7a, 0x68, 0x49, 0x55, 0xfb, 0x1e, 0xd0, 0xba, 0x9b, 0x94, 0x51, 0x63, 0x6d, 0x12,
0xfb, 0xa8, 0x0c, 0x20, 0x8b, 0xb2, 0xf5, 0x22, 0xd3, 0x13, 0xd0, 0x53, 0x7c, 0x55, 0xd1, 0xc0,
0x59, 0xae, 0x1c, 0xa0, 0x51, 0x69, 0xeb, 0x9b, 0x7e, 0x60, 0xe2, 0x19, 0x9b, 0xc2, 0x3e, 0xfb,
0x47, 0x46, 0x4e, 0xed, 0xe5, 0x94, 0xf0, 0x50, 0x4c, 0xa9, 0xe6, 0xa7, 0x8c, 0x58, 0xcc, 0x95,
0x53, 0x7d, 0x42, 0x8b, 0xb1, 0xd5, 0x28, 0xce, 0xc4, 0xe1, 0x02, 0x36, 0x82, 0x30, 0x2c, 0xd4,
0xbd, 0x8a, 0x24, 0x95, 0xa5, 0x53, 0xf7, 0xe5, 0xd4, 0x85, 0x36, 0x57, 0xf1, 0x88, 0xc9, 0xee,
0x6d, 0x1c, 0x08, 0x06, 0x62, 0xb7, 0x93, 0x69, 0x50, 0xa4, 0xa5, 0xdc, 0x24, 0xe1, 0x68, 0x98,
0x6c, 0x77, 0xf4, 0xae, 0x61, 0x2a, 0xd8, 0xa3, 0x51, 0xec, 0x8b, 0x3e, 0xdb, 0xc4, 0x12, 0x71,
0x6c, 0x40, 0x5a, 0x94, 0x2f, 0x59, 0x69, 0x96, 0x89, 0xf5, 0xf7, 0xfa, 0x98, 0x1f, 0x54, 0x34,
0xd0, 0x71, 0x9c, 0xcd, 0xad, 0xf0, 0x2c, 0x70, 0x98, 0x82, 0xb5, 0x27, 0xfd, 0xa4, 0x73, 0xdc,
0xeb, 0x76, 0xd5, 0x3a, 0xf0, 0xc9, 0xad, 0x9b, 0x5f, 0x47, 0xab, 0x38, 0x0e, 0x78, 0x33, 0xdd,
0x46, 0xf4, 0x20, 0xec, 0x53, 0xec, 0x1f, 0x9f, 0xac, 0xcd, 0x4e, 0xc8, 0x91, 0xa8, 0xf6, 0xf7,
0xa8, 0xa8, 0xc7, 0xc3, 0xaf, 0x1a, 0x4e, 0x20, 0x5d, 0x42, 0xc1, 0x67, 0xfd, 0xf8, 0x44, 0x47,
0xe7, 0xaf, 0xa2, 0x31, 0x45, 0xb3, 0xa3, 0xa9, 0x40, 0xb2, 0x6e, 0x9a, 0xf1, 0x09, 0x4d, 0x2a,
0x2e, 0xd8, 0x3c, 0xb1, 0x19, 0xbe, 0x97, 0x55, 0xfe, 0x54, 0x49, 0x4a, 0x87, 0xb7, 0x70, 0x78,
0xab, 0x64, 0xf8, 0xcd, 0x2a, 0x9a, 0x4f, 0x38, 0x4b, 0xf6, 0x23, 0x68, 0x23, 0x82, 0x76, 0x05,
0x02, 0xe2, 0xca, 0x83, 0xdf, 0xfd, 0x38, 0x3a, 0x88, 0xa3, 0x53, 0x82, 0x63, 0xcc, 0xdb, 0xcc,
0xf6, 0x0f, 0xee, 0xe2, 0xe0, 0x6e, 0x19, 0x01, 0x17, 0xb7, 0x24, 0x62, 0x7e, 0x14, 0x84, 0xfb,
0x11, 0xbc, 0x45, 0x04, 0x6f, 0x4b, 0x10, 0xdc, 0x05, 0xab, 0x97, 0x26, 0xff, 0x09, 0xc7, 0xfe,
0x54, 0x32, 0xf6, 0xd4, 0xb7, 0xbc, 0x60, 0xb6, 0x7f, 0xf0, 0x31, 0x0e, 0x3e, 0xae, 0x1c, 0x5c,
0xc1, 0x3c, 0x9a, 0x9a, 0x3a, 0x2a, 0x90, 0xf2, 0xb0, 0x55, 0x3a, 0x02, 0x88, 0x55, 0x60, 0xbd,
0x3d, 0xb2, 0x0c, 0x5c, 0x1f, 0xa2, 0x9a, 0x3e, 0x97, 0x51, 0xde, 0xd7, 0x41, 0xf1, 0x02, 0xc5,
0x1b, 0x94, 0xdb, 0x37, 0x6a, 0xe2, 0xc3, 0x0e, 0x7f, 0xf8, 0xde, 0xfa, 0xc9, 0xe8, 0xf6, 0x93,
0x70, 0x1b, 0x4c, 0xa6, 0x3c, 0x97, 0xd8, 0x56, 0x26, 0xd3, 0xcd, 0xb5, 0x87, 0xce, 0xbc, 0xb1,
0x8b, 0x26, 0x40, 0x29, 0x5c, 0x5c, 0x61, 0xea, 0xf3, 0xb3, 0x52, 0xbc, 0xba, 0xb2, 0xdd, 0x9f,
0x96, 0x5e, 0x65, 0x78, 0x42, 0xc3, 0x24, 0x0c, 0xe5, 0x81, 0x81, 0x71, 0x45, 0x1f, 0xdc, 0xd9,
0xfe, 0xda, 0x68, 0x62, 0x27, 0x7d, 0x3c, 0x44, 0xdf, 0x3d, 0xa3, 0xe2, 0x06, 0x52, 0xfd, 0x13,
0x85, 0x61, 0xbf, 0x58, 0xdf, 0x3d, 0x28, 0x39, 0xf7, 0xf2, 0x13, 0x7c, 0x68, 0x96, 0xb1, 0xaf,
0x31, 0x9f, 0xff, 0xfa, 0x5f, 0xb0, 0xae, 0x2b, 0x0f, 0xae, 0x22, 0x9d, 0x02, 0x90, 0xbe, 0x8b,
0x04, 0x0f, 0xa2, 0xaa, 0x71, 0xe8, 0x1c, 0x87, 0xe0, 0x78, 0xe4, 0xe6, 0x1a, 0x1f, 0x99, 0x96,
0x30, 0x39, 0x63, 0xde, 0x6a, 0x89, 0x37, 0x34, 0x3e, 0xb8, 0x1e, 0x5e, 0x78, 0x91, 0x2d, 0x6d,
0x3e, 0x7b, 0x24, 0xff, 0xb8, 0xba, 0xfc, 0x39, 0x8e, 0x97, 0xb7, 0x10, 0x2b, 0xb0, 0x28, 0xee,
0xfb, 0xd5, 0x97, 0x4a, 0x72, 0x57, 0x1d, 0xb2, 0x8b, 0x18, 0xf1, 0xdc, 0xc5, 0x56, 0xa4, 0x68,
0x19, 0x80, 0x47, 0xbc, 0x63, 0xdf, 0x63, 0x8d, 0x3f, 0x01, 0x32, 0xe3, 0x55, 0x84, 0x3d, 0x17,
0xb0, 0x48, 0x15, 0x3c, 0x55, 0xf5, 0x95, 0x92, 0x0c, 0x2f, 0xcb, 0x23, 0xc6, 0xf6, 0x5f, 0xcb,
0xbe, 0xd7, 0x0e, 0x12, 0x04, 0xe2, 0x22, 0xd1, 0xcd, 0x35, 0xec, 0xa6, 0x46, 0x9b, 0x62, 0x39,
0xf2, 0xd0, 0x23, 0xe6, 0x2b, 0xf9, 0x10, 0x84, 0x0b, 0x6c, 0x23, 0x4b, 0xdb, 0x10, 0xe5, 0x85,
0x19, 0x85, 0x62, 0xf3, 0xb1, 0xec, 0x86, 0xe5, 0x7d, 0xc8, 0x78, 0x47, 0x25, 0x02, 0xf6, 0xe1,
0x35, 0x15, 0xbf, 0x11, 0x21, 0x4c, 0xac, 0x6a, 0x25, 0x7d, 0xca, 0x07, 0x5b, 0xd7, 0x81, 0xce,
0xa6, 0xb3, 0x94, 0x7b, 0x5a, 0xdc, 0xa7, 0xc9, 0x4b, 0x0a, 0x5a, 0x08, 0x66, 0x1e, 0xbc, 0xa4,
0xbc, 0xf5, 0x84, 0x7c, 0xbe, 0x65, 0x16, 0x04, 0x50, 0x27, 0xb0, 0x12, 0x3e, 0xdf, 0x09, 0x4b,
0xe7, 0x3d, 0x51, 0xd0, 0x73, 0xa7, 0x54, 0x28, 0x92, 0xfe, 0x74, 0x0c, 0xb6, 0x53, 0xe1, 0x74,
0x66, 0x9e, 0x35, 0xe8, 0x88, 0x71, 0x18, 0x08, 0x00, 0x08, 0x25, 0xf2, 0x7c, 0xe5, 0xc5, 0x72,
0xf9, 0xbc, 0xb1, 0x9e, 0x0b, 0x8f, 0xe2, 0xf3, 0x1a, 0x7e, 0xdc, 0x98, 0x3f, 0xf2, 0x53, 0x12,
0xfc, 0x00, 0xb2, 0xef, 0x64, 0x3a, 0x23, 0xba, 0x4a, 0x0c, 0x9d, 0xf7, 0x93, 0x24, 0xe7, 0x0c,
0x20, 0xcd, 0xfd, 0x04, 0x14, 0x83, 0x9b, 0x06, 0x40, 0x9f, 0x5b, 0xf6, 0x5c, 0x91, 0x9e, 0xd2,
0x1c, 0x3e, 0x25, 0xa0, 0x86, 0x88, 0x0b, 0x32, 0x54, 0xac, 0xb1, 0x74, 0xfd, 0x7c, 0x93, 0x4a,
0x99, 0xd6, 0x7c, 0xe5, 0x29, 0x27, 0xfa, 0xb3, 0xaf, 0xb9, 0xee, 0x29, 0x3e, 0xf4, 0xb3, 0xfb,
0xa5, 0x5f, 0x79, 0x90, 0xe2, 0x17, 0xa0, 0x91, 0xc9, 0x5a, 0xe5, 0x01, 0x4f, 0x11, 0x96, 0x6b,
0x8a, 0xf6, 0x9a, 0xc6, 0x55, 0x11, 0x45, 0x95, 0x83, 0x9e, 0x5d, 0x6f, 0x83, 0x06, 0x18, 0x16,
0x6b, 0xaf, 0xe9, 0x6b, 0x45, 0x22, 0x20, 0x2b, 0x2f, 0x87, 0xbd, 0xfd, 0x90, 0xc0, 0xa6, 0x5a,
0x0b, 0x7b, 0x3a, 0xad, 0xa0, 0xe2, 0xb7, 0x32, 0xe0, 0x87, 0x8d, 0xba, 0x49, 0xb6, 0x18, 0x82,
0x21, 0x30, 0x11, 0x69, 0x48, 0x87, 0xb7, 0x98, 0xc4, 0xd3, 0x74, 0x27, 0x99, 0xd8, 0x43, 0x1e,
0x7f, 0x49, 0xe6, 0x88, 0x75, 0xcb, 0x25, 0x71, 0x35, 0xe3, 0xa3, 0xc0, 0x7a, 0x27, 0x49, 0x56,
0xf2, 0xbd, 0x7f, 0x1a, 0x86, 0xd6, 0xba, 0xe1, 0x46, 0xfc, 0xaf, 0xc2, 0x13, 0x51, 0x35, 0xe9,
0x33, 0xdc, 0xb1, 0xf6, 0x14, 0x7b, 0xe8, 0xab, 0xc5, 0x08, 0x03, 0x30, 0x9c, 0x16, 0xf7, 0x1e,
0x95, 0x90, 0x6f, 0x2b, 0x5e, 0x8a, 0x2a, 0x5d, 0xfb, 0xdd, 0x1d, 0xcd, 0xb1, 0xd4, 0x6a, 0xc4,
0xf1, 0x86, 0x53, 0xe5, 0x86, 0x55, 0x3d, 0x7a, 0x17, 0xb7, 0xf9, 0x11, 0x12, 0x18, 0x67, 0x2b,
0x9f, 0xe0, 0xe2, 0xae, 0x0c, 0x9c, 0xd3, 0x24, 0xf8, 0x11, 0x32, 0x08, 0x2b, 0xab, 0x26, 0xbb,
0xbd, 0xdc, 0x19, 0xcd, 0xe1, 0xab, 0xe7, 0xbb, 0xbd, 0xa2, 0x85, 0xad, 0xcc, 0x8d, 0x01, 0x97,
0x9d, 0x64, 0x06, 0x1a, 0xaa, 0xb8, 0xe5, 0x9c, 0x46, 0x68, 0x54, 0x41, 0xab, 0xd5, 0x9e, 0xbc,
0x50, 0x77, 0xe3, 0x31, 0x6c, 0x30, 0x97, 0x71, 0xa0, 0x45, 0x50, 0xf7, 0xf9, 0xad, 0x3b, 0x51,
0xfd, 0x39, 0xa0, 0x29, 0xe4, 0x1d, 0x58, 0x62, 0x32, 0x09, 0x83, 0x47, 0xc8, 0x55, 0x88, 0x13,
0xb0, 0x08, 0xef, 0x02, 0xe1, 0xf9, 0x71, 0x10, 0x42, 0x58, 0x3a, 0x67, 0xe4, 0x2b, 0x37, 0x41,
0x5f, 0xc9, 0x32, 0x04, 0xe3, 0x0a, 0x1e, 0x05, 0xc3, 0x7c, 0x8e, 0x89, 0x47, 0xae, 0x11, 0x5e,
0x85, 0x60, 0x59, 0x67, 0x69, 0x86, 0x96, 0x09, 0xa8, 0xd3, 0x9b, 0x0b, 0xe2, 0xe6, 0x91, 0xf2,
0x4a, 0x29, 0x89, 0xf3, 0xd3, 0xae, 0xc1, 0x54, 0xe5, 0xef, 0x7a, 0x8e, 0xc1, 0x7b, 0x50, 0x1c,
0xdd, 0x03, 0x9b, 0x29, 0x8d, 0xa5, 0x17, 0xd8, 0xfc, 0x82, 0x47, 0x03, 0xe8, 0x88, 0x03, 0x3b,
0xc0, 0xe6, 0x4b, 0x7e, 0x49, 0x55, 0xd7, 0x14, 0x7e, 0xd5, 0xd5, 0x44, 0x08, 0x6f, 0x1c, 0x07,
0xa1, 0x35, 0x63, 0xc8, 0xd2, 0x8b, 0x98, 0x2d, 0xd0, 0x2f, 0xd9, 0x17, 0x4b, 0xc8, 0x39, 0x20,
0x70, 0x10, 0x60, 0x30, 0x7e, 0xb1, 0x04, 0x0a, 0xd1, 0x92, 0x92, 0x2b, 0x88, 0x82, 0x1b, 0x44,
0x72, 0x8b, 0x61, 0x38, 0x43, 0x3e, 0x61, 0x9f, 0xc1, 0xc5, 0x0d, 0xb0, 0x48, 0x2b, 0x60, 0x8c,
0x8a, 0x18, 0x35, 0x8e, 0x4d, 0x55, 0x11, 0x8a, 0x5f, 0x01, 0x45, 0xf4, 0x27, 0xfc, 0x5a, 0x6c,
0xaf, 0xd9, 0xa4, 0x75, 0xfe, 0x1a, 0x9b, 0x0e, 0xea, 0xd9, 0xbd, 0xd6, 0x66, 0xd4, 0xf8, 0x16,
0x9d, 0x2c, 0xcd, 0x16, 0x3a, 0x0d, 0x75, 0x53, 0x83, 0x98, 0x48, 0x5c, 0x18, 0x1e, 0xf0, 0xd0,
0x6a, 0xf8, 0x6f, 0xee, 0x82, 0xb3, 0x7d, 0x15, 0x7a, 0xe0, 0xac, 0x45, 0x67, 0x45, 0x84, 0x87,
0xf6, 0x00, 0xc8, 0x01, 0x06, 0x4d, 0x71, 0x53, 0x1a, 0x6f, 0x7a, 0x12, 0x69, 0xfe, 0xe9, 0x98,
0x97, 0xde, 0x40, 0x89, 0x16, 0x35, 0x9e, 0x7e, 0xe3, 0xa7, 0x3f, 0xa2, 0xb4, 0x8c, 0x37, 0x85,
0xe4, 0x9f, 0xc5, 0xf3, 0x00, 0x6b, 0x9f, 0x41, 0x84, 0x17, 0x98, 0x73, 0x25, 0x91, 0x38, 0x00,
0x76, 0x3c, 0x16, 0x9f, 0xcd, 0x99, 0xb7, 0x1c, 0xd1, 0x61, 0x6d, 0x20, 0x42, 0x73, 0x99, 0x9b,
0x88, 0x2f, 0xb9, 0x58, 0xef, 0x67, 0x9c, 0xf6, 0x64, 0xd0, 0x14, 0x2f, 0xd2, 0x62, 0x77, 0xd9,
0x98, 0x5a, 0x3a, 0x68, 0x84, 0x83, 0x46, 0xe0, 0xb2, 0xb3, 0x71, 0x85, 0x11, 0xf2, 0xfa, 0xc1,
0x70, 0x6c, 0x3d, 0xb0, 0x0c, 0x64, 0x9e, 0xa4, 0xd9, 0x83, 0x79, 0x6b, 0x58, 0xc3, 0xfd, 0x39,
0xb4, 0x16, 0xcb, 0x3e, 0xf9, 0xd9, 0x0a, 0xb1, 0x15, 0x05, 0xe5, 0x3c, 0x5e, 0x2d, 0x81, 0x39,
0x2d, 0x88, 0xa7, 0x63, 0xcb, 0x4b, 0x8a, 0x9b, 0x69, 0xb1, 0xd5, 0xb3, 0x39, 0xa9, 0xb2, 0xc4,
0x9e, 0xd5, 0x82, 0x6d, 0x5c, 0x66, 0x16, 0x98, 0x0e, 0xdc, 0xe1, 0x2d, 0x03, 0x73, 0x08, 0x9a,
0xe8, 0x80, 0x98, 0x2e, 0x83, 0x47, 0x90, 0x07, 0xd9, 0x4b, 0x81, 0xcd, 0x10, 0x13, 0x51, 0xc8,
0x8b, 0x62, 0x51, 0x30, 0xec, 0x0d, 0x9a, 0xae, 0x18, 0x37, 0x91, 0x85, 0xdd, 0x9a, 0x38, 0x4a,
0x59, 0x65, 0xb3, 0x61, 0xf3, 0x49, 0xb1, 0xf0, 0xcb, 0xdb, 0x1e, 0x64, 0xe9, 0x20, 0x9d, 0xb9,
0x76, 0xee, 0x63, 0x22, 0x45, 0xac, 0x15, 0x04, 0xbb, 0x20, 0xe7, 0xb6, 0x9c, 0xcb, 0x67, 0x51,
0x44, 0x3c, 0xbc, 0xf6, 0xc9, 0xc2, 0x17, 0x2a, 0xc3, 0xa7, 0x23, 0x26, 0x59, 0x2d, 0xf3, 0x45,
0x79, 0xad, 0x45, 0x54, 0x86, 0xf8, 0xad, 0x17, 0x31, 0x6b, 0x52, 0x28, 0xc5, 0xab, 0x44, 0xc3,
0x2b, 0x71, 0x01, 0x9e, 0x9c, 0xad, 0xc2, 0x10, 0xe4, 0x3f, 0x9d, 0x43, 0x5e, 0x7b, 0xbf, 0x3a,
0xa5, 0x5b, 0xb9, 0xe9, 0x56, 0x69, 0xa9, 0xd5, 0xcd, 0x4a, 0x5c, 0xba, 0xbe, 0x53, 0x12, 0x4e,
0xcb, 0x4b, 0xc3, 0x1a, 0x59, 0x9c, 0x16, 0xa7, 0xcf, 0xae, 0x47, 0xa4, 0x99, 0x05, 0x96, 0x94,
0x7a, 0xa2, 0x3d, 0xa8, 0x5f, 0x3c, 0x5c, 0xab, 0x1d, 0xfe, 0xf0, 0xee, 0xf8, 0xf8, 0xb8, 0x4f,
0xfe, 0x3d, 0x58, 0x85, 0xc5, 0x9d, 0x01, 0x09, 0x7e, 0xc0, 0x02, 0x00, 0x99, 0x03, 0xc7, 0x88,
0x2d, 0x16, 0xd2, 0xe0, 0x5c, 0xbd, 0x0b, 0x08, 0xa8, 0x14, 0xbc, 0x67, 0xdc, 0x94, 0x45, 0xd6,
0x94, 0x09, 0x03, 0xb6, 0x46, 0x2c, 0x5c, 0x6a, 0x34, 0x04, 0x5c, 0x0a, 0x03, 0xb0, 0x8a, 0x10,
0x0e, 0x04, 0x95, 0xd8, 0xc8, 0xaf, 0x88, 0xbf, 0xab, 0x2d, 0x20, 0x84, 0x72, 0x01, 0x42, 0xce,
0xea, 0xfa, 0xdf, 0x98, 0xbc, 0x4f, 0x8b, 0x09, 0x50, 0x44, 0x2c, 0xdf, 0x01, 0x0b, 0x3b, 0x85,
0xc1, 0x07, 0x59, 0x41, 0x08, 0x44, 0xa9, 0x76, 0x9a, 0x6c, 0xa6, 0xe5, 0x01, 0x99, 0x7c, 0x17,
0xa3, 0xfc, 0xbe, 0xc6, 0x01, 0x16, 0x0b, 0xd7, 0xc0, 0xd2, 0x20, 0xe2, 0x37, 0xd1, 0x90, 0x46,
0x0e, 0x26, 0xa8, 0xff, 0x3b, 0x63, 0x4b, 0x62, 0xc5, 0xe4, 0x10, 0x42, 0x38, 0xe3, 0x94, 0xb8,
0x53, 0x41, 0x01, 0x76, 0x38, 0xf1, 0x1e, 0x26, 0x07, 0x18, 0x6b, 0xc7, 0x28, 0x9b, 0x58, 0xb0,
0xc6, 0xc1, 0x59, 0x13, 0x11, 0x27, 0xa5, 0x76, 0xc1, 0x57, 0xca, 0xef, 0x4d, 0xa6, 0x17, 0xd8,
0xc0, 0x53, 0xb0, 0x10, 0x92, 0xbf, 0x02, 0x13, 0x35, 0x69, 0xfc, 0x90, 0x42, 0xbc, 0x7a, 0xed,
0xcf, 0x04, 0x09, 0x8a, 0x94, 0x0b, 0x02, 0x42, 0x8f, 0x17, 0x9d, 0x41, 0x2b, 0x56, 0x11, 0x58,
0xc3, 0x44, 0xb9, 0xa4, 0x34, 0x2c, 0xd1, 0x86, 0xac, 0xfc, 0x7b, 0x3f, 0x78, 0xf4, 0xa5, 0x54,
0xab, 0x99, 0x72, 0x84, 0x42, 0x67, 0x1f, 0x02, 0x2f, 0xc6, 0x3b, 0xdb, 0xca, 0x15, 0x76, 0x73,
0xc9, 0x7d, 0xe2, 0x7a, 0x65, 0x11, 0x24, 0x0e, 0x38, 0x0c, 0x60, 0x6a, 0x49, 0xd5, 0x9d, 0x77,
0x4e, 0x6d, 0xc9, 0x36, 0xde, 0x48, 0xdb, 0x39, 0x57, 0xc5, 0xd3, 0x89, 0x24, 0xcd, 0x35, 0xb3,
0x84, 0x77, 0x08, 0x3c, 0x91, 0x97, 0xa9, 0x88, 0xd2, 0xed, 0x2e, 0x4e, 0xd5, 0x5a, 0xe5, 0xd1,
0x69, 0x97, 0x43, 0xb3, 0xe9, 0xd4, 0xb5, 0xb1, 0x2f, 0x8f, 0x28, 0x6d, 0x84, 0xdf, 0xd7, 0x59,
0x52, 0xc3, 0x26, 0x2c, 0xa5, 0xad, 0xef, 0x01, 0xc3, 0x63, 0x93, 0xa1, 0x6c, 0xd9, 0x52, 0x8c,
0xd6, 0x1e, 0x48, 0xec, 0x0e, 0xa9, 0x9d, 0xf1, 0x9c, 0xb7, 0xe4, 0xf4, 0xb6, 0x60, 0x48, 0xc4,
0x8d, 0xb0, 0xf2, 0xb3, 0x68, 0x89, 0x42, 0x34, 0xce, 0x25, 0xac, 0xc6, 0x9e, 0x37, 0xe0, 0x70,
0xaa, 0xe3, 0x09, 0x73, 0xb7, 0x55, 0x7c, 0xf7, 0xc4, 0x87, 0xdb, 0x35, 0xcf, 0xaa, 0xd6, 0xee,
0x44, 0xb9, 0x93, 0x33, 0xb5, 0x4c, 0x78, 0x13, 0xbe, 0xbb, 0x39, 0x51, 0xf4, 0xa3, 0x15, 0xfc,
0xb1, 0x26, 0x01, 0x10, 0xc1, 0x35, 0x11, 0xe7, 0x47, 0xb5, 0x44, 0xb1, 0x6e, 0xa4, 0x82, 0x23,
0x4d, 0x7e, 0x7b, 0x58, 0xdb, 0x31, 0xf4, 0xed, 0xcc, 0x8e, 0x60, 0x4b, 0x12, 0xff, 0x35, 0x0e,
0xd1, 0xce, 0x17, 0xf5, 0x92, 0x71, 0xc5, 0xfa, 0x7e, 0xe2, 0x67, 0x6a, 0x45, 0xd7, 0x84, 0x18,
0xea, 0x39, 0xaf, 0x96, 0x26, 0x30, 0xe8, 0xa1, 0xe9, 0xb0, 0x9e, 0x3a, 0x21, 0x52, 0xe1, 0xda,
0x10, 0xc1, 0x51, 0x09, 0x82, 0x23, 0x89, 0xe1, 0x28, 0xe7, 0xe9, 0x42, 0x4e, 0xe7, 0x15, 0xef,
0x61, 0x24, 0xbf, 0xe6, 0xf5, 0x88, 0x2f, 0x04, 0xb6, 0x5e, 0x4f, 0xdc, 0x11, 0x69, 0xe6, 0xdf,
0x18, 0x39, 0xf7, 0x35, 0x2a, 0x58, 0x51, 0xde, 0x5f, 0x4a, 0x6a, 0xa5, 0x35, 0xfa, 0xa3, 0x09,
0x04, 0x21, 0xf7, 0x7d, 0xfe, 0xcb, 0x27, 0x3d, 0x43, 0xd7, 0x97, 0xdf, 0xfb, 0x73, 0x86, 0xd6,
0x07, 0xbe, 0xc0, 0xe7, 0x09, 0x8f, 0xe8, 0x8f, 0xb0, 0x01, 0x75, 0x15, 0xf5, 0x5a, 0xf0, 0x28,
0x39, 0x4d, 0xab, 0x15, 0xa6, 0xc8, 0xf5, 0x7b, 0xfe, 0x49, 0x43, 0x0d, 0x92, 0x04, 0xb3, 0x91,
0x70, 0x05, 0xcb, 0xf0, 0x85, 0xb5, 0x9b, 0xb8, 0x9e, 0x8b, 0x26, 0x38, 0x24, 0x9e, 0x35, 0x83,
0xc0, 0x30, 0x5a, 0xb1, 0x88, 0x9b, 0x9a, 0x5f, 0xc1, 0x04, 0x7a, 0xdc, 0x2a, 0x82, 0x8a, 0x93,
0x9c, 0x3b, 0x4d, 0x1a, 0x44, 0x87, 0x25, 0xbd, 0x9b, 0x09, 0x4f, 0xd0, 0x88, 0xa0, 0xfd, 0x9b,
0xa0, 0x6f, 0x66, 0xdf, 0x01, 0x00, 0x74, 0xd7, 0x2e, 0xd8, 0x63, 0x10, 0x87, 0x5a, 0x5e, 0x1e,
0xae, 0xac, 0x7b, 0x86, 0x86, 0x87, 0xcd, 0x16, 0x89, 0x19, 0x62, 0x90, 0x84, 0x48, 0xc4, 0x2f,
0xf8, 0xda, 0xab, 0x31, 0x15, 0x4c, 0x92, 0x6a, 0x36, 0x59, 0x45, 0xe2, 0xdc, 0x07, 0xd6, 0xe9,
0xb8, 0x36, 0x8b, 0x2a, 0xc7, 0xe7, 0x6c, 0x98, 0x28, 0xbf, 0xf0, 0x4a, 0x88, 0x8c, 0xf2, 0xa5,
0xaf, 0x8e, 0x5c, 0xe1, 0xa9, 0x91, 0x25, 0x33, 0x2f, 0x98, 0x88, 0x80, 0x06, 0x26, 0x99, 0x4e,
0x73, 0x51, 0x40, 0xad, 0x9c, 0xb4, 0xcb, 0xf7, 0x34, 0x89, 0x65, 0x6a, 0x18, 0xca, 0x5e, 0x5d,
0xf5, 0x48, 0x3e, 0xa8, 0xc1, 0x85, 0x62, 0x7f, 0xac, 0x67, 0x2d, 0x97, 0xe8, 0x11, 0x24, 0x03,
0x22, 0xa2, 0xe8, 0x0d, 0xa3, 0x2d, 0x36, 0x38, 0xb3, 0xdd, 0xdb, 0x5c, 0xcb, 0xb5, 0x0a, 0x81,
0x04, 0xfc, 0xc1, 0x25, 0xe8, 0x8f, 0x85, 0x40, 0x55, 0x38, 0x12, 0x22, 0x49, 0x5d, 0xbe, 0xc7,
0x87, 0xd4, 0xc4, 0x98, 0xec, 0x74, 0x64, 0xb8, 0x5f, 0x4b, 0x77, 0x95, 0x34, 0x39, 0x06, 0xc8,
0x05, 0x93, 0x32, 0x51, 0x7d, 0x8d, 0x9a, 0x26, 0x18, 0xf0, 0x28, 0x20, 0x87, 0x21, 0x39, 0x50,
0xd9, 0x56, 0xd3, 0x0a, 0xe2, 0x92, 0xc5, 0xf3, 0x5c, 0x36, 0xd1, 0x15, 0x59, 0x03, 0x27, 0xbc,
0x18, 0xca, 0xfd, 0xea, 0xca, 0xf3, 0x8e, 0x56, 0xcb, 0x26, 0x64, 0x2d, 0xfe, 0x0b, 0x72, 0x74,
0x71, 0x23, 0x36, 0xab, 0xc6, 0xcb, 0xc0, 0x20, 0xc2, 0x78, 0x08, 0x1e, 0x78, 0x4e, 0xc5, 0xb9,
0x40, 0xd6, 0x88, 0x50, 0x30, 0xd1, 0x06, 0xc6, 0x5d, 0x02, 0x21, 0xe4, 0xc1, 0xa4, 0x96, 0x5a,
0xe5, 0x82, 0x1a, 0xa7, 0xbf, 0x82, 0x33, 0x1c, 0xb0, 0x45, 0x51, 0x91, 0x7f, 0x98, 0x4e, 0x8f,
0x6d, 0xfc, 0x05, 0xa5, 0x1a, 0xcf, 0x06, 0x21, 0x45, 0x5c, 0x70, 0x6b, 0x3b, 0x59, 0xb9, 0x9e,
0xc3, 0x93, 0x42, 0xe2, 0x07, 0x28, 0xdb, 0xb6, 0xb7, 0x72, 0x18, 0xb9, 0xb8, 0x05, 0x89, 0x5a,
0x04, 0x31, 0x4b, 0x52, 0xba, 0x86, 0xe0, 0x19, 0x5b, 0x48, 0x9e, 0x00, 0x80, 0x38, 0xdd, 0xa8,
0x95, 0x2e, 0x83, 0x13, 0x7f, 0x94, 0x1c, 0x4a, 0x76, 0x8e, 0x53, 0x6e, 0xdc, 0xee, 0x3b, 0xee,
0x00, 0x85, 0x2b, 0x04, 0x05, 0x90, 0x91, 0x6f, 0x43, 0x97, 0xb4, 0x59, 0x49, 0x42, 0x9d, 0xed,
0x83, 0x8a, 0xda, 0xee, 0x61, 0x63, 0xab, 0x73, 0x74, 0xcf, 0xd6, 0xfb, 0x5a, 0x10, 0x5b, 0x29,
0x10, 0x6f, 0xd1, 0xce, 0x35, 0x18, 0xd6, 0x76, 0xcf, 0x1e, 0x3b, 0x3a, 0x87, 0x9c, 0xc0, 0xf7,
0xca, 0x76, 0x45, 0x80, 0xda, 0x9d, 0xb4, 0xb6, 0x7b, 0x0e, 0xd9, 0x32, 0x5e, 0x22, 0xed, 0x2d,
0x1d, 0xbe, 0x95, 0xf3, 0xf1, 0xec, 0xaa, 0x02, 0xd7, 0x4f, 0x74, 0xf8, 0x8e, 0x83, 0x85, 0x39,
0x5e, 0xec, 0x1c, 0x19, 0x0c, 0x79, 0xb9, 0x20, 0xe4, 0xac, 0xcb, 0xa1, 0x4a, 0xc3, 0x90, 0x92,
0xd3, 0x00, 0x79, 0x18, 0x90, 0x39, 0xc2, 0x37, 0x78, 0x16, 0xc0, 0xab, 0x2c, 0x6f, 0xca, 0x4f,
0x02, 0xb8, 0xfd, 0x3c, 0xe5, 0x11, 0x3c, 0xc8, 0x8b, 0xd8, 0x47, 0x0c, 0x82, 0x17, 0x96, 0xeb,
0xa7, 0x66, 0x19, 0x7f, 0xe7, 0xe3, 0x45, 0x5b, 0x7c, 0x2d, 0x95, 0x28, 0x15, 0x75, 0xde, 0x3c,
0x5e, 0x1e, 0x18, 0xa5, 0x85, 0x90, 0x2d, 0xac, 0xfc, 0x17, 0x89, 0x24, 0x46, 0x5e, 0x09, 0x26,
0x35, 0xcb, 0xb6, 0xd9, 0x12, 0x42, 0x9d, 0x06, 0x47, 0x57, 0x61, 0x9a, 0x72, 0xf6, 0x21, 0xb3,
0x2b, 0x6f, 0x72, 0x75, 0x74, 0xda, 0x74, 0x43, 0x81, 0x01, 0x18, 0xf1, 0x2b, 0x7f, 0x5e, 0x66,
0x6a, 0x2c, 0x52, 0x03, 0xe5, 0x9f, 0x9a, 0x55, 0xbf, 0xab, 0xc5, 0xb9, 0x3b, 0xb5, 0xc0, 0xb5,
0xc0, 0xc7, 0x69, 0x08, 0xda, 0xe9, 0x34, 0x21, 0x6e, 0xe3, 0x65, 0x5e, 0x93, 0xfe, 0x01, 0xbb,
0xee, 0xdf, 0x53, 0x54, 0x3c, 0x78, 0x1b, 0x0c, 0x9a, 0x96, 0x60, 0xef, 0x2d, 0x16, 0x8c, 0xf6,
0x9d, 0x34, 0x56, 0xa9, 0xe2, 0xed, 0x65, 0xc1, 0x55, 0xed, 0xe8, 0x22, 0x11, 0xb7, 0x2d, 0xf7,
0xef, 0xcc, 0xed, 0x15, 0x4d, 0xf2, 0xe2, 0x57, 0x09, 0x0b, 0x56, 0xc9, 0xde, 0x54, 0x1f, 0x1b,
0xed, 0x3a, 0x23, 0x08, 0x03, 0xe5, 0x6f, 0x83, 0x44, 0x3c, 0x26, 0xbc, 0xc3, 0x8a, 0x3e, 0x0f,
0x11, 0xf0, 0x10, 0x77, 0x8a, 0x09, 0x8d, 0x48, 0x72, 0xc0, 0x1a, 0xf3, 0xaa, 0xe7, 0x4b, 0xce,
0x73, 0x24, 0x45, 0x49, 0x62, 0xcd, 0x25, 0x6b, 0x5b, 0x41, 0xf3, 0x19, 0x04, 0xcd, 0xb5, 0x52,
0xe3, 0xbc, 0x28, 0x8b, 0x9f, 0xb3, 0x38, 0x59, 0xd1, 0x8f, 0xe0, 0x89, 0x9a, 0x24, 0x46, 0xa7,
0x32, 0x83, 0x45, 0xe2, 0x52, 0x6b, 0x29, 0x69, 0xb9, 0xa9, 0x48, 0xbd, 0x77, 0x67, 0xd0, 0x0b,
0x79, 0x36, 0x04, 0xdd, 0x93, 0x00, 0xcc, 0xb5, 0xa2, 0x63, 0x42, 0x1b, 0x25, 0x11, 0x78, 0x94,
0x4e, 0x8a, 0x71, 0xc5, 0x47, 0x6b, 0xb1, 0xb0, 0x88, 0x1d, 0x84, 0xa1, 0x4c, 0x66, 0x31, 0x2e,
0x10, 0xde, 0xe0, 0x05, 0x1e, 0x7d, 0x84, 0x70, 0x9b, 0x28, 0x51, 0x1c, 0x06, 0x90, 0xb2, 0xa1,
0x21, 0x49, 0x63, 0x0b, 0x3e, 0x41, 0xad, 0x12, 0x7b, 0x09, 0x33, 0x2b, 0x66, 0xc0, 0xea, 0x13,
0x51, 0xd0, 0xe5, 0x6c, 0x63, 0xc7, 0x7f, 0xa3, 0x2c, 0x83, 0x06, 0x85, 0x88, 0x73, 0x14, 0x4b,
0xc6, 0x7d, 0xd8, 0x66, 0x5c, 0x6d, 0x8b, 0x73, 0x46, 0xf9, 0xde, 0xfc, 0x05, 0x05, 0xea, 0x0e,
0x82, 0xda, 0xc8, 0x45, 0xa2, 0x85, 0x4c, 0x9d, 0x85, 0x41, 0x14, 0x4d, 0x2d, 0x87, 0xbd, 0xc4,
0x97, 0xbb, 0x0f, 0x42, 0x76, 0x32, 0x04, 0x04, 0x7f, 0x00, 0x6c, 0x8b, 0xb8, 0xbb, 0xf7, 0x55,
0xc4, 0x7d, 0xf7, 0x76, 0x7b, 0x86, 0xd0, 0x27, 0x93, 0x45, 0x84, 0x68, 0x65, 0x81, 0xe8, 0xc6,
0xf2, 0x58, 0x0c, 0x0e, 0x2d, 0xce, 0xc8, 0x7c, 0x89, 0xb0, 0x9b, 0x0f, 0x42, 0x55, 0x90, 0x1a,
0x87, 0x78, 0xc8, 0x3c, 0xbe, 0xb2, 0x44, 0xc8, 0xdf, 0xcb, 0x1f, 0x5b, 0xdb, 0xae, 0xfd, 0xdc,
0x5d, 0xbe, 0x20, 0x80, 0x15, 0x6c, 0x84, 0x77, 0x5c, 0x10, 0x12, 0xfc, 0x77, 0xdc, 0x48, 0x55,
0xeb, 0xd2, 0xdd, 0xe8, 0x65, 0x41, 0xaf, 0x95, 0x4c, 0x84, 0x93, 0x60, 0xfd, 0x76, 0xbb, 0xe7,
0xfa, 0xee, 0x53, 0x59, 0x20, 0xf0, 0xc9, 0x72, 0x63, 0x5e, 0xaa, 0x01, 0x4d, 0xab, 0xed, 0x69,
0xbc, 0xfe, 0x00, 0x5b, 0xbd, 0xc7, 0xff, 0xe3, 0x6b, 0xc2, 0xe3, 0xdc, 0x7d, 0xbe, 0x7f, 0xbc,
0xf2, 0x43, 0x37, 0x62, 0x25, 0x19, 0x3c, 0xf0, 0x9d, 0xdf, 0x95, 0xc0, 0x5f, 0x22, 0x82, 0xfc,
0x0f, 0x9d, 0x1c, 0xdf, 0x8c, 0x9a, 0x78, 0x3a, 0xb2, 0xc0, 0x90, 0xdb, 0x2c, 0xa7, 0x3a, 0x2f,
0xf5, 0x83, 0x9e, 0xdd, 0xe5, 0x3b, 0x4b, 0x13, 0x61, 0x7a, 0xb4, 0xe9, 0xf0, 0xa3, 0x48, 0x1d,
0x02, 0x19, 0x88, 0x73, 0x1d, 0x2c, 0xeb, 0x7b, 0x2c, 0x6d, 0x73, 0xa4, 0x3b, 0xcb, 0xe2, 0x35,
0x8c, 0x9d, 0x86, 0x8f, 0x57, 0x36, 0xb6, 0xd7, 0x32, 0x06, 0xbf, 0xd0, 0x0d, 0x89, 0x4c, 0x7e,
0xa1, 0x1f, 0x12, 0x39, 0x5c, 0x2b, 0x6f, 0x89, 0xe4, 0x39, 0x59, 0xba, 0x3c, 0x60, 0x4e, 0xd6,
0xcc, 0x59, 0x99, 0x91, 0x49, 0x46, 0xde, 0x0a, 0x3e, 0xe2, 0x18, 0x48, 0x2c, 0x40, 0xb5, 0x1e,
0x20, 0x00, 0xf6, 0xc0, 0xf4, 0x40, 0x6a, 0xf3, 0xea, 0x78, 0xbc, 0xb6, 0x1d, 0x90, 0x9f, 0x8d,
0x8a, 0x16, 0x46, 0xba, 0x33, 0xd8, 0xf1, 0x53, 0xe7, 0x01, 0xb7, 0xda, 0xe1, 0xdb, 0x9f, 0xa8,
0x75, 0x6e, 0x42, 0xb1, 0xa2, 0x5a, 0xa2, 0xc4, 0xa3, 0x32, 0xa1, 0xbe, 0xe4, 0x97, 0x48, 0x89,
0xf2, 0x18, 0x5a, 0x4b, 0xac, 0xb0, 0x2c, 0x82, 0x07, 0x18, 0xac, 0xee, 0x11, 0xef, 0x5a, 0x32,
0xc4, 0xf2, 0x1e, 0xad, 0x75, 0x44, 0x70, 0xa4, 0xba, 0x67, 0x2b, 0x12, 0x70, 0x1f, 0xbb, 0x94,
0xb7, 0xa0, 0x4b, 0x04, 0x1f, 0x37, 0xbf, 0xc4, 0x72, 0x97, 0xee, 0x53, 0x4d, 0x1a, 0x86, 0x50,
0xf4, 0xfe, 0x62, 0xdd, 0x91, 0xbd, 0x8e, 0xd1, 0x89, 0xe1, 0x31, 0x5a, 0x29, 0x9f, 0x3f, 0xdc,
0xe6, 0x13, 0x1f, 0xf2, 0xe1, 0x66, 0x5c, 0x99, 0xbd, 0xd9, 0x53, 0x9e, 0xaa, 0xe2, 0xcf, 0x4c,
0x92, 0x98, 0x2d, 0x96, 0xde, 0xee, 0xbc, 0x22, 0x1a, 0xac, 0x65, 0xe1, 0x60, 0x8b, 0x92, 0xff,
0x7d, 0x38, 0x48, 0x93, 0xae, 0x80, 0xb4, 0x79, 0xa0, 0x05, 0xb9, 0x0a, 0x77, 0xfd, 0xe5, 0x59,
0xe7, 0xff, 0xd1, 0x31, 0x4a, 0x13, 0x4f, 0x86, 0x86, 0x59, 0x3e, 0x2e, 0x7e, 0x0c, 0x33, 0x99,
0xb6, 0x89, 0x87, 0x4a, 0x78, 0xc2, 0x84, 0xbf, 0xd0, 0xfb, 0x3f, 0x2c, 0x49, 0xd2, 0xc4, 0xb1,
0x57, 0x00, 0x00
};
@@ -1078,7 +1078,7 @@ const uint8_t PAGE_settings_ui[] PROGMEM = {
// Autogenerated from wled00/data/settings_sync.htm, do not edit!!
const uint16_t PAGE_settings_sync_length = 3489;
const uint16_t PAGE_settings_sync_length = 3490;
const uint8_t PAGE_settings_sync[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xad, 0x1a, 0x6b, 0x73, 0x9b, 0x48,
0xf2, 0x3b, 0xbf, 0x62, 0xc2, 0x56, 0xe5, 0xa4, 0xb5, 0xac, 0xa7, 0xe5, 0x38, 0xb6, 0x20, 0x67,
@@ -1286,19 +1286,19 @@ const uint8_t PAGE_settings_sync[] PROGMEM = {
0x03, 0x89, 0x3c, 0x34, 0x1b, 0xa5, 0xe7, 0x99, 0xca, 0xea, 0x58, 0xdd, 0x66, 0xf1, 0x3e, 0x9c,
0x96, 0xe7, 0xf5, 0x9e, 0xf2, 0x24, 0x49, 0x65, 0x82, 0x76, 0x24, 0x22, 0xf0, 0x92, 0x8c, 0x45,
0x2f, 0x32, 0xf3, 0x7e, 0xcc, 0xd5, 0x3e, 0x01, 0xe4, 0x95, 0x63, 0x42, 0x5b, 0x0a, 0x90, 0x73,
0x3f, 0x9f, 0xff, 0x60, 0xe8, 0x1f, 0x69, 0x88, 0x6e, 0xf8, 0x0b, 0x96, 0x9a, 0x37, 0x68, 0x54,
0xf8, 0xfb, 0x90, 0x8d, 0x5d, 0x11, 0x7e, 0xea, 0x64, 0x31, 0xe4, 0x39, 0x15, 0x76, 0xba, 0x34,
0x71, 0x49, 0x0c, 0x15, 0x7e, 0x71, 0xf2, 0xd1, 0xed, 0x99, 0x2b, 0xbd, 0x76, 0xa3, 0x0d, 0xcc,
0xe2, 0xb5, 0x5e, 0xdf, 0x38, 0x39, 0x68, 0xb6, 0xea, 0x90, 0x60, 0xf0, 0xba, 0x00, 0x54, 0x1c,
0x16, 0x1c, 0xd7, 0x4f, 0x4c, 0x1b, 0xaf, 0x6b, 0x60, 0xb2, 0xa9, 0x86, 0xf6, 0x55, 0xbc, 0x6e,
0x26, 0xd4, 0x7e, 0x77, 0x8c, 0x30, 0x70, 0xdd, 0x42, 0xe8, 0x7d, 0xb3, 0x71, 0x6c, 0xda, 0x78,
0xdd, 0x4c, 0xa8, 0x51, 0x57, 0xbb, 0xa9, 0x7f, 0x5b, 0x48, 0x35, 0x34, 0x53, 0x8d, 0x22, 0x57,
0x4b, 0x13, 0x07, 0x08, 0x9e, 0xbf, 0x31, 0x16, 0x61, 0x8d, 0xaf, 0x65, 0x85, 0xc9, 0x05, 0x2b,
0x84, 0x7e, 0x10, 0xc5, 0xfc, 0xa9, 0x4a, 0x46, 0x1c, 0x5a, 0xec, 0x31, 0xa7, 0xb1, 0xab, 0xdb,
0x0d, 0x54, 0x63, 0xaa, 0x2e, 0x32, 0x03, 0xfd, 0x29, 0x7d, 0xe4, 0x63, 0x70, 0xcc, 0x97, 0x5b,
0x7f, 0x08, 0xf0, 0x33, 0xdf, 0xf4, 0x8d, 0x85, 0xdf, 0x0b, 0xe0, 0xef, 0x16, 0xe0, 0x1f, 0xfe,
0xb6, 0x01, 0x7f, 0xe8, 0x80, 0x3f, 0x4d, 0xfc, 0x1f, 0x61, 0x45, 0x94, 0xf0, 0xaa, 0x28, 0x00,
0x00
0x3f, 0x9f, 0xff, 0x60, 0xc8, 0xfe, 0x47, 0x3a, 0xa2, 0x1b, 0xfe, 0x82, 0xb5, 0xe6, 0x0d, 0x5a,
0x15, 0xfe, 0x40, 0x64, 0x63, 0x5b, 0x84, 0xdf, 0x3a, 0x59, 0x0c, 0x89, 0x4e, 0xc5, 0x9d, 0x2e,
0x4d, 0x5c, 0x12, 0x43, 0x89, 0x5f, 0x1c, 0x7d, 0x74, 0x7b, 0xe6, 0x4a, 0xb3, 0xdd, 0x68, 0x03,
0xb7, 0x78, 0xad, 0xd7, 0x37, 0x8e, 0x0e, 0x9a, 0xad, 0x3a, 0x64, 0x18, 0xbc, 0x2e, 0x00, 0x15,
0xa7, 0x05, 0xc7, 0xf5, 0x13, 0xd3, 0xc6, 0xeb, 0x1a, 0x98, 0x6c, 0xac, 0xa1, 0x9d, 0x15, 0xaf,
0x9b, 0x09, 0xb5, 0xdf, 0x1d, 0x23, 0x0c, 0x5c, 0xb7, 0x10, 0x7a, 0xdf, 0x6c, 0x1c, 0x9b, 0x36,
0x5e, 0x37, 0x13, 0x6a, 0xd4, 0xd5, 0x6e, 0xea, 0xdf, 0x16, 0x52, 0x0d, 0xcd, 0x54, 0xa3, 0xc8,
0xd5, 0xd2, 0xc8, 0x01, 0xa2, 0xe7, 0x6f, 0x8c, 0x45, 0x58, 0xe4, 0x6b, 0x59, 0x61, 0x76, 0xc1,
0x12, 0xa1, 0x1f, 0x44, 0x31, 0x7f, 0xaa, 0x92, 0x11, 0x87, 0x1e, 0x7b, 0xcc, 0x69, 0xec, 0xea,
0x7e, 0x03, 0xd5, 0x98, 0xaa, 0x8b, 0xcc, 0x40, 0x7f, 0x4a, 0x1f, 0xf9, 0x1c, 0x1c, 0x13, 0xe6,
0xd6, 0x5f, 0x02, 0xfc, 0xcc, 0x47, 0x7d, 0x63, 0xe1, 0x07, 0x03, 0xf8, 0xc3, 0x05, 0xf8, 0x87,
0x3f, 0x6e, 0xc0, 0x5f, 0x3a, 0xe0, 0x6f, 0x13, 0xff, 0x07, 0x07, 0x66, 0x12, 0x3e, 0xab, 0x28,
0x00, 0x00
};

File diff suppressed because it is too large Load Diff

View File

@@ -273,6 +273,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
uint8_t oldMap1D2D = seg.map1D2D;
seg.map1D2D = M12_Pixels; // no mapping
// set brightness immediately and disable transition
transitionDelayTemp = 0;
jsonTransitionOnce = true;
@@ -316,6 +319,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
set = 0;
}
}
seg.map1D2D = oldMap1D2D; // restore mapping
strip.trigger(); // force segment update
}
// send UDP/WS if segment options changed (except selection; will also deselect current preset)

View File

@@ -129,6 +129,9 @@ void stateUpdated(byte callMode) {
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
// notify usermods of state change
usermods.onStateChange(callMode);
if (fadeTransition) {
//set correct delay if not using notification delay
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration

View File

@@ -15,6 +15,7 @@ class NetworkDebugPrinter : public Print {
virtual void flush( bool txOnly) { return;} // WLEDMM
};
// use it on your linux/macOS with: nc -p 7868 -u -l -s <network ip>
extern NetworkDebugPrinter NetDebug;
#endif

View File

@@ -156,7 +156,7 @@ void serializePlaylist(JsonObject sObj) {
JsonArray ps = playlist.createNestedArray("ps");
JsonArray dur = playlist.createNestedArray("dur");
JsonArray transition = playlist.createNestedArray(F("transition"));
playlist[F("repeat")] = playlistRepeat;
playlist[F("repeat")] = (playlistIndex < 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
playlist["end"] = playlistEndPreset;
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
for (int i=0; i<playlistLen; i++) {

View File

@@ -274,7 +274,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
} else {
// this is a playlist or API call
if (sObj[F("playlist")].isNull()) {
// we will save API call immediately
// we will save API call immediately (often causes presets.json corruption)
presetToSave = 0;
if (index > 250 || !fileDoc) return; // cannot save API calls to temporary preset (255)
sObj.remove("o");
@@ -284,11 +284,12 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
sObj.remove(F("psave"));
if (sObj["n"].isNull()) sObj["n"] = saveName;
initPresetsFile(); // just in case if someone deleted presets.json using /edit
writeObjectToFileUsingId(getFileName(index), index, fileDoc);
writeObjectToFileUsingId(getFileName(index<255), index, fileDoc);
presetsModifiedTime = toki.second(); //unix time
updateFSInfo();
} else {
// store playlist
// WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1
includeBri = true; // !sObj["on"].isNull();
playlistSave = true;
}

View File

@@ -40,6 +40,7 @@ bool UsermodManager::onMqttMessage(char* topic, char* payload) {
return false;
}
void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin
void UsermodManager::onStateChange(uint8_t mode) { for (byte i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed
/*
* Enables usermods to lookup another Usermod.

View File

@@ -96,10 +96,6 @@
#include "my_config.h"
#endif
#ifdef WLED_DEBUG_HOST
#include "net_debug.h"
#endif
#include <ESPAsyncWebServer.h>
#ifdef WLED_ADD_EEPROM_SUPPORT
#include <EEPROM.h>
@@ -730,6 +726,7 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
// enable additional debug output
#if defined(WLED_DEBUG_HOST)
#include "net_debug.h"
// On the host side, use netcat to receive the log statements: nc -l 7868 -u
// use -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' or FQDN within quotes
#define DEBUGOUT NetDebug