3.1.0.ALPHA2

* Version Bump to 3.1.0.ALPHA2
 * further code changes
 * further integration of multi segments
 * integration of multi segments to GUI
This commit is contained in:
bpohvoodoo
2019-10-03 19:28:39 +02:00
parent fb4cfe3a3e
commit a0a8fe72b5
17 changed files with 3828 additions and 3510 deletions
+37 -135
View File
@@ -1,4 +1,8 @@
#include "definitions.h" #include "definitions.h"
// ***************************************************************************
// Load library "ticker" for blinking status led, mqtt send and save state
// ***************************************************************************
#include <Ticker.h>
#include "version.h" #include "version.h"
// *************************************************************************** // ***************************************************************************
@@ -10,10 +14,10 @@
#include <DNSServer.h> #include <DNSServer.h>
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager #include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <FS.h>
#include <WiFiClient.h> #include <WiFiClient.h>
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include <FS.h>
#include <WebSockets.h> //https://github.com/Links2004/arduinoWebSockets #include <WebSockets.h> //https://github.com/Links2004/arduinoWebSockets
#include <WebSocketsServer.h> #include <WebSocketsServer.h>
@@ -25,8 +29,6 @@
GY33_MCU tcs; GY33_MCU tcs;
#endif #endif
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
// MQTT // MQTT
#if defined(ENABLE_MQTT) #if defined(ENABLE_MQTT)
#if ENABLE_MQTT == 0 #if ENABLE_MQTT == 0
@@ -47,12 +49,11 @@
AsyncMqttClient * mqtt_client; AsyncMqttClient * mqtt_client;
WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler; WiFiEventHandler wifiDisconnectHandler;
Ticker mqttReconnectTimer;
Ticker wifiReconnectTimer;
#endif #endif
#endif #if defined(ENABLE_HOMEASSISTANT)
Ticker ha_send_data;
#if defined(ARDUINOJSON_VERSION)
#if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR >= 8)
#error "Install ArduinoJson v6.8.x or higher"
#endif #endif
#endif #endif
@@ -166,21 +167,9 @@ WS2812FX * strip = NULL;
} }
#endif #endif
// ***************************************************************************
// Load library "ticker" for blinking status led, mqtt send and save state
// ***************************************************************************
#include <Ticker.h>
Ticker ticker; Ticker ticker;
#if defined(ENABLE_MQTT)
#if ENABLE_MQTT == 1
Ticker mqttReconnectTimer;
Ticker wifiReconnectTimer;
#endif
#if defined(ENABLE_HOMEASSISTANT)
Ticker ha_send_data;
#endif
#endif
void tick() { void tick() {
//toggle state //toggle state
@@ -193,9 +182,6 @@ void tick() {
decode_results results; decode_results results;
#endif #endif
Ticker settings_save_state;
Ticker settings_save_conf;
// *************************************************************************** // ***************************************************************************
// Saved state handling in WifiManager // Saved state handling in WifiManager
// *************************************************************************** // ***************************************************************************
@@ -242,97 +228,22 @@ void saveConfigCallback () {
// *************************************************************************** // ***************************************************************************
#include "spiffs_webserver.h" #include "spiffs_webserver.h"
// ***************************************************************************
// Include: Request handlers
// ***************************************************************************
#include "request_handlers.h"
// *************************************************************************** // ***************************************************************************
// Include: Custom animations // Include: Custom animations
// *************************************************************************** // ***************************************************************************
#include "mode_custom_ws2812fx_animations.h" // Add animations in this file #include "mode_custom_ws2812fx_animations.h" // Add animations in this file
// function to Initialize the strip // ***************************************************************************
void initStrip(uint16_t stripSize = WS2812FXStripSettings.stripSize, char RGBOrder[5] = WS2812FXStripSettings.RGBOrder, uint8_t pin = WS2812FXStripSettings.pin, uint8_t fxoptions = WS2812FXStripSettings.fxoptions ){ // Include: helper functions
DBG_OUTPUT_PORT.println("Initializing strip!"); // ***************************************************************************
/*#if defined(USE_WS2812FX_DMA) #include "helper_functions.h"
if (dma != NULL) {
delete(dma);
}
#endif*/
if (strip != NULL) {
delete(strip);
WS2812FXStripSettings.stripSize = stripSize;
strcpy(WS2812FXStripSettings.RGBOrder, RGBOrder);
WS2812FXStripSettings.pin = pin;
WS2812FXStripSettings.fxoptions = fxoptions;
}
if (ledstates != NULL) { // ***************************************************************************
delete(ledstates); // Include: other functions
} // ***************************************************************************
ledstates = new uint8_t [WS2812FXStripSettings.stripSize]; #include "json_functions.h"
#include "filesystem_functions.h"
#if !defined(LED_TYPE_WS2811) #include "request_handlers.h"
strip = new WS2812FX(stripSize, pin, checkRGBOrder(RGBOrder) + NEO_KHZ800);
#else
strip = new WS2812FX(stripSize, pin, checkRGBOrder(RGBOrder) + NEO_KHZ400);
#endif
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
strip->init();
#if defined(USE_WS2812FX_DMA)
initDMA(stripSize);
strip->setCustomShow(DMA_Show);
#endif
//parameters: index, start, stop, mode, color, speed, options
for (uint8_t seg=0; seg < num_segments; seg++) {
(readStateSegmentFS(seg)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
strip->setSegment(seg, seg_start, seg_stop , ws2812fx_mode, hex_colors_trans, convertSpeed(ws2812fx_speed), fxoptions);
}
//strip->setSegment(0, 0, (stripSize - 1)/2, ws2812fx_mode, hex_colors_trans, convertSpeed(ws2812fx_speed), fxoptions);
//strip->setSegment(1, ((stripSize - 1)/2) + 1, (stripSize - 1), ws2812fx_mode, hex_colors_trans, convertSpeed(ws2812fx_speed), fxoptions);
strip->setCustomMode(0, F("Autoplay"), myCustomEffect0);
strip->setCustomMode(1, F("Custom WS"), myCustomEffect1);
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
strip->setCustomMode(2, F("TV"), myCustomEffect2);
strip->setCustomMode(3, F("E1.31"), myCustomEffect3);
strip->setCustomMode(4, F("Fire 2012"), myCustomEffect4);
strip->setCustomMode(5, F("Gradient"), myCustomEffect5);
gReverseDirection = (WS2812FXStripSettings.fxoptions & 128);
DBG_OUTPUT_PORT.print("Number of Segments: ");
DBG_OUTPUT_PORT.println(strip->getNumSegments());
if (e131 != NULL) { delete(e131); }
e131 = new ESPAsyncE131(END_UNIVERSE - START_UNIVERSE + 1);
float universe_leds = 170.0; // a universe has only 512 (0..511) channels: 3*170 or 4*128 <= 512
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) {
//universe_leds = 128.0;
}
float float_enduni = stripSize/universe_leds;
uint8_t END_UNIVERSE = stripSize/universe_leds;
if (float_enduni > END_UNIVERSE) {
END_UNIVERSE = END_UNIVERSE +1;
}
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
if (e131->begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) {// Listen via Multicast
DBG_OUTPUT_PORT.println(F("Listening for data..."));
} else {
DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***"));
}
#endif
}
#if defined(ENABLE_MQTT) #if defined(ENABLE_MQTT)
void initMqtt() { void initMqtt() {
@@ -713,6 +624,7 @@ void loop() {
// *************************************************************************** // ***************************************************************************
// Simple statemachine that handles the different modes // Simple statemachine that handles the different modes
// *************************************************************************** // ***************************************************************************
if ((mode == OFF) && ((strip->getBrightness() == 0) || !transEffect)) { if ((mode == OFF) && ((strip->getBrightness() == 0) || !transEffect)) {
if(strip->isRunning()) { if(strip->isRunning()) {
strip->strip_off(); // Workaround: to be shure, strip->strip_off(); // Workaround: to be shure,
@@ -743,15 +655,6 @@ void loop() {
} }
} }
if (mode == INIT_STRIP) {
mode = prevmode;
strip->strip_off();
delay(10);
if(strip->isRunning()) strip->stop();
initStrip();
prevmode = INIT_STRIP;
}
if (mode == SET) { if (mode == SET) {
mode = HOLD; mode = HOLD;
// Segment // Segment
@@ -792,6 +695,14 @@ void loop() {
strip->trigger(); strip->trigger();
} }
if ((mode == HOLD) || ((mode == OFF) && (strip->getBrightness() > 0) && transEffect)) {
if (ws2812fx_mode == FX_MODE_CUSTOM_0) {
handleAutoPlay();
}
if(!strip->isRunning()) strip->start();
strip->service();
}
if (prevmode != mode) { if (prevmode != mode) {
convertColors(); convertColors();
if (memcmp(hex_colors_trans, strip->getColors(segment), sizeof(hex_colors_trans)) != 0) { if (memcmp(hex_colors_trans, strip->getColors(segment), sizeof(hex_colors_trans)) != 0) {
@@ -800,13 +711,6 @@ void loop() {
} }
strip->setSpeed(segment, convertSpeed(ws2812fx_speed_actual)); strip->setSpeed(segment, convertSpeed(ws2812fx_speed_actual));
//strip->setBrightness(brightness_actual); //strip->setBrightness(brightness_actual);
if (prevmode != INIT_STRIP) { // do not save if INIT_STRIP mode was set
#if defined(ENABLE_STATE_SAVE)
if(!settings_save_state.active()) settings_save_state.once(3, tickerSaveState);
#endif
snprintf(last_state, sizeof(last_state), "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", prevmode, ws2812fx_mode, ws2812fx_speed, brightness, main_color.red, main_color.green, main_color.blue, main_color.white, back_color.red, back_color.green, back_color.blue, back_color.white, xtra_color.red, xtra_color.green, xtra_color.blue, xtra_color.white);
last_state[sizeof(last_state) - 1] = 0x00;
}
#if defined(ENABLE_MQTT) #if defined(ENABLE_MQTT)
#if ENABLE_MQTT == 0 #if ENABLE_MQTT == 0
mqtt_client->publish(mqtt_outtopic, mqtt_buf); mqtt_client->publish(mqtt_outtopic, mqtt_buf);
@@ -819,23 +723,22 @@ void loop() {
#endif #endif
#endif #endif
} }
prevmode = mode;
#if defined(ENABLE_STATE_SAVE) #if defined(ENABLE_STATE_SAVE)
if (updateState){ if (updateState){
(writeStateFS(updateState)) ? DBG_OUTPUT_PORT.println(" State FS Save Success!") : DBG_OUTPUT_PORT.println("State FS Save failure!"); (writeStateFS(updateState)) ? DBG_OUTPUT_PORT.println("State FS Save Success!") : DBG_OUTPUT_PORT.println("State FS Save failure!");
}
if (updateSegState) {
(writeSegmentStateFS(updateSegState, segment)) ? DBG_OUTPUT_PORT.println("Segment State FS Save Success!") : DBG_OUTPUT_PORT.println("Segment State FS Save failure!");
initStrip();
} }
if (updateConfig) { if (updateConfig) {
(writeConfigFS(updateConfig)) ? DBG_OUTPUT_PORT.println("Config FS Save success!"): DBG_OUTPUT_PORT.println("Config FS Save failure!"); (writeConfigFS(updateConfig)) ? DBG_OUTPUT_PORT.println("Config FS Save success!"): DBG_OUTPUT_PORT.println("Config FS Save failure!");
} }
#endif #endif
if ((mode == HOLD) || ((mode == OFF) && (strip->getBrightness() > 0) && transEffect)) {
if (ws2812fx_mode == FX_MODE_CUSTOM_0) {
handleAutoPlay();
}
if(!strip->isRunning()) strip->start();
strip->service();
}
// Async color transition // Async color transition
if (memcmp(hex_colors_trans, strip->getColors(segment), sizeof(hex_colors_trans)) != 0) { if (memcmp(hex_colors_trans, strip->getColors(segment), sizeof(hex_colors_trans)) != 0) {
if (transEffect) { if (transEffect) {
@@ -917,7 +820,6 @@ void loop() {
} }
} }
*/ */
prevmode = mode;
#if defined(ENABLE_REMOTE) #if defined(ENABLE_REMOTE)
handleRemote(); handleRemote();
+3 -1
View File
@@ -182,7 +182,9 @@
var mkfile = document.createElement("button"); var mkfile = document.createElement("button");
mkfile.innerHTML = 'MkFile'; mkfile.innerHTML = 'MkFile';
document.getElementById(element).appendChild(mkfile); document.getElementById(element).appendChild(mkfile);
var para = document.createElement("text");
para.innerHTML = " Press Ctrl-S for save, Ctrl-Z for undo, Ctrl-Shift-Z for redo";
document.getElementById(element).appendChild(para);
function httpPostProcessRequest(){ function httpPostProcessRequest(){
if (xmlHttp.readyState == 4){ if (xmlHttp.readyState == 4){
if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText); if(xmlHttp.status != 200) alert("ERROR["+xmlHttp.status+"]: "+xmlHttp.responseText);
Binary file not shown.
+128 -31
View File
@@ -877,7 +877,7 @@ input[type=number], label{
</div> </div>
</div> </div>
</div> </div>
<div class="flex xs12 sm7"> <div class="flex xs12 sm8">
<div class="sliders container"> <div class="sliders container">
<div class="color-wrap" style="display:none"> <div class="color-wrap" style="display:none">
<div id="color-display"></div> <div id="color-display"></div>
@@ -912,6 +912,13 @@ input[type=number], label{
<input type="number" id="speedNum"> <input type="number" id="speedNum">
<input value="255" type="range" min="0" max="255" id="speed"> <input value="255" type="range" min="0" max="255" id="speed">
</div> </div>
<div id="segments" class="container" style="text-align: left;">
<div class="layout row wrap">
<div class="flex xs12 sm2" id="selectSegLbl" style="text-align: left;"><p>selectSeg</p>
<select id="selectseg" class="custom-select" style="border: 2px solid #aaaaaa; border-radius: 6px; width:90%; "></select>
</div>
</div>
</div>
<div id="message" class="container hidden" style="text-align: left;"> <div id="message" class="container hidden" style="text-align: left;">
<div id="wsmessageLbl" style="text-align: left;"><p>wsMessage</p> <div id="wsmessageLbl" style="text-align: left;"><p>wsMessage</p>
<input type="text" id="wsmessage" style="border: 2px solid #aaaaaa; border-radius: 6px; width:100%;" /> <input type="text" id="wsmessage" style="border: 2px solid #aaaaaa; border-radius: 6px; width:100%;" />
@@ -959,14 +966,17 @@ input[type=number], label{
</div> </div>
</div> </div>
<div class="layout row wrap"> <div class="layout row wrap">
<div class="flex xs12 sm4"><p>selectCount</p> <div class="flex xs12 sm3"><p>selectSegCnt</p>
<input type="number" min="0" max="65535" id="selectcount" style="border: 2px solid #aaaaaa; border-radius: 6px; width:100%;" /> <input type="number" min="1" max="9" id="selectsegcnt" style="border: 2px solid #aaaaaa; border-radius: 6px; width:50%;" />
</div> </div>
<div class="flex xs12 sm4"><p>selectRGBO</p> <div class="flex xs12 sm3"><p>selectCount</p>
<input type="number" min="0" max="65535" id="selectcount" style="border: 2px solid #aaaaaa; border-radius: 6px; width:50%;" />
</div>
<div class="flex xs12 sm3"><p>selectRGBO</p>
<select id="selectrgbo" class="custom-select"></select> <select id="selectrgbo" class="custom-select"></select>
</div> </div>
<div class="flex xs12 sm4"><p>selectPin</p> <div class="flex xs12 sm3"><p>selectPin</p>
<input type="number" min="0" max="16" id="selectpin" style="border: 2px solid #aaaaaa; border-radius: 6px; width:100%;" /> <input type="number" min="0" max="16" id="selectpin" style="border: 2px solid #aaaaaa; border-radius: 6px; width:50%;" />
</div> </div>
</div> </div>
<div class="layout row wrap"> <div class="layout row wrap">
@@ -983,6 +993,14 @@ input[type=number], label{
<select id="selectoptsize" class="custom-select"></select> <select id="selectoptsize" class="custom-select"></select>
</div> </div>
</div> </div>
<div class="layout row wrap">
<div class="flex xs12 sm6"><p>segStart</p>
<input type="number" min="0" max="*jsvariable" id="segstart" style="border: 2px solid #aaaaaa; border-radius: 6px; width:90%;" />
</div>
<div class="flex xs12 sm6"><p>segStop</p>
<input type="number" min="0" max="*jsvariable" id="segstop" style="border: 2px solid #aaaaaa; border-radius: 6px; width:90%;" />
</div>
</div>
<div class="layout row wrap"> <div class="layout row wrap">
<div class="flex xs12" style="text-align: left; margin:20px 0;"><p>selectColors</p> <div class="flex xs12" style="text-align: left; margin:20px 0;"><p>selectColors</p>
<span style="white-space: nowrap;"> <span style="white-space: nowrap;">
@@ -1043,6 +1061,9 @@ var language = {
white: "White", white: "White",
not_greater: "cannot enter numbers greater than 255", not_greater: "cannot enter numbers greater than 255",
not_less: "cannot enter numbers less than 0", not_less: "cannot enter numbers less than 0",
selectSeg: "Select segment",
segStart: "First LED of selected segment",
segStop: "Last LED of selected segment",
wsMessage: "Websocket Message:", wsMessage: "Websocket Message:",
selectLanguage: "Select Language:", selectLanguage: "Select Language:",
selectHostname: "Hostname:", selectHostname: "Hostname:",
@@ -1050,6 +1071,7 @@ var language = {
selectMQTTPort: "and Port:", selectMQTTPort: "and Port:",
selectMQTTUser: "MQTT Username:", selectMQTTUser: "MQTT Username:",
selectMQTTPass: "MQTT Password:", selectMQTTPass: "MQTT Password:",
selectSegCnt: "Number of Segments:",
selectCount: "Strip LED Count:", selectCount: "Strip LED Count:",
selectRGBO: "RGB Order:", selectRGBO: "RGB Order:",
selectPin: "Strip GPIO Pin:", selectPin: "Strip GPIO Pin:",
@@ -1099,6 +1121,9 @@ var language = {
white: "Wit", white: "Wit",
not_greater: "Geen nummers hoger dan 255", not_greater: "Geen nummers hoger dan 255",
not_less: "Geen nummers lager dan 0", not_less: "Geen nummers lager dan 0",
selectSeg: "Selecteer segment",
segStart: "Eerste LED van huidige segmenten",
segStop: "Laatste LED van huidige segmenten",
wsMessage: "Websocket message:", wsMessage: "Websocket message:",
selectLanguage: "Selecteer Taal:", selectLanguage: "Selecteer Taal:",
selectHostname: "Hostname:", selectHostname: "Hostname:",
@@ -1106,6 +1131,7 @@ var language = {
selectMQTTPort: "en Port:", selectMQTTPort: "en Port:",
selectMQTTUser: "MQTT gebruikersnaam:", selectMQTTUser: "MQTT gebruikersnaam:",
selectMQTTPass: "MQTT wachtwoord:", selectMQTTPass: "MQTT wachtwoord:",
selectSegCnt: "Number of Segments:",
selectCount: "LED nummer:", selectCount: "LED nummer:",
selectPin: "Strip GPIO Pin:", selectPin: "Strip GPIO Pin:",
selectRGBO: "RGB Order:", selectRGBO: "RGB Order:",
@@ -1155,6 +1181,9 @@ var language = {
white: "Weiß", white: "Weiß",
not_greater: "Akzeptiere keine Nummern größer 255", not_greater: "Akzeptiere keine Nummern größer 255",
not_less: "Akzeptiere keine Nummern kleiner 0", not_less: "Akzeptiere keine Nummern kleiner 0",
selectSeg: "Segment wählen",
segStart: "Erste LED des gewählten Segments",
segStop: "Letzte LED des gewählten Segments",
wsMessage: "Websocket Message:", wsMessage: "Websocket Message:",
selectLanguage: "Sprache auswählen:", selectLanguage: "Sprache auswählen:",
selectHostname: "Hostname:", selectHostname: "Hostname:",
@@ -1162,6 +1191,7 @@ var language = {
selectMQTTPort: "und Port:", selectMQTTPort: "und Port:",
selectMQTTUser: "MQTT Username:", selectMQTTUser: "MQTT Username:",
selectMQTTPass: "MQTT Password:", selectMQTTPass: "MQTT Password:",
selectSegCnt: "Anzahl Segmente:",
selectCount: "Strip LED Anzahl:", selectCount: "Strip LED Anzahl:",
selectRGBO: "RGB Reihenfolge:", selectRGBO: "RGB Reihenfolge:",
selectPin: "Strip GPIO Pin:", selectPin: "Strip GPIO Pin:",
@@ -1281,6 +1311,7 @@ var config = {
mqtt_port: 0, mqtt_port: 0,
mqtt_user: "", mqtt_user: "",
mqtt_pass: "", mqtt_pass: "",
ws_seg: 1,
ws_cnt: 0, ws_cnt: 0,
ws_rgbo: "", ws_rgbo: "",
ws_pin: 0, ws_pin: 0,
@@ -1289,6 +1320,9 @@ var config = {
transitionEffects: true transitionEffects: true
}; };
var data = { var data = {
segment: 0,
start: 0,
stop: 0,
mode: 0, mode: 0,
color: {w:0, r:0, g:0, b:0, hex:"00000000", w2:0, r2:0, g2:0, b2:0, hex2:"00000000", w3:0, r3:0, g3:0, b3:0, hex3:"00000000"}, color: {w:0, r:0, g:0, b:0, hex:"00000000", w2:0, r2:0, g2:0, b2:0, hex2:"00000000", w3:0, r3:0, g3:0, b3:0, hex3:"00000000"},
brightness: 192, brightness: 192,
@@ -1341,7 +1375,7 @@ function displayColors(all = false) {
} }
// initial color val numbers when DOM is loaded // initial color val numbers when DOM is loaded
function colorNumrVals(){ function colorNumVals(){
redNumVal.value = red.value; redNumVal.value = red.value;
greenNumVal.value = green.value; greenNumVal.value = green.value;
blueNumVal.value = blue.value; blueNumVal.value = blue.value;
@@ -1447,7 +1481,7 @@ function initcolorSliders(){
displayColors(); displayColors();
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
redNumVal.dispatchEvent(event); redNumVal.dispatchEvent(event);
}); });
@@ -1456,7 +1490,7 @@ function initcolorSliders(){
displayColors(); displayColors();
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
greenNumVal.dispatchEvent(event); greenNumVal.dispatchEvent(event);
}); });
@@ -1465,7 +1499,7 @@ function initcolorSliders(){
displayColors(); displayColors();
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
blueNumVal.dispatchEvent(event); blueNumVal.dispatchEvent(event);
}); });
@@ -1474,7 +1508,7 @@ function initcolorSliders(){
displayColors(); displayColors();
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
whiteNumVal.dispatchEvent(event); whiteNumVal.dispatchEvent(event);
}); });
@@ -1482,14 +1516,14 @@ function initcolorSliders(){
bright.addEventListener('input', () => { bright.addEventListener('input', () => {
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
brightNumVal.dispatchEvent(event); brightNumVal.dispatchEvent(event);
}); });
speed.addEventListener('input', () => { speed.addEventListener('input', () => {
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
// Trigger onChange event to send value // Trigger onChange event to send value
speedNumVal.dispatchEvent(event); speedNumVal.dispatchEvent(event);
}); });
@@ -1548,6 +1582,7 @@ function getConfig() {
if (typeof res.mqtt_port !== "undefined") config.mqtt_port = res.mqtt_port; if (typeof res.mqtt_port !== "undefined") config.mqtt_port = res.mqtt_port;
if (typeof res.mqtt_user !== "undefined") config.mqtt_user = res.mqtt_user; if (typeof res.mqtt_user !== "undefined") config.mqtt_user = res.mqtt_user;
if (typeof res.mqtt_pass !== "undefined") config.mqtt_pass = res.mqtt_pass; if (typeof res.mqtt_pass !== "undefined") config.mqtt_pass = res.mqtt_pass;
if (typeof res.ws_seg !== "undefined") config.ws_seg = res.ws_seg;
if (typeof res.ws_cnt !== "undefined") config.ws_cnt = res.ws_cnt; if (typeof res.ws_cnt !== "undefined") config.ws_cnt = res.ws_cnt;
if (typeof res.ws_rgbo !== "undefined") { if (typeof res.ws_rgbo !== "undefined") {
config.ws_rgbo = res.ws_rgbo; config.ws_rgbo = res.ws_rgbo;
@@ -1612,8 +1647,12 @@ function readSettings() {
if (typeof(tmpsettings[set]) !== "undefined") settings[set] = tmpsettings[set]; if (typeof(tmpsettings[set]) !== "undefined") settings[set] = tmpsettings[set];
} }
applySettings(); applySettings();
if (e && e.substring(0,6) !== "ERROR!") connectAdditionalNodes(); if (e && e.substring(0,6) !== "ERROR!") {
else console.warn("ERROR loading settings", e); connectAdditionalNodes();
} else {
console.warn("ERROR loading settings", e);
saveSettings();
}
}); });
} }
function applySettings() { function applySettings() {
@@ -1684,7 +1723,7 @@ function onSelectColNum(colnum) {
white.value = data.color["w" + (colnum > 1 ? colnum : "")]; white.value = data.color["w" + (colnum > 1 ? colnum : "")];
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
} }
function initSettings() { function initSettings() {
// Add languages to language select // Add languages to language select
@@ -1736,11 +1775,33 @@ function initSettings() {
config.mqtt_pass = mqtt_pass.value; config.mqtt_pass = mqtt_pass.value;
ws_send("Cmw" + config.mqtt_pass); ws_send("Cmw" + config.mqtt_pass);
}); });
var count = document.getElementById("selectcount"); var selsegment = document.getElementById("selectseg");
count.value = config.ws_cnt; for(var i = 0; i < config.ws_seg; i++) {
count.addEventListener('change', ()=>{ var option = document.createElement("OPTION");
config.ws_cnt = count.value; option.setAttribute("value", i);
ws_send("Csc" + config.ws_cnt); option.innerHTML = i;
selsegment.appendChild(option);
}
selsegment.value = data.segment;
selsegment.addEventListener('change', ()=>{
data.segment = selsegment.value;
ws_send("Ss" + data.segment);
});
var num_segments = document.getElementById("selectsegcnt");
num_segments.value = config.ws_seg;
num_segments.addEventListener('change', ()=>{
config.ws_seg = num_segments.value;
ws_send("Css" + config.ws_seg);
while (selsegment.firstChild) {
selsegment.removeChild(selsegment.firstChild);
}
for(var i = 0; i < config.ws_seg; i++) {
var option = document.createElement("OPTION");
option.setAttribute("value", i);
option.innerHTML = i;
selsegment.appendChild(option);
}
selsegment.value = data.segment;
}); });
var pin = document.getElementById("selectpin"); var pin = document.getElementById("selectpin");
pin.value = config.ws_pin; pin.value = config.ws_pin;
@@ -1760,6 +1821,28 @@ function initSettings() {
config.ws_rgbo = rgbo.value; config.ws_rgbo = rgbo.value;
ws_send("Csr" + config.ws_rgbo); ws_send("Csr" + config.ws_rgbo);
}); });
var start = document.getElementById("segstart");
start.setAttribute("max",config.ws_cnt-1);
start.value = data.start;
start.addEventListener('change', ()=>{
data.start = start.value;
ws_send("S[" + data.start);
});
var stop = document.getElementById("segstop");
stop.setAttribute("max",config.ws_cnt-1);
stop.value = data.stop;
stop.addEventListener('change', ()=>{
data.stop = stop.value;
ws_send("S]" + data.stop);
});
var count = document.getElementById("selectcount");
count.value = config.ws_cnt;
count.addEventListener('change', ()=>{
config.ws_cnt = count.value;
ws_send("Csc" + config.ws_cnt);
start.setAttribute("max",config.ws_cnt-1);
stop.setAttribute("max",config.ws_cnt-1);
});
var optrev = document.getElementById("selectoptrev"); var optrev = document.getElementById("selectoptrev");
for (var code in selectoptrev) { for (var code in selectoptrev) {
var option = document.createElement("OPTION"); var option = document.createElement("OPTION");
@@ -1855,6 +1938,7 @@ function initSettings() {
settings.theme_back = colback.value; settings.theme_back = colback.value;
document.getElementById("container").style.backgroundColor = settings.theme_back; document.getElementById("container").style.backgroundColor = settings.theme_back;
document.getElementById("language").style.backgroundColor = settings.theme_back; document.getElementById("language").style.backgroundColor = settings.theme_back;
document.getElementById("selectseg").style.backgroundColor = settings.theme_back;
document.getElementById("selectrgbo").style.backgroundColor = settings.theme_back; document.getElementById("selectrgbo").style.backgroundColor = settings.theme_back;
document.getElementById("selectoptrev").style.backgroundColor = settings.theme_back; document.getElementById("selectoptrev").style.backgroundColor = settings.theme_back;
document.getElementById("selectoptfade").style.backgroundColor = settings.theme_back; document.getElementById("selectoptfade").style.backgroundColor = settings.theme_back;
@@ -1867,6 +1951,7 @@ function initSettings() {
for (var i = 0; i < icons.length; i++) { for (var i = 0; i < icons.length; i++) {
icons[i].style.color = (yiq >= 125) ? '#222' : '#EEE'; icons[i].style.color = (yiq >= 125) ? '#222' : '#EEE';
} }
document.getElementById("selectSegLbl").style.color = (yiq >= 125) ? '#111' : '#EEE';
document.getElementById("wsmessageLbl").style.color = (yiq >= 125) ? '#111' : '#EEE'; document.getElementById("wsmessageLbl").style.color = (yiq >= 125) ? '#111' : '#EEE';
document.getElementById("redNum").style.color = (yiq >= 125) ? '#111' : '#EEE'; document.getElementById("redNum").style.color = (yiq >= 125) ? '#111' : '#EEE';
document.getElementById("greenNum").style.color = (yiq >= 125) ? '#111' : '#EEE'; document.getElementById("greenNum").style.color = (yiq >= 125) ? '#111' : '#EEE';
@@ -2069,19 +2154,22 @@ function ws_connect() {
// document.getElementById('modal').style.display = "none"; // document.getElementById('modal').style.display = "none";
// console.log("res", res); // console.log("res", res);
if (res) { if (res) {
// Status starts here
if (typeof res.mode !== "undefined") data.mode = res.mode; if (typeof res.mode !== "undefined") data.mode = res.mode;
if (typeof res.brightness !== "undefined") {
data.brightness = res.brightness;
// init ColorSliderVals
bright.value = res.brightness;
}
// Segment Status starts here
if (typeof res.segment !== "undefined") { data.segment= res.segment; document.getElementById("selectseg").value = data.segment; }
if (typeof res.start !== "undefined") { data.start= res.start; document.getElementById("segstart").value = data.start; }
if (typeof res.stop !== "undefined") { data.stop = res.stop; document.getElementById("segstop").value = data.stop; }
if (typeof res.ws2812fx_mode !== "undefined") data.ws2812fx_mode = res.ws2812fx_mode; if (typeof res.ws2812fx_mode !== "undefined") data.ws2812fx_mode = res.ws2812fx_mode;
if (typeof res.speed !== "undefined") { if (typeof res.speed !== "undefined") {
data.speed = res.speed; data.speed = res.speed;
// init SliderVals // init SliderVals
speed.value = res.speed; speed.value = res.speed;
} }
if (typeof res.brightness !== "undefined") {
data.brightness = res.brightness;
// init ColorSliderVals
bright.value = res.brightness;
}
if (typeof res.color !== "undefined") { if (typeof res.color !== "undefined") {
data.color.w = res.color[0]; data.color.w = res.color[0];
data.color.r = res.color[1]; data.color.r = res.color[1];
@@ -2115,7 +2203,7 @@ function ws_connect() {
red.value = data.color.r3; red.value = data.color.r3;
green.value = data.color.g3; green.value = data.color.g3;
blue.value = data.color.b3; blue.value = data.color.b3;
white.value = data.color.w3; white.value = data.color.w3;
} }
} }
// Config starts here // Config starts here
@@ -2124,6 +2212,7 @@ function ws_connect() {
if (typeof res.mqtt_port !== "undefined") { config.mqtt_port = res.mqtt_port; document.getElementById("mqtt_port").value = config.mqtt_port; } if (typeof res.mqtt_port !== "undefined") { config.mqtt_port = res.mqtt_port; document.getElementById("mqtt_port").value = config.mqtt_port; }
if (typeof res.mqtt_user !== "undefined") { config.mqtt_user = res.mqtt_user; document.getElementById("mqtt_user").value = config.mqtt_user; } if (typeof res.mqtt_user !== "undefined") { config.mqtt_user = res.mqtt_user; document.getElementById("mqtt_user").value = config.mqtt_user; }
if (typeof res.mqtt_pass !== "undefined") { config.mqtt_pass = res.mqtt_pass; document.getElementById("mqtt_pass").value = config.mqtt_pass; } if (typeof res.mqtt_pass !== "undefined") { config.mqtt_pass = res.mqtt_pass; document.getElementById("mqtt_pass").value = config.mqtt_pass; }
if (typeof res.ws_seg !== "undefined") { config.ws_seg = res.ws_seg; document.getElementById("selectsegcnt").value = config.ws_seg; }
if (typeof res.ws_cnt !== "undefined") { config.ws_cnt = res.ws_cnt; document.getElementById("selectcount").value = config.ws_cnt; } if (typeof res.ws_cnt !== "undefined") { config.ws_cnt = res.ws_cnt; document.getElementById("selectcount").value = config.ws_cnt; }
if (typeof res.ws_rgbo !== "undefined") { if (typeof res.ws_rgbo !== "undefined") {
config.ws_rgbo = res.ws_rgbo; config.ws_rgbo = res.ws_rgbo;
@@ -2148,6 +2237,7 @@ function ws_connect() {
document.getElementById("selectoptgamma").value = (config.ws_fxopt & 8); document.getElementById("selectoptgamma").value = (config.ws_fxopt & 8);
document.getElementById("selectoptsize").value = (config.ws_fxopt & 6); document.getElementById("selectoptsize").value = (config.ws_fxopt & 6);
} }
if (typeof res.transEffect !== "undefined") { config.transitionEffects = res.transEffect; document.getElementById("set-transitionEffects").value = config.transitionEffects; }
// Modes starts here // Modes starts here
if (typeof res[0] !== "undefined") { if (typeof res[0] !== "undefined") {
res.forEach(item => { res.forEach(item => {
@@ -2157,7 +2247,7 @@ function ws_connect() {
}); });
} }
// init Color Vals // init Color Vals
colorNumrVals(); colorNumVals();
initSliderColors(); initSliderColors();
// init Change Range Val // init Change Range Val
changeRangeNumVal(); changeRangeNumVal();
@@ -2218,6 +2308,8 @@ function select_active_button() {
if (arr.indexOf("hidden") === -1) { if (arr.indexOf("hidden") === -1) {
wsmess.className += " hidden"; wsmess.className += " hidden";
} }
segments = document.getElementById("segments");
segments.className = segments.className.replace(/\b hidden\b/g, "");
} }
if (data.mode >= 1) { if (data.mode >= 1) {
document.getElementById(data.ws2812fx_mode).style.backgroundColor = settings.theme_btnsel; document.getElementById(data.ws2812fx_mode).style.backgroundColor = settings.theme_btnsel;
@@ -2229,6 +2321,11 @@ function select_active_button() {
} else if (data.ws2812fx_mode === 57) { //CUSTOM_WS } else if (data.ws2812fx_mode === 57) { //CUSTOM_WS
wsmess = document.getElementById("message"); wsmess = document.getElementById("message");
wsmess.className = wsmess.className.replace(/\b hidden\b/g, ""); wsmess.className = wsmess.className.replace(/\b hidden\b/g, "");
sements = document.getElementById("segments");
var arr = segments.className.split(" ");
if (arr.indexOf("hidden") === -1) {
segments.className += " hidden";
}
disable_modebuttons(false); disable_modebuttons(false);
disable_color_selection(true); disable_color_selection(true);
disable_bright_selection(false); disable_bright_selection(false);
@@ -2357,7 +2454,7 @@ function onSelectColor(event) {
displayColors(); displayColors();
initSliderColors(); initSliderColors();
changeRangeNumVal(); changeRangeNumVal();
colorNumrVals(); colorNumVals();
} }
} }
function redrawColorPicker() { function redrawColorPicker() {
@@ -2525,7 +2622,7 @@ document.addEventListener("DOMContentLoaded", function(event) {
getModes(); getModes();
readSettings(); readSettings();
ws_connect(); ws_connect();
ws_send("$") ws_send("$");
document.getElementById("modal-content").innerHTML = language.en.loadModes; document.getElementById("modal-content").innerHTML = language.en.loadModes;
//ws_send("C"); //ws_send("C");
getConfig(); getConfig();
Binary file not shown.
+3 -4
View File
@@ -18,6 +18,7 @@ char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just
#define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code. #define ENABLE_OTA 1 // If defined, enable Arduino OTA code. If set to 0 enable Arduino OTA code, if set to 1 enable ESP8266HTTPUpdateServer OTA code.
#define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client #define ENABLE_MQTT 1 // If defined use MQTT OR AMQTT, if set to 0 enable MQTT client code, see: https://github.com/toblum/McLighting/wiki/MQTT-API, if set to 1, enable Async MQTT code, see: https://github.com/marvinroger/async-mqtt-client
//#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname //#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname
//#define ENABLE_MQTT_INCLUDE_IP // uncomment/comment to add the IP-adress to the MQTT message
#define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active #define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active
#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth #define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth
#define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button. #define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button.
@@ -30,7 +31,7 @@ char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just
#define ENABLE_STATE_SAVE // If defined, load saved state on reboot and save state on SPIFFS #define ENABLE_STATE_SAVE // If defined, load saved state on reboot and save state on SPIFFS
#define CUSTOM_WS2812FX_ANIMATIONS // uncomment and put animations in "custom_ws2812fx_animations.h" #define CUSTOM_WS2812FX_ANIMATIONS // uncomment and put animations in "custom_ws2812fx_animations.h"
//#define USE_HTML_MIN_GZ // uncomment for using index.htm & edit.htm from PROGMEM instead of SPIFFS #define USE_HTML_MIN_GZ // uncomment for using index.htm & edit.htm from PROGMEM instead of SPIFFS
#define TRANS_COLOR_DELAY 5 // Delay for color transition #define TRANS_COLOR_DELAY 5 // Delay for color transition
#define TRANS_DELAY 10 // Delay for brightness and speed transition #define TRANS_DELAY 10 // Delay for brightness and speed transition
@@ -146,7 +147,7 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod
#define DBG_OUTPUT_PORT Serial // Set debug output port #define DBG_OUTPUT_PORT Serial // Set debug output port
// List of all color modes // List of all color modes
enum MODE {OFF, HOLD, SET, INIT_STRIP}; enum MODE {OFF, HOLD, SET};
MODE mode = SET; // Standard mode that is active when software starts MODE mode = SET; // Standard mode that is active when software starts
MODE prevmode = HOLD; // Do not change MODE prevmode = HOLD; // Do not change
@@ -175,8 +176,6 @@ LEDState back_color = { 0, 0, 0, 0 }; // Store the "2nd color" of the strip u
LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes LEDState xtra_color = { 0, 0, 0, 0 }; // Store the "3rd color" of the strip used in single color modes
bool updateConfig = false; // For WiFiManger custom config and config bool updateConfig = false; // For WiFiManger custom config and config
char last_state[67]; // Keeps the state representation before auto or off mode
bool updateState = false;
// Button handling // Button handling
+262
View File
@@ -0,0 +1,262 @@
#if defined(ENABLE_STATE_SAVE)
Ticker save_state;
Ticker save_seg_state;
Ticker save_conf;
bool updateState = false;
bool updateSegState = false;
void tickerSaveState(){
updateState = true;
}
void tickerSaveConfig(){
updateConfig = true;
}
void tickerSaveSegmentState(){
updateSegState = true;
}
// Write configuration to FS JSON
bool writeConfigFS(bool save){
if (save) {
//FS save
DBG_OUTPUT_PORT.println("Saving config: ");
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
DBG_OUTPUT_PORT.println("Failed!");
save_conf.detach();
updateConfig = false;
return false;
}
DBG_OUTPUT_PORT.println(listConfigJSON());
configFile.print(listConfigJSON());
configFile.close();
save_conf.detach();
updateConfig = false;
return true;
//end save
} else {
DBG_OUTPUT_PORT.println("SaveConfig is false!");
return false;
}
}
// Read search_str to FS
bool readConfigFS() {
//read configuration from FS JSON
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
DBG_OUTPUT_PORT.print("Reading config file... ");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
DBG_OUTPUT_PORT.println("Opened!");
size_t size = configFile.size();
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
configFile.close();
#if defined(ENABLE_MQTT)
const size_t bufferSize = JSON_OBJECT_SIZE(11) + 150;
#else
const size_t bufferSize = JSON_OBJECT_SIZE(7) + 100;
#endif
DynamicJsonDocument jsonBuffer(bufferSize);
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
DBG_OUTPUT_PORT.print("Config: ");
if (!error) {
DBG_OUTPUT_PORT.println("Parsed!");
JsonObject root = jsonBuffer.as<JsonObject>();
serializeJson(root, DBG_OUTPUT_PORT);
DBG_OUTPUT_PORT.println("");
strcpy(HOSTNAME, root["hostname"]);
#if defined(ENABLE_MQTT)
strcpy(mqtt_host, root["mqtt_host"]);
mqtt_port = root["mqtt_port"].as<uint16_t>();
strcpy(mqtt_user, root["mqtt_user"]);
strcpy(mqtt_pass, root["mqtt_pass"]);
#endif
num_segments = constrain(root["ws_seg"].as<uint8_t>(), 1, MAX_NUM_SEGMENTS - 1);
WS2812FXStripSettings.stripSize = constrain(root["ws_cnt"].as<uint16_t>(), 1, MAXLEDS);
char tmp_rgbOrder[5];
strcpy(tmp_rgbOrder, root["ws_rgbo"]);
checkRGBOrder(tmp_rgbOrder);
uint8_t temp_pin;
checkPin((uint8_t) root["ws_pin"]);
WS2812FXStripSettings.fxoptions = constrain(root["ws_fxopt"].as<uint8_t>(), 0, 255) & 0xFE;
transEffect = root["transEffect"].as<bool>();
jsonBuffer.clear();
return true;
} else {
DBG_OUTPUT_PORT.print("Failed to load json config: ");
DBG_OUTPUT_PORT.println(error.c_str());
jsonBuffer.clear();
}
} else {
DBG_OUTPUT_PORT.println("Failed to open /config.json");
}
} else {
DBG_OUTPUT_PORT.println("Coudnt find config.json");
writeConfigFS(true);
}
//end read
return false;
}
bool writeStateFS(bool save){
if (save) {
//save the strip state to FS JSON
DBG_OUTPUT_PORT.print("Saving state: ");
//SPIFFS.remove("/stripstate.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file");
File configFile = SPIFFS.open("/stripstate.json", "w");
if (!configFile) {
DBG_OUTPUT_PORT.println("Failed!");
save_state.detach();
updateState = false;
return false;
}
DBG_OUTPUT_PORT.println(listStateJSON());
configFile.print(listStateJSON());
configFile.close();
char filename[28];
save_state.detach();
updateState = false;
return true;
//end save
} else {
DBG_OUTPUT_PORT.println("SaveState is false!");
return false;
}
}
bool readStateFS() {
//read strip state from FS JSON
if (SPIFFS.exists("/stripstate.json")) {
//file exists, reading and loading
DBG_OUTPUT_PORT.print("Reading state file... ");
File configFile = SPIFFS.open("/stripstate.json", "r");
if (configFile) {
DBG_OUTPUT_PORT.println("Opened!");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
configFile.close();
const size_t bufferSize = JSON_OBJECT_SIZE(3) + 50;
DynamicJsonDocument jsonBuffer(bufferSize);
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
DBG_OUTPUT_PORT.print("Config: ");
if (!error) {
DBG_OUTPUT_PORT.print("Parsed");
JsonObject root = jsonBuffer.as<JsonObject>();
serializeJson(root, DBG_OUTPUT_PORT);
DBG_OUTPUT_PORT.println("");
segment = root["segment"];
mode = static_cast<MODE>(root["mode"].as<uint8_t>());
brightness = root["brightness"];
jsonBuffer.clear();
return true;
} else {
DBG_OUTPUT_PORT.print("Failed to load json config: ");
DBG_OUTPUT_PORT.println(error.c_str());
jsonBuffer.clear();
}
} else {
DBG_OUTPUT_PORT.println("Failed to open \"/stripstate.json\"");
}
} else {
DBG_OUTPUT_PORT.println("Couldn't find \"/stripstate.json\"");
writeStateFS(true);
}
//end read
return false;
}
bool writeSegmentStateFS(bool save, uint8_t seg){
if (save) {
//save the segment state to FS JSON
DBG_OUTPUT_PORT.print("Saving segment state: ");
char filename[28];
snprintf(filename, 28, "/stripstate_segment_%02i.json", seg);
filename[27] = 0x00;
File configFile = SPIFFS.open(filename, "w");
if (!configFile) {
DBG_OUTPUT_PORT.println("Failed!");
save_seg_state.detach();
updateSegState = false;
return false;
}
DBG_OUTPUT_PORT.println(listSegmentStateJSON(seg));
configFile.print(listSegmentStateJSON(seg));
configFile.close();
save_seg_state.detach();
updateSegState = false;
return true;
//end save
} else {
DBG_OUTPUT_PORT.println("SaveSegmentState is false!");
return false;
}
}
bool readSegmentStateFS(uint8_t seg) {
//read strip state from FS JSON
char filename[28];
snprintf(filename, 28, "/stripstate_segment_%02i.json", seg);
filename[27] = 0x00;
if (SPIFFS.exists(filename)) {
//file exists, reading and loading
DBG_OUTPUT_PORT.printf("Reading segmentstate file: %s\r\n", filename);
File configFile = SPIFFS.open(filename, "r");
if (configFile) {
DBG_OUTPUT_PORT.println("Opened!");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
configFile.close();
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(7) + 100;
DynamicJsonDocument jsonBuffer(bufferSize);
DeserializationError error = deserializeJson(jsonBuffer, buf.get());
DBG_OUTPUT_PORT.print("Config: ");
if (!error) {
DBG_OUTPUT_PORT.print("Parsed");
JsonObject root = jsonBuffer.as<JsonObject>();
serializeJson(root, DBG_OUTPUT_PORT);
DBG_OUTPUT_PORT.println("");
seg_start = root["start"].as<uint16_t>();
seg_stop = root["stop"].as<uint16_t>();
ws2812fx_mode = root["ws2812fx_mode"].as<uint8_t>();
ws2812fx_speed = root["speed"].as<uint8_t>();
main_color.white = root["color"][0].as<uint8_t>();
main_color.red = root["color"][1].as<uint8_t>();
main_color.green = root["color"][2].as<uint8_t>();
main_color.blue = root["color"][3].as<uint8_t>();
back_color.white = root["color"][4].as<uint8_t>();
back_color.red = root["color"][5].as<uint8_t>();
back_color.green = root["color"][6].as<uint8_t>();
back_color.blue = root["color"][7].as<uint8_t>();
xtra_color.white = root["color"][8].as<uint8_t>();
xtra_color.red = root["color"][9].as<uint8_t>();
xtra_color.green = root["color"][10].as<uint8_t>();
xtra_color.blue = root["color"][11].as<uint8_t>();
convertColors();
jsonBuffer.clear();
return true;
} else {
DBG_OUTPUT_PORT.print("Failed to load json config: ");
DBG_OUTPUT_PORT.println(error.c_str());
jsonBuffer.clear();
}
} else {
DBG_OUTPUT_PORT.printf("Failed to open \"/%s\"\r\n", filename);
}
} else {
DBG_OUTPUT_PORT.printf("Couldn't find \"/%s\"", filename);
writeSegmentStateFS(true, seg);
}
//end read
return false;
}
#endif
+283
View File
@@ -0,0 +1,283 @@
// Prototypes
bool readSegmentStateFS(uint8_t seg);
// End Prototypes
uint16_t convertSpeed(uint8_t mcl_speed) {
uint16_t ws2812_speed = 61760 * (exp(0.0002336 * mcl_speed) - exp(-0.03181 * mcl_speed));
ws2812_speed = SPEED_MAX - ws2812_speed;
ws2812_speed = constrain(ws2812_speed, SPEED_MIN, SPEED_MAX);
return ws2812_speed;
}
uint8_t unconvertSpeed(uint16_t ws2812_speed) {
//log((SPEED_MAX - ws2812_speed)/61760) = (0.0002336 * mcl_speed) - (-0.03181 * mcl_speed);
//log((SPEED_MAX - ws2812_speed)/61760) = (0.0002336 + 0.03181) * mcl_speed;
uint16_t mcl_speed = (log((SPEED_MAX - ws2812_speed)/61760))/ (0.0002336 + 0.03181);
//uint16_t mcl_speed = 61760 * (exp(0.0002336 * mcl_speed) - exp(-0.03181 * mcl_speed));
mcl_speed = 255 - mcl_speed;
mcl_speed = constrain(mcl_speed, 0, 255);
return mcl_speed;
}
bool checkPin(uint8_t pin) {
#if defined(USE_WS2812FX_DMA)
#if USE_WS2812FX_DMA == 0
pin = 3;
#endif
#if USE_WS2812FX_DMA == 1
pin = 1;
#endif
#if USE_WS2812FX_DMA == 2
pin = 2;
#endif
#endif
if (((pin >= 0 && pin <= 5) || (pin >= 12 && pin <= 16)) && (pin != WS2812FXStripSettings.pin)) {
WS2812FXStripSettings.pin = pin;
return true;
}
return false;
}
neoPixelType checkRGBOrder(char rgbOrder[5]) {
for( uint8_t i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ;
DBG_OUTPUT_PORT.printf("Checking RGB Order: %s ...", rgbOrder);
neoPixelType returnOrder = 0;
if (strcmp(rgbOrder, "GRB") == 0) {
returnOrder = NEO_GRB;
} else if (strcmp(rgbOrder, "GBR") == 0) {
returnOrder = NEO_GBR;
} else if (strcmp(rgbOrder, "RGB") == 0) {
returnOrder = NEO_RGB;
} else if (strcmp(rgbOrder, "RBG") == 0) {
returnOrder = NEO_RBG;
} else if (strcmp(rgbOrder, "BRG") == 0) {
returnOrder = NEO_BRG;
} else if (strcmp(rgbOrder, "BGR") == 0) {
returnOrder = NEO_BGR;
} else if (strcmp(rgbOrder, "WGRB") == 0) {
returnOrder = NEO_WGRB;
} else if (strcmp(rgbOrder, "WGBR") == 0) {
returnOrder = NEO_WGBR;
} else if (strcmp(rgbOrder, "WRGB") == 0) {
returnOrder = NEO_WRGB;
} else if (strcmp(rgbOrder, "WRBG") == 0) {
returnOrder = NEO_WRBG;
} else if (strcmp(rgbOrder, "WBRG") == 0) {
returnOrder = NEO_WBRG;
} else if (strcmp(rgbOrder, "WBGR") == 0) {
returnOrder = NEO_WBGR;
} else if (strcmp(rgbOrder, "GWRB") == 0) {
returnOrder = NEO_GWRB;
} else if (strcmp(rgbOrder, "GWBR") == 0) {
returnOrder = NEO_GWBR;
} else if (strcmp(rgbOrder, "RWGB") == 0) {
returnOrder = NEO_RWGB;
} else if (strcmp(rgbOrder, "RWBG") == 0) {
returnOrder = NEO_RWBG;
} else if (strcmp(rgbOrder, "BWRG") == 0) {
returnOrder = NEO_BWRG;
} else if (strcmp(rgbOrder, "BWGR") == 0) {
returnOrder = NEO_BWGR;
} else if (strcmp(rgbOrder, "GRWB") == 0) {
returnOrder = NEO_GRWB;
} else if (strcmp(rgbOrder, "GBWR") == 0) {
returnOrder = NEO_GBWR;
} else if (strcmp(rgbOrder, "RGWB") == 0) {
returnOrder = NEO_RGWB;
} else if (strcmp(rgbOrder, "RBWG") == 0) {
returnOrder = NEO_RBWG;
} else if (strcmp(rgbOrder, "BRWG") == 0){
returnOrder = NEO_BRWG;
} else if (strcmp(rgbOrder, "BGWR") == 0) {
returnOrder = NEO_GRBW;
} else if (strcmp(rgbOrder, "GRBW") == 0) {
returnOrder = NEO_GRBW;
} else if (strcmp(rgbOrder, "GBWR") == 0) {
returnOrder = NEO_GBRW;
} else if (strcmp(rgbOrder, "RGBW") == 0) {
returnOrder = NEO_RGBW;
} else if (strcmp(rgbOrder, "RBGW") == 0) {
returnOrder = NEO_RBGW;
} else if (strcmp(rgbOrder, "BRGW") == 0) {
returnOrder = NEO_BRGW;
} else if (strcmp(rgbOrder, "BGRW") == 0) {
returnOrder = NEO_BGRW;
} else {
DBG_OUTPUT_PORT.print("invalid input!");
uint16_t check = checkRGBOrder(WS2812FXStripSettings.RGBOrder);
if (check != 0) {
returnOrder = static_cast<neoPixelType>(check);
strcpy(rgbOrder, WS2812FXStripSettings.RGBOrder);
} else {
returnOrder = static_cast<neoPixelType>(checkRGBOrder(RGBORDER));
strcpy(rgbOrder, RGBORDER);
}
}
DBG_OUTPUT_PORT.println("success!");
strcpy(WS2812FXStripSettings.RGBOrder, rgbOrder);
return returnOrder;
}
// function to Initialize the strip
void initStrip(uint16_t stripSize = WS2812FXStripSettings.stripSize, char RGBOrder[5] = WS2812FXStripSettings.RGBOrder, uint8_t pin = WS2812FXStripSettings.pin, uint8_t fxoptions = WS2812FXStripSettings.fxoptions ){
DBG_OUTPUT_PORT.println("Initializing strip!");
/*#if defined(USE_WS2812FX_DMA)
if (dma != NULL) {
delete(dma);
}
#endif*/
if (strip != NULL) {
strip->strip_off();
delay(10);
if(strip->isRunning()) strip->stop();
strip->resetSegments();
strip->resetSegmentRuntimes();
delete(strip);
WS2812FXStripSettings.stripSize = stripSize;
strcpy(WS2812FXStripSettings.RGBOrder, RGBOrder);
WS2812FXStripSettings.pin = pin;
WS2812FXStripSettings.fxoptions = fxoptions;
}
if (ledstates != NULL) {
delete(ledstates);
}
ledstates = new uint8_t [WS2812FXStripSettings.stripSize];
#if !defined(LED_TYPE_WS2811)
strip = new WS2812FX(stripSize, pin, checkRGBOrder(RGBOrder) + NEO_KHZ800);
#else
strip = new WS2812FX(stripSize, pin, checkRGBOrder(RGBOrder) + NEO_KHZ400);
#endif
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
strip->init();
#if defined(USE_WS2812FX_DMA)
initDMA(stripSize);
strip->setCustomShow(DMA_Show);
#endif
//parameters: index, start, stop, mode, color, speed, options
for (uint8_t seg=0; seg < num_segments; seg++) {
if (seg != segment) { // Read actual segment last
(readSegmentStateFS(seg)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
strip->setSegment(seg, seg_start, seg_stop , ws2812fx_mode, hex_colors_trans, convertSpeed(ws2812fx_speed), fxoptions);
}
}
//read actual segment last to set all vars correctly
(readSegmentStateFS(segment)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
strip->setSegment(segment, seg_start, seg_stop , ws2812fx_mode, hex_colors_trans, convertSpeed(ws2812fx_speed), fxoptions);
strip->setCustomMode(0, F("Autoplay"), myCustomEffect0);
strip->setCustomMode(1, F("Custom WS"), myCustomEffect1);
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
strip->setCustomMode(2, F("TV"), myCustomEffect2);
strip->setCustomMode(3, F("E1.31"), myCustomEffect3);
strip->setCustomMode(4, F("Fire 2012"), myCustomEffect4);
strip->setCustomMode(5, F("Gradient"), myCustomEffect5);
gReverseDirection = (WS2812FXStripSettings.fxoptions & 128);
DBG_OUTPUT_PORT.print("Number of Segments: ");
DBG_OUTPUT_PORT.println(strip->getNumSegments());
if (e131 != NULL) { delete(e131); }
e131 = new ESPAsyncE131(END_UNIVERSE - START_UNIVERSE + 1);
float universe_leds = 170.0; // a universe has only 512 (0..511) channels: 3*170 or 4*128 <= 512
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) {
//universe_leds = 128.0;
}
float float_enduni = stripSize/universe_leds;
uint8_t END_UNIVERSE = stripSize/universe_leds;
if (float_enduni > END_UNIVERSE) {
END_UNIVERSE = END_UNIVERSE +1;
}
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
if (e131->begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) {// Listen via Multicast
DBG_OUTPUT_PORT.println(F("Listening for data..."));
} else {
DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***"));
}
#endif
}
// Call convertColors whenever main_color, back_color or xtra_color changes.
void convertColors() {
hex_colors_trans[0] = (uint32_t)(main_color.white << 24) | (main_color.red << 16) | (main_color.green << 8) | main_color.blue;
hex_colors_trans[1] = (uint32_t)(back_color.white << 24) | (back_color.red << 16) | (back_color.green << 8) | back_color.blue;
hex_colors_trans[2] = (uint32_t)(xtra_color.white << 24) | (xtra_color.red << 16) | (xtra_color.green << 8) | xtra_color.blue;
}
uint32_t* convertColors2(uint8_t w, uint8_t r, uint8_t g, uint8_t b, uint8_t w2, uint8_t r2, uint8_t g2, uint8_t b2, uint8_t w3, uint8_t r3, uint8_t g3, uint8_t b3) {
uint32_t hexcolors[3] = {};
hexcolors[0] = (uint32_t)(w << 24) | (r << 16) | (g << 8) | b;
hexcolors[1] = (uint32_t)(w2 << 24) | (r2 << 16) | (g2 << 8) | b2;
hexcolors[2] = (uint32_t)(w3 << 24) | (r3 << 16) | (g3 << 8) | b3;
return hexcolors;
}
void getSegmentParams(uint8_t seg) {
seg_start = strip->getSegment(seg)->start;;
seg_stop = strip->getSegment(seg)->stop;;
ws2812fx_mode = strip->getMode(seg);
main_color.white = ((strip->getColors(seg)[0] >> 24) & 0xFF);
main_color.red = ((strip->getColors(seg)[0] >> 16) & 0xFF);
main_color.green = ((strip->getColors(seg)[0] >> 8) & 0xFF);
main_color.blue = ((strip->getColors(seg)[0]) & 0xFF);
back_color.white = ((strip->getColors(seg)[1] >> 24) & 0xFF);
back_color.red = ((strip->getColors(seg)[1] >> 16) & 0xFF);
back_color.green = ((strip->getColors(seg)[1] >> 8) & 0xFF);
back_color.blue = ((strip->getColors(seg)[1]) & 0xFF);
xtra_color.white = ((strip->getColors(seg)[2] >> 24) & 0xFF);
xtra_color.red = ((strip->getColors(seg)[2] >> 16) & 0xFF);
xtra_color.green = ((strip->getColors(seg)[2] >> 8) & 0xFF);
xtra_color.blue = ((strip->getColors(seg)[2] >> 0) & 0xFF);
}
void calculateColorTransitionSteps() {
//compare all colors and calculate steps
trans_cnt_max = 0;
int calculate_max[4] = {};
for (uint8_t i=0; i<3; i++){
for (uint8_t j=0; j<4; j++) {
calculate_max[j] = ((hex_colors[i] >> ((3-j)*8)) & 0xFF) - ((hex_colors_trans[i] >> ((3-j)*8)) & 0xFF);
calculate_max[j] = abs(calculate_max[j]);
trans_cnt_max = max(trans_cnt_max, calculate_max[j]);
}
}
}
void convertColorsFade() {
if (transEffect) {
if (trans_cnt > 1) {
memcpy(hex_colors, strip->getColors(segment), sizeof(hex_colors));
DBG_OUTPUT_PORT.println("Color transistion aborted. Restarting...!");
trans_cnt = 1;
}
calculateColorTransitionSteps();
}
}
uint32_t scale_wrgb(uint32_t wrgb, uint8_t level) {
uint8_t w = ((wrgb >> 24) & 0xFF) * level / 255;
uint8_t r = ((wrgb >> 16) & 0xFF) * level / 255;
uint8_t g = ((wrgb >> 8) & 0xFF) * level / 255;
uint8_t b = ((wrgb) & 0xFF) * level / 255;
return (w << 24) | (r << 16) | (g << 8) | b;
}
uint32_t trans(uint32_t newcolor, uint32_t oldcolor, uint8_t level) {
level = (level * (255/trans_cnt_max));
newcolor = scale_wrgb(newcolor, level);
oldcolor = scale_wrgb(oldcolor, 255-level);
return newcolor + oldcolor;
}
+465 -459
View File
@@ -1,463 +1,469 @@
#include <pgmspace.h> #include <pgmspace.h>
#define edit_htm_gz_len 5489 #define edit_htm_gz_len 5563
static const char edit_htm_gz[] PROGMEM ={ static const char edit_htm_gz[] PROGMEM ={
0x1f, 0x8b, 0x08, 0x08, 0x10, 0x9c, 0x83, 0x5c, 0x04, 0x00, 0x65, 0x64, 0x1f, 0x8b, 0x08, 0x08, 0x79, 0x1c, 0x96, 0x5d, 0x04, 0x00, 0x65, 0x64,
0x69, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xed, 0x1c, 0x67, 0x7b, 0xf2, 0x69, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xed, 0x1d, 0x6b, 0x57, 0xea,
0x36, 0xf0, 0x7b, 0x7f, 0x85, 0xeb, 0x8e, 0x40, 0x99, 0x21, 0x24, 0x6f, 0x46, 0xf0, 0x7b, 0xcf, 0xe9, 0x7f, 0x48, 0xd3, 0x87, 0x50, 0x9e, 0xa2,
0x66, 0x5b, 0x76, 0x12, 0xa0, 0x84, 0x91, 0x84, 0xa4, 0xeb, 0x31, 0xb6, 0xd7, 0x2a, 0x6a, 0x5b, 0x40, 0x40, 0x45, 0x8a, 0x08, 0x2a, 0xda, 0xd7,
0x00, 0x27, 0xc6, 0x76, 0x6c, 0x13, 0x20, 0x69, 0xfa, 0xdb, 0x7b, 0x92, 0x09, 0xc9, 0x02, 0xd1, 0x90, 0xc4, 0x24, 0x08, 0x7a, 0x6b, 0x7f, 0x7b,
0xbc, 0x07, 0x38, 0xa3, 0xf3, 0x29, 0xef, 0x00, 0x4b, 0x77, 0xa7, 0xbb, 0x67, 0x1f, 0x79, 0x27, 0x10, 0xd4, 0x3e, 0x4f, 0xb9, 0xed, 0x25, 0xec,
0xd3, 0xe9, 0x74, 0x3a, 0x49, 0x3e, 0xfe, 0xbc, 0xda, 0xa9, 0x0c, 0x6e, 0xce, 0xcc, 0xce, 0xcc, 0xce, 0xce, 0xce, 0xce, 0xee, 0xe6, 0x1e, 0x7c,
0x2e, 0x6a, 0xcc, 0xd4, 0x98, 0x49, 0xdf, 0x7e, 0x76, 0x8c, 0xbf, 0x18, 0x76, 0xd4, 0xa9, 0xf5, 0x6f, 0xce, 0xeb, 0xdc, 0xc4, 0x9a, 0x2a, 0xdf,
0x89, 0x93, 0x27, 0x27, 0x2c, 0x92, 0xd9, 0x6f, 0x3f, 0x63, 0x98, 0xe3, 0x7e, 0xfa, 0xc9, 0x01, 0xfe, 0xe6, 0x14, 0x41, 0x1d, 0x1f, 0xf2, 0x48,
0x29, 0xe2, 0x04, 0xfc, 0x03, 0x7e, 0x1a, 0xa2, 0x21, 0xa1, 0x6f, 0xfb, 0xe5, 0xa1, 0x84, 0xe3, 0x0e, 0x26, 0x48, 0x90, 0xc8, 0x13, 0x3c, 0x5b,
0x17, 0x67, 0xf5, 0x7a, 0x9f, 0xa9, 0x09, 0xa2, 0xa1, 0x68, 0xc7, 0x39, 0xb2, 0xa5, 0xa0, 0x6f, 0x7b, 0xe7, 0x27, 0x8d, 0x46, 0x8f, 0xab, 0x4b,
0x52, 0x68, 0x02, 0xe8, 0xc6, 0x4a, 0x42, 0x8c, 0xb1, 0x52, 0xd1, 0x09, 0xb2, 0xa5, 0x19, 0x07, 0x05, 0x52, 0x68, 0x43, 0x98, 0xd6, 0x93, 0x82,
0x6b, 0xa0, 0xa5, 0x91, 0xe3, 0x75, 0x9d, 0x65, 0x66, 0x48, 0x10, 0xb9, 0x38, 0xeb, 0x49, 0x47, 0x87, 0xbc, 0x85, 0x16, 0x56, 0x41, 0x34, 0x4d,
0x13, 0x56, 0xe7, 0x35, 0x44, 0x89, 0x92, 0x4f, 0x96, 0x57, 0x64, 0x0c, 0x9e, 0x9b, 0x22, 0x49, 0x16, 0x0e, 0x79, 0x53, 0x34, 0x10, 0xa3, 0x4b,
0xd3, 0x46, 0xf2, 0x9c, 0x79, 0x86, 0x42, 0xfa, 0x79, 0xca, 0x88, 0xb2, 0x3e, 0x79, 0x51, 0x53, 0x31, 0x50, 0x1b, 0xa9, 0x33, 0xee, 0x23, 0x94,
0x80, 0x96, 0x87, 0xcc, 0x4e, 0x3e, 0x7f, 0x64, 0x97, 0xaa, 0x8a, 0x2e, 0xb2, 0xcf, 0x73, 0x4e, 0x56, 0x25, 0xb4, 0x28, 0x73, 0x5b, 0xc5, 0xe2,
0x1a, 0xa2, 0x22, 0x1f, 0x32, 0xdc, 0x48, 0x57, 0xa4, 0xb9, 0x81, 0x9c, 0xbe, 0x5b, 0xac, 0x6b, 0xa6, 0x6c, 0xc9, 0x9a, 0x5a, 0xe6, 0x84, 0xa1,
0x3a, 0x09, 0x8d, 0x8d, 0x43, 0x66, 0x57, 0x5d, 0x3a, 0x45, 0x23, 0x45, 0xa9, 0x29, 0x33, 0x0b, 0x79, 0x2a, 0x15, 0x34, 0xb2, 0xca, 0xdc, 0x07,
0x13, 0x90, 0x76, 0xc8, 0x6c, 0xab, 0x4b, 0x06, 0xc0, 0x45, 0x81, 0xf9, 0x7d, 0xe1, 0x29, 0x1b, 0x6a, 0x86, 0x84, 0x8c, 0x32, 0xb7, 0xa9, 0x2f,
0xa2, 0x58, 0x2c, 0xba, 0xea, 0x39, 0xfe, 0x7e, 0xa2, 0x29, 0x73, 0x59, 0x38, 0x40, 0x90, 0x25, 0xee, 0xf3, 0xed, 0xed, 0x6d, 0x2f, 0x80, 0x20,
0xc8, 0xf0, 0x8a, 0xa4, 0x00, 0xe4, 0x17, 0xf5, 0x5d, 0xfc, 0xc7, 0x01, 0xde, 0x8f, 0x0d, 0x6d, 0xa6, 0x4a, 0x39, 0x51, 0x53, 0x34, 0x00, 0xfd,
0x11, 0x44, 0x5d, 0x95, 0xb8, 0xd5, 0x21, 0x23, 0x2b, 0x32, 0x72, 0x53, 0xbc, 0xf1, 0x01, 0xff, 0xf1, 0xc0, 0x48, 0xb2, 0xa9, 0x2b, 0xc2, 0x53,
0x5e, 0x66, 0xf4, 0x29, 0x27, 0x28, 0x8b, 0x43, 0x26, 0x0f, 0x7f, 0xb6, 0x99, 0x53, 0x35, 0x15, 0xf9, 0x88, 0x2f, 0x72, 0xe6, 0x44, 0x90, 0xb4,
0xf3, 0xd0, 0x84, 0x36, 0x19, 0x71, 0x09, 0x26, 0x9f, 0x36, 0xff, 0x66, 0x79, 0x99, 0x2b, 0xc2, 0x9f, 0xcd, 0x22, 0xb4, 0x62, 0x8c, 0x87, 0x42,
0x8b, 0x4c, 0xd2, 0xc1, 0x18, 0x83, 0x98, 0x19, 0x5d, 0x7c, 0x42, 0xc0, 0x8a, 0x2b, 0x66, 0xd9, 0x7f, 0xf9, 0x6d, 0x2e, 0xed, 0x41, 0x19, 0x81,
0x4e, 0xc1, 0x64, 0xd2, 0xa9, 0x18, 0x73, 0x33, 0x51, 0x82, 0x56, 0x74, 0xb8, 0x39, 0x53, 0x7e, 0x46, 0xc0, 0x52, 0xc9, 0xe6, 0xd4, 0xad, 0x19,
0x4e, 0xd6, 0x33, 0x3a, 0xd2, 0xc4, 0xb1, 0x0f, 0x60, 0x81, 0xc4, 0xc9, 0x09, 0x53, 0x59, 0x81, 0x86, 0x4c, 0x41, 0x35, 0x73, 0x26, 0x32, 0xe4,
0xd4, 0x38, 0x1c, 0x29, 0x92, 0x60, 0xd5, 0xbc, 0x84, 0x69, 0x70, 0x2e, 0x51, 0x10, 0x62, 0x8e, 0xe4, 0xf1, 0xc4, 0x2a, 0x0f, 0x35, 0x45, 0x72,
0xb9, 0x94, 0x28, 0x89, 0x3a, 0xb4, 0x89, 0x3b, 0xc3, 0xcf, 0xbf, 0xa1, 0xaa, 0x5e, 0x22, 0xb5, 0x39, 0x53, 0xbc, 0x0a, 0x55, 0x64, 0x13, 0x1a,
0xa8, 0xc0, 0xb8, 0x57, 0x79, 0x9e, 0x82, 0x19, 0xa7, 0x4d, 0x44, 0xd9, 0xc6, 0x5d, 0x13, 0x12, 0xc3, 0xd2, 0x74, 0xe0, 0x3f, 0xa0, 0x48, 0x7f,
0x53, 0xa4, 0x72, 0x82, 0x20, 0xca, 0x13, 0x28, 0x5b, 0xc7, 0x01, 0x34, 0xc9, 0x54, 0x30, 0xc6, 0xb2, 0xea, 0x2f, 0xd3, 0x05, 0x49, 0x92, 0xd5,
0x0a, 0x1c, 0x04, 0x3b, 0x4c, 0x43, 0x12, 0x67, 0x88, 0x8f, 0xc8, 0xd5, 0x31, 0x14, 0x2e, 0x67, 0x04, 0x9a, 0xc6, 0x8c, 0x84, 0xbb, 0xd0, 0x40,
0x84, 0x28, 0x67, 0x16, 0xa2, 0x60, 0x4c, 0x0f, 0x99, 0xbd, 0xbc, 0x5b, 0x8a, 0x60, 0xc9, 0x8f, 0xc8, 0xdb, 0x8e, 0xac, 0xe6, 0xe6, 0xb2, 0x64,
0x23, 0xfc, 0x5c, 0xd3, 0xa1, 0x33, 0x00, 0x59, 0x04, 0xb2, 0xda, 0xda, 0x4d, 0xca, 0xdc, 0x4e, 0xd1, 0xa7, 0x1e, 0x71, 0x66, 0x98, 0xd0, 0x3b,
0xd6, 0x74, 0x95, 0x93, 0x5d, 0xed, 0xd1, 0x6e, 0xa4, 0xdd, 0x1c, 0xec, 0x80, 0x2e, 0x03, 0x65, 0x63, 0x45, 0x93, 0xa6, 0x2e, 0xa8, 0xde, 0x46,
0x43, 0x51, 0x96, 0x44, 0x19, 0x65, 0x46, 0x92, 0xc2, 0xdf, 0x87, 0xc8, 0x69, 0xd7, 0xb2, 0xbe, 0x0f, 0xf7, 0xab, 0xac, 0x2a, 0xb2, 0x8a, 0x72,
0xb5, 0xa7, 0x2e, 0x37, 0x48, 0x76, 0x38, 0x55, 0x1e, 0x91, 0xc6, 0x3c, 0x43, 0x45, 0x13, 0xef, 0xa3, 0x24, 0xdc, 0xd1, 0x17, 0x2b, 0x65, 0x2c,
0xbb, 0x2c, 0xc7, 0x6c, 0x6c, 0x3d, 0x86, 0xc9, 0xa6, 0xcd, 0x5e, 0xad, 0x4f, 0xb4, 0x47, 0x64, 0x70, 0x1f, 0x3d, 0x16, 0xc5, 0x1a, 0x5c, 0x81,
0x56, 0xb3, 0x30, 0x6c, 0x34, 0x5d, 0xcf, 0x18, 0x30, 0x32, 0x1e, 0x45, 0xc2, 0x98, 0x75, 0x78, 0xac, 0xd7, 0xeb, 0x0e, 0x8a, 0x8b, 0x68, 0x9a,
0xb4, 0x80, 0x5e, 0x4c, 0xfb, 0x4a, 0x1c, 0xad, 0x3a, 0x1c, 0x47, 0x74, 0x39, 0x0b, 0x86, 0xce, 0xa3, 0x8c, 0xe6, 0xd0, 0xb3, 0x59, 0x7f, 0x09,
0xd8, 0xc6, 0xee, 0x7f, 0xf9, 0x2c, 0xb4, 0x51, 0x51, 0x56, 0xe7, 0x06, 0x51, 0x71, 0x88, 0xef, 0xd5, 0x5d, 0x18, 0x36, 0x0a, 0x57, 0xc8, 0xe8,
0xf3, 0x1c, 0x6b, 0xb0, 0x29, 0x2a, 0xc7, 0x8b, 0xc6, 0x0a, 0x9a, 0xdb, 0xa6, 0x65, 0x55, 0x9f, 0x59, 0xdc, 0xc7, 0x84, 0x23, 0x52, 0xd3, 0x05,
0x40, 0xf4, 0xd9, 0x63, 0xc6, 0x98, 0x0f, 0x6d, 0xc6, 0x49, 0xcc, 0x36, 0x51, 0xb6, 0x9e, 0xa0, 0xd1, 0xd5, 0x94, 0x3f, 0xfa, 0x0d, 0x1d, 0x33,
0x1e, 0x92, 0x57, 0x48, 0x13, 0x38, 0x99, 0x4b, 0x33, 0x25, 0x4d, 0xe4, 0x64, 0x4c, 0x05, 0x85, 0xdb, 0xc4, 0x43, 0xf7, 0x0a, 0x19, 0x92, 0xa0,
0x40, 0xe2, 0x7e, 0x88, 0xf1, 0x67, 0x66, 0xca, 0x53, 0x66, 0x0e, 0x85, 0x0a, 0x59, 0xae, 0x62, 0xc8, 0x02, 0x48, 0xdf, 0x8b, 0x1a, 0x1f, 0xb9,
0x50, 0x21, 0x21, 0xde, 0xf0, 0x1b, 0x32, 0x0c, 0x8c, 0xd1, 0xbd, 0x68, 0xa9, 0xf6, 0x9c, 0x9b, 0x41, 0x29, 0xd4, 0x28, 0x48, 0xb4, 0x42, 0x86,
0xac, 0x03, 0x71, 0x55, 0xc5, 0xd2, 0x43, 0x84, 0x49, 0xe5, 0xf3, 0xe3, 0x0e, 0x83, 0x67, 0x78, 0x2f, 0x5b, 0x4b, 0x61, 0x3c, 0x75, 0x49, 0x75,
0x18, 0x26, 0x1a, 0x49, 0xd1, 0x34, 0x04, 0x87, 0x2e, 0x36, 0x92, 0x8c, 0x12, 0x67, 0x6c, 0xc5, 0xe2, 0x28, 0x99, 0x01, 0xc7, 0x93, 0xb5, 0x8d,
0x80, 0x78, 0x45, 0xe3, 0xa8, 0x96, 0xc1, 0x98, 0x90, 0x26, 0x89, 0x1b, 0xca, 0x25, 0x83, 0xcd, 0x27, 0x27, 0x21, 0x51, 0x33, 0x04, 0xaa, 0x76,
0xf9, 0xa3, 0xfd, 0x94, 0x02, 0xff, 0x3c, 0x42, 0x12, 0x7c, 0xe3, 0x21, 0xb0, 0x33, 0x64, 0x28, 0x72, 0x12, 0x46, 0x69, 0xe7, 0x65, 0xc0, 0xbd,
0x1f, 0x34, 0x03, 0xf2, 0xa7, 0x00, 0x9e, 0x26, 0x16, 0xb5, 0xdf, 0x09, 0x0f, 0x91, 0x02, 0xdf, 0xc4, 0x43, 0x84, 0x0d, 0x84, 0xfc, 0x29, 0x81,
0x15, 0xff, 0x88, 0x89, 0xa5, 0x2e, 0xc2, 0x46, 0x3a, 0xac, 0xf0, 0xf0, 0x77, 0x4a, 0x4a, 0xf1, 0x77, 0x42, 0x29, 0x34, 0xae, 0x92, 0xea, 0x8f,
0x70, 0x84, 0xc6, 0x8a, 0x86, 0x98, 0xe7, 0x37, 0xea, 0x8d, 0xf0, 0x76, 0xb0, 0x93, 0x8d, 0x2a, 0x2c, 0x97, 0x87, 0x68, 0xa4, 0x19, 0x88, 0xfb,
0x08, 0xcc, 0x70, 0x23, 0x09, 0x09, 0xb6, 0xc8, 0x41, 0x72, 0x02, 0x1a, 0xf8, 0x06, 0x3d, 0x12, 0x1e, 0xcb, 0xc0, 0x93, 0x30, 0x54, 0x90, 0x64,
0x73, 0x73, 0xc9, 0x08, 0xb1, 0xcf, 0xec, 0x5e, 0xac, 0x36, 0xf8, 0x29, 0x8b, 0x1f, 0x45, 0x52, 0x42, 0x23, 0x61, 0xa6, 0x58, 0x51, 0x06, 0x9c,
0xe2, 0xef, 0x91, 0x70, 0x28, 0x2b, 0x46, 0xc2, 0x6e, 0x30, 0x19, 0xa9, 0xdf, 0x49, 0xda, 0x90, 0x38, 0x41, 0xe2, 0x3d, 0x92, 0xca, 0xaa, 0x66,
0x16, 0xe2, 0x41, 0x3e, 0x52, 0x2f, 0x6e, 0x7f, 0x32, 0xd7, 0xa4, 0x04, 0xa5, 0x9c, 0x56, 0xd3, 0xf1, 0x3a, 0x22, 0x4e, 0x67, 0x35, 0xf1, 0xf5,
0x2b, 0x70, 0x06, 0x77, 0x28, 0xce, 0xb8, 0x09, 0xca, 0xa9, 0xf2, 0xe4, 0x94, 0xe4, 0xf5, 0x41, 0x33, 0x43, 0x49, 0xf1, 0x92, 0x60, 0x09, 0x65,
0x68, 0xc4, 0xe9, 0x68, 0xaf, 0x98, 0x16, 0xaf, 0xca, 0x9d, 0xde, 0x22, 0x79, 0x2a, 0x8c, 0x51, 0x41, 0x57, 0xc7, 0xfb, 0x43, 0xc1, 0x44, 0x3b,
0xdf, 0x6c, 0x4c, 0x94, 0x12, 0x7c, 0x7e, 0xe8, 0x5f, 0x4e, 0x6b, 0x97, 0xdb, 0x59, 0xf9, 0xaa, 0xda, 0xb9, 0x98, 0x17, 0x5b, 0xcd, 0xb1, 0x56,
0x13, 0xf8, 0x55, 0xc6, 0x8f, 0x95, 0x49, 0xa5, 0x74, 0x83, 0x7f, 0xd4, 0x81, 0xcf, 0x0f, 0xbd, 0xcb, 0x49, 0xfd, 0x72, 0x0c, 0x4f, 0x55, 0xfc,
0x3b, 0x68, 0x71, 0x89, 0x7f, 0x34, 0x86, 0xbd, 0xfa, 0xf5, 0x69, 0x6f, 0xb3, 0x36, 0xae, 0x55, 0x6e, 0xf0, 0x43, 0xa3, 0x83, 0xe6, 0x97, 0xf8,
0x30, 0x2a, 0xdc, 0xe6, 0x85, 0x42, 0x7d, 0x75, 0xdb, 0x2d, 0x97, 0x6f, 0xa1, 0x39, 0xb8, 0x68, 0x5c, 0x1f, 0x5f, 0xf4, 0x87, 0xa5, 0xdb, 0xa2,
0x1b, 0x07, 0xe2, 0x6d, 0xbf, 0x7c, 0x3e, 0xba, 0xae, 0xcb, 0xb7, 0x57, 0x54, 0x6a, 0x3c, 0xdd, 0x76, 0xab, 0xd5, 0xdb, 0xe6, 0x9e, 0x7c, 0xdb,
0xe7, 0xd2, 0xcd, 0x75, 0x6f, 0x97, 0xe7, 0x25, 0xe9, 0x02, 0x23, 0xa8, 0xab, 0x9e, 0x0e, 0xaf, 0x1b, 0xea, 0xed, 0xd5, 0xa9, 0x72, 0x73, 0x7d,
0xcb, 0xf3, 0x5e, 0xad, 0x7e, 0x89, 0x7e, 0xd0, 0x74, 0xa9, 0xbd, 0x3d, 0xf1, 0x41, 0x14, 0x15, 0xe5, 0x1c, 0x23, 0xe8, 0x8b, 0xd3, 0x8b, 0x7a,
0xcf, 0xe7, 0x4b, 0xdd, 0x49, 0x03, 0x5c, 0xf4, 0x8a, 0x93, 0xea, 0xf5, 0xe3, 0x12, 0xfd, 0x60, 0x98, 0x4a, 0x7b, 0x73, 0x56, 0x2c, 0x56, 0xba,
0x4e, 0x33, 0x55, 0x91, 0xce, 0xce, 0x9a, 0xdd, 0xe6, 0xea, 0xe1, 0xf2, 0xe3, 0x26, 0xb8, 0xf7, 0x27, 0x41, 0x69, 0x34, 0x3a, 0xad, 0x4c, 0x4d,
0xaa, 0xfb, 0x38, 0xa8, 0xd5, 0x76, 0xaa, 0xb3, 0xd2, 0xb4, 0xb5, 0x28, 0x39, 0x39, 0x69, 0x75, 0x5b, 0x4f, 0x0f, 0x97, 0x57, 0xdd, 0xc7, 0x7e,
0x4d, 0x2f, 0xf7, 0xbb, 0xb7, 0xca, 0x69, 0xb1, 0x54, 0xe8, 0x16, 0x26, 0xbd, 0xbe, 0x75, 0x34, 0xad, 0x4c, 0xce, 0xe6, 0x95, 0xc9, 0xe5, 0x6e,
0xed, 0x7e, 0x9d, 0xe3, 0x51, 0xb1, 0x5d, 0x31, 0xce, 0xf7, 0xfb, 0x17, 0xf7, 0x56, 0x3b, 0xde, 0xae, 0x94, 0xba, 0xa5, 0x71, 0xbb, 0xd7, 0x10,
0xe5, 0xfa, 0xa2, 0x74, 0xdf, 0x9b, 0x8b, 0xa7, 0x4d, 0xb5, 0xb4, 0xa7, 0x44, 0xb4, 0xdd, 0xae, 0x59, 0xa7, 0xbb, 0xbd, 0xf3, 0x6a, 0x63, 0x5e,
0xf7, 0x7e, 0xc8, 0xb5, 0xe6, 0x9f, 0x9e, 0x1a, 0xbb, 0xe2, 0x76, 0xf1, 0xb9, 0xbf, 0x98, 0xc9, 0xc7, 0x2d, 0xbd, 0xb2, 0x63, 0x5e, 0xfc, 0x50,
0x9e, 0x37, 0xb8, 0xcb, 0x87, 0x5e, 0x63, 0xda, 0x18, 0xca, 0xf3, 0x83, 0x38, 0x9b, 0x7d, 0xf3, 0xdc, 0xfc, 0x20, 0x6f, 0x6e, 0xdf, 0x8b, 0x96,
0x4e, 0xee, 0xc2, 0xf8, 0xd4, 0x7e, 0xd2, 0xdb, 0xe2, 0xbd, 0xf4, 0x58, 0x70, 0xf9, 0x70, 0xd1, 0x9c, 0x34, 0x07, 0xea, 0x6c, 0xaf, 0x53, 0x38,
0x4f, 0x1d, 0x18, 0x85, 0xfb, 0xeb, 0x41, 0xf5, 0x71, 0x75, 0xa6, 0x95, 0xb7, 0xbe, 0x69, 0x3f, 0x9b, 0x6d, 0xf9, 0x5e, 0x79, 0x6c, 0x64, 0xf6,
0xf4, 0x52, 0x9e, 0x6b, 0xf6, 0x7a, 0xe2, 0xf6, 0x20, 0x5f, 0xc9, 0x4d, 0xac, 0xd2, 0xfd, 0x75, 0xff, 0xe8, 0xf1, 0xe9, 0xc4, 0xa8, 0x98, 0x95,
0xcf, 0x8b, 0xad, 0xcb, 0x91, 0xb1, 0x9b, 0xdb, 0xd7, 0x7e, 0x50, 0xaf, 0xa2, 0xd0, 0xba, 0xb8, 0x90, 0x37, 0xfb, 0xc5, 0x5a, 0x61, 0x72, 0xba,
0xaf, 0x24, 0x75, 0xbf, 0xd7, 0xd7, 0x0e, 0xce, 0x8b, 0xf9, 0x51, 0x71, 0x7d, 0x76, 0x39, 0xb4, 0x3e, 0x14, 0x76, 0x8d, 0x1f, 0xf4, 0xeb, 0x2b,
0x7f, 0xbc, 0xac, 0x73, 0x83, 0xee, 0x41, 0x6a, 0x6c, 0xec, 0xd7, 0x6e, 0x45, 0xdf, 0xbd, 0xe8, 0x19, 0x7b, 0xa7, 0xdb, 0xc5, 0xe1, 0xf6, 0xee,
0xf7, 0xda, 0xe7, 0x37, 0xa3, 0x7c, 0xe7, 0x3e, 0x25, 0xc8, 0x37, 0x0d, 0x68, 0xd1, 0x10, 0xfa, 0xdd, 0xbd, 0xcc, 0xc8, 0xda, 0xad, 0xdf, 0xee,
0x75, 0x76, 0x31, 0x19, 0x2e, 0x9a, 0x67, 0xa5, 0xc7, 0xd6, 0x72, 0xff, 0xb4, 0x4f, 0x6f, 0x86, 0xc5, 0xce, 0x7d, 0x46, 0x52, 0x6f, 0x9a, 0xfa,
0xf1, 0x66, 0xc8, 0xef, 0x36, 0x84, 0x76, 0xa9, 0x7b, 0x3e, 0xe9, 0xd6, 0xf4, 0x7c, 0x3c, 0x98, 0xb7, 0x4e, 0x2a, 0x8f, 0x67, 0x8b, 0xdd, 0xc7,
0xee, 0xd5, 0xbb, 0xde, 0x60, 0xba, 0xb3, 0x37, 0xe8, 0x17, 0x2e, 0x53, 0x9b, 0x81, 0xf8, 0xa1, 0x29, 0xb5, 0x2b, 0xdd, 0xd3, 0x71, 0xb7, 0x7e,
0xd5, 0xeb, 0xeb, 0x5c, 0x75, 0xfb, 0xd3, 0xf5, 0xfc, 0x66, 0x32, 0xdb, 0xaf, 0xdf, 0x5d, 0xf4, 0x27, 0x5b, 0x3b, 0xfd, 0x5e, 0xe9, 0x32, 0x73,
0x57, 0x17, 0xe7, 0xab, 0x9b, 0x6d, 0x59, 0xbd, 0xd5, 0x6f, 0x9b, 0x9d, 0x74, 0x7d, 0x5d, 0x38, 0xda, 0xfc, 0xe6, 0x7a, 0x76, 0x33, 0x9e, 0xee,
0xe5, 0xd9, 0xac, 0x73, 0xb5, 0x7d, 0x96, 0x9b, 0x16, 0x53, 0x9d, 0xbd, 0xea, 0xf3, 0xd3, 0xa7, 0x9b, 0x4d, 0x55, 0xbf, 0x35, 0x6f, 0x5b, 0x9d,
0xc7, 0xda, 0x64, 0xb7, 0x51, 0xb9, 0x2d, 0xab, 0x93, 0x59, 0x69, 0x6f, 0xc5, 0xc9, 0xb4, 0x73, 0xb5, 0x79, 0x52, 0x98, 0x6c, 0x67, 0x3a, 0x3b,
0x3a, 0xdc, 0x5f, 0x9c, 0x36, 0x2f, 0x4f, 0xab, 0xbd, 0xf2, 0xb0, 0x7b, 0x8f, 0xf5, 0xf1, 0x87, 0x66, 0xed, 0xb6, 0xaa, 0x8f, 0xa7, 0x95, 0x9d,
0x23, 0xf2, 0xdd, 0xa2, 0x26, 0xf1, 0x3b, 0x83, 0x71, 0xfe, 0xaa, 0xad, 0xc9, 0x60, 0x77, 0x7e, 0xdc, 0xba, 0x3c, 0x3e, 0xba, 0xa8, 0x0e, 0xba,
0xef, 0x57, 0x4f, 0xcb, 0xfd, 0xfd, 0xbd, 0x62, 0xbd, 0x70, 0x53, 0xd7, 0x37, 0xb2, 0xd8, 0xdd, 0x36, 0x14, 0x71, 0xab, 0x3f, 0x2a, 0x5e, 0xb5,
0xd5, 0xbb, 0xc9, 0xe5, 0xcd, 0x5d, 0x73, 0x98, 0x2b, 0x3d, 0xed, 0x4c, 0xcd, 0xdd, 0xa3, 0xe3, 0x6a, 0x6f, 0x77, 0x67, 0xbb, 0x51, 0xba, 0x69,
0x74, 0xa1, 0x2b, 0x14, 0x10, 0x2a, 0x9f, 0x2e, 0x66, 0x42, 0xe3, 0x7a, 0x98, 0xfa, 0xdd, 0xf8, 0xf2, 0xe6, 0xae, 0x35, 0x28, 0x54, 0x9e, 0xb7,
0x78, 0xca, 0x4f, 0xca, 0x8d, 0xfe, 0xfd, 0xed, 0xb0, 0x33, 0x54, 0xa6, 0xc6, 0xa6, 0xd4, 0x95, 0x4a, 0x08, 0x55, 0x8f, 0xe7, 0x53, 0xa9, 0x79,
0x7c, 0x6d, 0x88, 0x46, 0x3d, 0xa5, 0xcb, 0x97, 0x26, 0x77, 0x0f, 0x10, 0x3d, 0x38, 0x16, 0xc7, 0xd5, 0x66, 0xef, 0xfe, 0x76, 0xd0, 0x19, 0x68,
0x36, 0xfd, 0x70, 0x93, 0x2a, 0x5d, 0xad, 0xe6, 0x3b, 0xb7, 0x3b, 0x7a, 0x13, 0xb1, 0x3e, 0x40, 0xc3, 0x0b, 0xad, 0x2b, 0x56, 0xc6, 0x77, 0x0f,
0xa9, 0xf9, 0x30, 0x6e, 0x2a, 0x8d, 0xb6, 0x8e, 0x16, 0x65, 0x54, 0x3b, 0x10, 0x88, 0xfd, 0x70, 0x93, 0xa9, 0x5c, 0x3d, 0xcd, 0xb6, 0x6e, 0xb7,
0xeb, 0x5c, 0x4c, 0xba, 0xcb, 0xe5, 0xc5, 0xf9, 0xd9, 0x1d, 0xdf, 0x38, 0xcc, 0x4a, 0xeb, 0x61, 0xd4, 0xd2, 0x9a, 0x6d, 0x13, 0xcd, 0xab, 0xa8,
0xdd, 0x7b, 0x30, 0x5a, 0xb9, 0x7c, 0x49, 0x28, 0x55, 0x9f, 0x9a, 0x0d, 0x7e, 0xd2, 0x39, 0x1f, 0x77, 0x17, 0x8b, 0xf3, 0xd3, 0x93, 0x3b, 0xb1,
0x79, 0x3e, 0xaf, 0xa6, 0x0a, 0x46, 0xab, 0xf9, 0xa9, 0xbb, 0x5f, 0x9d, 0x79, 0xbc, 0xf3, 0x60, 0x9d, 0x15, 0x8a, 0x15, 0xa9, 0x72, 0xf4, 0xdc,
0x9e, 0x9e, 0x8e, 0x3a, 0xe5, 0xeb, 0x54, 0xb3, 0xf6, 0xc4, 0x9f, 0xb6, 0x6a, 0xaa, 0xb3, 0xd9, 0x51, 0xa6, 0x64, 0x9d, 0xb5, 0xbe, 0xe9, 0xee,
0xe6, 0x37, 0xfc, 0x7e, 0xa1, 0x7d, 0x5f, 0xbb, 0x44, 0xf7, 0x2d, 0x71, 0x1e, 0x4d, 0x8e, 0x8f, 0x87, 0x9d, 0xea, 0x75, 0xa6, 0x55, 0x7f, 0x16,
0x31, 0x7f, 0xbc, 0x3a, 0x4d, 0x4d, 0xe6, 0xdd, 0x72, 0xf7, 0xa9, 0xd3, 0x8f, 0xcf, 0x66, 0x37, 0xe2, 0x6e, 0xa9, 0x7d, 0x5f, 0xbf, 0x44, 0xf7,
0x28, 0x0e, 0x85, 0xd2, 0x68, 0xbf, 0xd6, 0xe1, 0x7b, 0xfc, 0x43, 0xf7, 0x67, 0xf2, 0x7c, 0xf6, 0x78, 0x75, 0x9c, 0x19, 0xcf, 0xba, 0xd5, 0xee,
0xb1, 0x7a, 0x7f, 0x53, 0x10, 0x2b, 0xad, 0xf9, 0xb2, 0x56, 0x39, 0x2f, 0x73, 0xa7, 0xb9, 0x3d, 0x90, 0x2a, 0xc3, 0xdd, 0x7a, 0x47, 0xbc, 0x10,
0xee, 0x9c, 0x2b, 0xa3, 0xf6, 0x50, 0x99, 0x1b, 0x0f, 0x8d, 0x49, 0x95, 0x1f, 0xba, 0x8f, 0x47, 0xf7, 0x37, 0x25, 0xb9, 0x76, 0x36, 0x5b, 0xd4,
0x2b, 0x0c, 0x3e, 0x5d, 0x3e, 0xb4, 0x9a, 0x0b, 0xe3, 0xa0, 0xd9, 0x5b, 0x6b, 0xa7, 0xdb, 0x5b, 0xa7, 0xda, 0xb0, 0x3d, 0xd0, 0x66, 0xd6, 0x43,
0xcd, 0x97, 0xcd, 0xab, 0xf2, 0xea, 0xe1, 0x6a, 0x38, 0x7c, 0x38, 0x53, 0x73, 0x7c, 0x24, 0x94, 0xfa, 0xdf, 0x5c, 0x3e, 0x9c, 0xb5, 0xe6, 0xd6,
0x2a, 0x95, 0xcb, 0x4a, 0xe9, 0x61, 0x7a, 0xd9, 0x11, 0x95, 0xc1, 0x75, 0x5e, 0xeb, 0xe2, 0x69, 0xb6, 0x68, 0x5d, 0x55, 0x9f, 0x1e, 0xae, 0x06,
0xe5, 0x53, 0xa3, 0x38, 0xe8, 0xd6, 0x3a, 0xd5, 0x7c, 0xe9, 0x62, 0x55, 0x83, 0x87, 0x13, 0xad, 0x56, 0xbb, 0xac, 0x55, 0x1e, 0x26, 0x97, 0x1d,
0xc8, 0x7d, 0x6a, 0x14, 0x86, 0xea, 0x7c, 0xfb, 0xbc, 0x98, 0x92, 0x96, 0x59, 0xeb, 0x5f, 0xd7, 0xbe, 0x69, 0x6e, 0xf7, 0xbb, 0xf5, 0xce, 0x51,
0xa8, 0x5b, 0x1c, 0x0c, 0xcb, 0xa3, 0xb3, 0x41, 0x55, 0x55, 0xae, 0x90, 0xb1, 0x72, 0xfe, 0x54, 0x2a, 0x7c, 0xd3, 0x2c, 0x0d, 0xf4, 0xd9, 0xe6,
0x04, 0x96, 0x51, 0xbe, 0xaa, 0x8f, 0x16, 0xf3, 0x5d, 0xa5, 0xdd, 0x3e, 0xe9, 0x76, 0x46, 0x59, 0xa0, 0xee, 0x76, 0x7f, 0x50, 0x1d, 0x9e, 0xf4,
0xbf, 0x2c, 0x4f, 0x95, 0xe1, 0x6a, 0xd7, 0x98, 0x09, 0x3d, 0xbe, 0xbd, 0x8f, 0x74, 0xed, 0x0a, 0x29, 0x60, 0x19, 0xd5, 0xab, 0xc6, 0x70, 0x3e,
0x58, 0xcd, 0x2e, 0x0a, 0x9d, 0x56, 0x97, 0x6b, 0xdd, 0x2d, 0x0f, 0x72, 0xfb, 0xa0, 0xb5, 0xdb, 0xa7, 0x97, 0xd5, 0x89, 0x36, 0x78, 0xfa, 0x60,
0x8f, 0x72, 0x59, 0xd9, 0xbb, 0xda, 0x69, 0xee, 0x89, 0x4f, 0xa5, 0xc1, 0x4d, 0xa5, 0x0b, 0xb1, 0x3d, 0x7f, 0x9a, 0x9e, 0x97, 0x3a, 0x67, 0x5d,
0xac, 0x2f, 0xb7, 0xb9, 0x7c, 0xf5, 0xe1, 0xd3, 0x18, 0x69, 0x67, 0xca, 0xe1, 0xec, 0x6e, 0xb1, 0x57, 0x78, 0x54, 0xab, 0xda, 0xce, 0xd5, 0x56,
0xf4, 0x7c, 0xaa, 0x6d, 0xab, 0xf9, 0xed, 0x27, 0x4d, 0x7a, 0x2a, 0x1e, 0x6b, 0x47, 0x7e, 0xae, 0xf4, 0xa7, 0x3d, 0xb5, 0x2d, 0x14, 0x8f, 0x1e,
0x68, 0xb7, 0xf5, 0x62, 0x07, 0xba, 0xe0, 0xfc, 0x7e, 0x58, 0xd8, 0x79, 0xbe, 0x19, 0x21, 0xe3, 0x44, 0x9b, 0x9c, 0x4e, 0x8c, 0x4d, 0xbd, 0xb8,
0xbc, 0xea, 0x3e, 0xdd, 0xa8, 0xa9, 0xc5, 0xe8, 0xa6, 0x71, 0x95, 0x6b, 0xf9, 0x6c, 0x28, 0xcf, 0xdb, 0x7b, 0xc6, 0x6d, 0x63, 0xbb, 0x03, 0x5d,
0xaa, 0xc3, 0xe6, 0xdd, 0x23, 0x0c, 0xe6, 0x7d, 0x43, 0x3f, 0x6b, 0x56, 0x70, 0x7a, 0x3f, 0x28, 0x6d, 0x3d, 0x5e, 0x75, 0x9f, 0x6f, 0xf4, 0xcc,
0xb4, 0xf6, 0x0f, 0xa5, 0x9b, 0xfa, 0xf2, 0xae, 0xd0, 0x68, 0xf6, 0x77, 0x7c, 0x78, 0xd3, 0xbc, 0x2a, 0xb4, 0xf4, 0x41, 0xeb, 0xee, 0x11, 0x06,
0x6f, 0xaf, 0x97, 0x93, 0x22, 0x5a, 0x34, 0xf5, 0xf3, 0x31, 0xd7, 0x68, 0xf4, 0xae, 0x65, 0x9e, 0xb4, 0x6a, 0x46, 0xfb, 0x87, 0xca, 0x4d, 0x63,
0x9f, 0xdd, 0xec, 0x36, 0x87, 0x0f, 0x17, 0x4f, 0xfb, 0xad, 0x72, 0xf9, 0x71, 0x57, 0x6a, 0xb6, 0x7a, 0x1f, 0x6e, 0xaf, 0x17, 0xe3, 0x6d, 0x34,
0x6e, 0x2f, 0xb5, 0xaa, 0x3e, 0x5e, 0x5d, 0x7c, 0x3a, 0x80, 0x6f, 0x35, 0x6f, 0x99, 0xa7, 0x23, 0xa1, 0xd9, 0x3e, 0xb9, 0xf9, 0xd0, 0x1a, 0x3c,
0x77, 0x50, 0x3f, 0x50, 0xce, 0x96, 0x3b, 0x1d, 0x51, 0x3f, 0xbd, 0x5e, 0x9c, 0x3f, 0xef, 0x9e, 0x55, 0xab, 0x77, 0x3b, 0x99, 0xa7, 0xa3, 0xc7,
0xa0, 0x4f, 0x1d, 0x4e, 0xca, 0x9f, 0x2e, 0x2b, 0x30, 0x88, 0xba, 0x30, 0xab, 0xf3, 0x6f, 0xf6, 0xe0, 0x5b, 0x2f, 0xec, 0x35, 0xf6, 0xb4, 0x93,
0x22, 0x6b, 0x67, 0x5d, 0x18, 0x90, 0xb5, 0x33, 0x18, 0x9a, 0xa4, 0x68, 0xc5, 0x56, 0x47, 0x36, 0x8f, 0xaf, 0xe7, 0xe8, 0x9b, 0x8e, 0xa0, 0x14,
0x0a, 0xff, 0x9d, 0xe1, 0x0a, 0x5a, 0x54, 0x83, 0xc7, 0x29, 0x85, 0x5d, 0x8f, 0x17, 0x35, 0x18, 0x44, 0x5d, 0x18, 0x91, 0xf5, 0x93, 0x2e, 0x0c,
0x54, 0xf7, 0x6b, 0xb9, 0xf2, 0xed, 0xa4, 0x74, 0x91, 0x7f, 0x98, 0x36, 0xc8, 0xfa, 0x09, 0x0c, 0x4d, 0x52, 0x34, 0x81, 0xbf, 0x4e, 0x70, 0x05,
0xef, 0x76, 0xb4, 0x61, 0xe7, 0x53, 0x09, 0x7f, 0x6a, 0x52, 0x7d, 0x70, 0x2d, 0xaa, 0xc3, 0xcf, 0x09, 0x85, 0x9d, 0x1f, 0xed, 0xd6, 0x0b, 0xd5,
0xdf, 0x9f, 0x77, 0x67, 0x95, 0x0a, 0x9b, 0x04, 0x4f, 0x9c, 0xd1, 0x90, 0xdb, 0x71, 0xe5, 0xbc, 0xf8, 0x30, 0x69, 0xdd, 0x6d, 0x19, 0x83, 0xce,
0x8a, 0x38, 0xe3, 0x2d, 0x6e, 0x07, 0x4f, 0x40, 0x71, 0x5d, 0xd1, 0x86, 0x37, 0x15, 0xfc, 0xa9, 0x2b, 0x8d, 0xfe, 0x7d, 0x6f, 0xd6, 0x9d, 0xd6,
0x68, 0x69, 0x4a, 0x03, 0x51, 0x66, 0x7b, 0xcf, 0x1d, 0xb2, 0x11, 0xc8, 0x6a, 0x7c, 0x1a, 0x5c, 0x73, 0xce, 0x40, 0x3a, 0x12, 0xac, 0x57, 0xba,
0xf0, 0x2a, 0x98, 0xf5, 0x0c, 0x91, 0xe7, 0xa4, 0x0c, 0x27, 0x89, 0x13, 0x1e, 0x3c, 0x3b, 0x25, 0x76, 0x47, 0xab, 0x02, 0xad, 0x09, 0x0d, 0x6a,
0x98, 0x99, 0x66, 0xa2, 0x20, 0x48, 0xb1, 0x26, 0x95, 0x50, 0xff, 0x98, 0xb9, 0xcd, 0x1d, 0x5f, 0xcc, 0x47, 0x60, 0x63, 0xea, 0x60, 0x5a, 0xb4,
0x71, 0xc2, 0x92, 0xed, 0x7d, 0x75, 0xb9, 0x31, 0x00, 0x89, 0x12, 0x93, 0x64, 0x51, 0x50, 0x72, 0x82, 0x22, 0x8f, 0x61, 0xd6, 0x9a, 0xca, 0x92,
0x84, 0x69, 0x38, 0x22, 0x61, 0x59, 0x87, 0x57, 0x12, 0x8e, 0x9a, 0x02, 0xa4, 0x24, 0x9d, 0x6c, 0xa2, 0x5d, 0x65, 0xce, 0x8d, 0x65, 0x36, 0x77,
0xf8, 0xa7, 0x54, 0x73, 0x3a, 0xc5, 0xf3, 0x6a, 0x5c, 0xe1, 0xc2, 0xf8, 0xf5, 0x45, 0x92, 0xa0, 0x25, 0x56, 0x62, 0x12, 0xe8, 0xe1, 0x28, 0x86,
0x26, 0x84, 0x32, 0x3b, 0x31, 0x27, 0x66, 0x6b, 0x62, 0x62, 0x52, 0x31, 0xe7, 0x3d, 0x4c, 0x93, 0xd0, 0x96, 0x89, 0x12, 0x9a, 0x78, 0xd9, 0xa4,
0xa6, 0x0e, 0x6f, 0x13, 0x20, 0x44, 0xb0, 0x89, 0xdc, 0x37, 0x0c, 0x0d, 0x8b, 0x67, 0xdf, 0xe4, 0x72, 0x46, 0xf1, 0x4f, 0x48, 0xe5, 0xb6, 0x92,
0x98, 0x18, 0x4e, 0xb8, 0xe3, 0x78, 0x50, 0x00, 0x03, 0x81, 0xd1, 0x0c, 0x4f, 0xe0, 0xf6, 0x9c, 0xc5, 0x65, 0x92, 0xcc, 0x28, 0xfe, 0x66, 0xa8,
0x7f, 0xd3, 0x08, 0x49, 0xd1, 0x98, 0xd1, 0x7c, 0x32, 0x16, 0x97, 0xcc, 0x2c, 0xe1, 0x66, 0x0a, 0x5f, 0x73, 0x34, 0xda, 0xe2, 0x04, 0xe9, 0x4e,
0x37, 0x39, 0x13, 0xe7, 0x7b, 0xb2, 0x70, 0x63, 0xe8, 0xba, 0x8d, 0xe1, 0x10, 0x41, 0x17, 0x1c, 0x04, 0x55, 0x53, 0xfc, 0x4d, 0xa3, 0x2b, 0xcd,
0x64, 0x81, 0x49, 0x58, 0x51, 0x17, 0x0e, 0xe1, 0x05, 0x60, 0x97, 0x47, 0xe0, 0x86, 0xb3, 0xf1, 0x48, 0x5e, 0x70, 0x5f, 0x17, 0x6c, 0xa4, 0xef,
0x19, 0x55, 0x5c, 0x22, 0x29, 0x43, 0x62, 0x99, 0xc3, 0x7c, 0x92, 0xa2, 0xc9, 0x2a, 0x91, 0xa3, 0x8b, 0x44, 0x4e, 0x50, 0x25, 0x2e, 0x65, 0xc7,
0x52, 0x2e, 0x83, 0xb2, 0x39, 0xc5, 0x4e, 0x00, 0xc7, 0xc9, 0x30, 0xdb, 0x6c, 0x78, 0x65, 0x20, 0x01, 0xcf, 0x22, 0xca, 0xe9, 0xf2, 0x02, 0x29,
0x51, 0xe6, 0xcd, 0x12, 0x8b, 0xc3, 0x8c, 0xc9, 0x61, 0xc6, 0xe2, 0x30, 0x39, 0x12, 0xff, 0x94, 0x8b, 0x69, 0x86, 0xcb, 0x78, 0x0d, 0x8b, 0x48,
0x63, 0x72, 0x28, 0xca, 0x63, 0x51, 0x16, 0x0d, 0xc4, 0x6c, 0xeb, 0x44, 0xca, 0x83, 0x11, 0xa0, 0xa0, 0xc2, 0x5c, 0x48, 0x65, 0x60, 0x25, 0x36,
0x50, 0x47, 0x54, 0x93, 0x71, 0x8b, 0xf6, 0x3d, 0x5a, 0x8d, 0x35, 0x6e, 0x97, 0x39, 0xc6, 0x65, 0xce, 0xe6, 0x32, 0xc7, 0xb8, 0x94, 0xd5, 0x91,
0x86, 0xf4, 0xd8, 0xa4, 0x6d, 0x1a, 0x6e, 0x56, 0xc7, 0x9a, 0x32, 0x83, 0xac, 0xca, 0x16, 0xe2, 0x36, 0x4d, 0x5b, 0x5e, 0x57, 0x62, 0xc6, 0xbe,
0x12, 0xa7, 0x32, 0x18, 0x8b, 0xdb, 0x5c, 0xb8, 0x81, 0x0c, 0x25, 0x2e, 0x4d, 0xfe, 0x1e, 0x3d, 0x8d, 0x0c, 0x61, 0x8a, 0xcc, 0xc4, 0xd4, 0x5d,
0x96, 0x23, 0x85, 0xbf, 0xe3, 0xbe, 0x98, 0xab, 0x92, 0xc2, 0x09, 0x64, 0x22, 0x3e, 0x7e, 0x47, 0x86, 0x36, 0x85, 0x22, 0x56, 0x1d, 0x13, 0xdf,
0xf1, 0x11, 0x2b, 0x42, 0xf7, 0xaf, 0xf0, 0x34, 0x3a, 0x36, 0x83, 0x6b, 0x3b, 0xbc, 0xf8, 0xc0, 0x2c, 0x2d, 0x39, 0xa2, 0x4f, 0x9e, 0x90, 0x60,
0xbe, 0xc0, 0xd0, 0x2e, 0xec, 0x47, 0x8e, 0xec, 0x42, 0xd1, 0xae, 0x72, 0x9f, 0xcf, 0x74, 0x45, 0x13, 0x24, 0xb2, 0xb8, 0x49, 0x18, 0xf8, 0x87,
0x84, 0xc8, 0x10, 0x42, 0x64, 0x09, 0x1c, 0x6a, 0xf8, 0xa1, 0x6b, 0x32, 0x96, 0x94, 0x06, 0x1e, 0xc4, 0xab, 0x56, 0x99, 0x6c, 0xa8, 0x97, 0x76,
0x5a, 0x88, 0x17, 0x42, 0xfe, 0x25, 0xd7, 0x17, 0xd8, 0x4a, 0x5e, 0x25, 0xe3, 0xbd, 0x40, 0x69, 0xdb, 0xad, 0x73, 0x05, 0xca, 0x11, 0x5a, 0x64,
0xa5, 0x97, 0xe1, 0x91, 0x62, 0x18, 0xca, 0x2c, 0x5a, 0x52, 0x67, 0x9c, 0xfd, 0x1d, 0x3d, 0x32, 0xa2, 0xd7, 0x7f, 0xb4, 0x14, 0x2f, 0xb8, 0xc2,
0x17, 0xf2, 0x84, 0xe5, 0x40, 0x9f, 0x38, 0xe4, 0x1c, 0xa6, 0x10, 0x49, 0xab, 0xbb, 0xcf, 0xb1, 0xfd, 0xac, 0x29, 0x70, 0x80, 0xf1, 0xa1, 0x66,
0x73, 0xa4, 0x99, 0x2f, 0x54, 0x8d, 0x98, 0xf0, 0x3b, 0x18, 0xb4, 0x7a, 0x59, 0xda, 0x74, 0x99, 0xd0, 0xae, 0x4f, 0x28, 0x15, 0x29, 0xef, 0xa1,
0x22, 0x06, 0xcb, 0x0e, 0x87, 0x0e, 0x2f, 0x2e, 0x16, 0xd6, 0x68, 0x1b, 0x9e, 0xc2, 0x24, 0xc3, 0xcc, 0x21, 0x92, 0x78, 0xc9, 0x72, 0x9f, 0xeb,
0x6b, 0x36, 0x28, 0xda, 0xae, 0x9f, 0xda, 0x71, 0x0e, 0xd6, 0x87, 0x4e, 0x06, 0x31, 0xf2, 0xb7, 0x31, 0x6a, 0x77, 0x4e, 0x22, 0xde, 0x09, 0xa7,
0xde, 0x86, 0xd7, 0x44, 0xd5, 0xb0, 0x32, 0x33, 0xe3, 0xb9, 0xcc, 0x63, 0x61, 0x96, 0x5c, 0x4e, 0x96, 0x75, 0x00, 0xd1, 0x75, 0x58, 0xca, 0x0f,
0xb1, 0x18, 0x18, 0xf8, 0x9c, 0x81, 0xea, 0xa2, 0x84, 0x2e, 0x4d, 0x23, 0x61, 0x8a, 0x07, 0x05, 0xbc, 0x2e, 0x75, 0x93, 0x4a, 0xa2, 0x21, 0xeb,
0x4c, 0x98, 0xe3, 0x26, 0xcd, 0xe0, 0xce, 0x4a, 0x33, 0x54, 0x3b, 0x49, 0x96, 0x93, 0x36, 0x1a, 0xcd, 0x54, 0x11, 0x8b, 0xc8, 0x89, 0x06, 0x4c,
0x87, 0xa1, 0x47, 0x4e, 0x63, 0x96, 0x33, 0xe9, 0xd4, 0x30, 0xd4, 0x23, 0x61, 0xa8, 0x21, 0x2b, 0xe8, 0x92, 0x19, 0x69, 0x8a, 0x0d, 0xb1, 0x2c,
0x77, 0xa1, 0xb9, 0xdc, 0x38, 0x61, 0x04, 0x85, 0x9f, 0x63, 0x0a, 0x59, 0x87, 0x7b, 0x30, 0xcb, 0x51, 0x55, 0xa5, 0x3d, 0x6c, 0x3d, 0x0a, 0x06,
0x4a, 0xbc, 0x46, 0xe9, 0x25, 0x58, 0x52, 0xcf, 0x3a, 0x79, 0x13, 0x8a, 0xb7, 0x98, 0x2a, 0xc7, 0x96, 0xa5, 0xef, 0xfb, 0x4a, 0xd9, 0x72, 0xe6,
0x90, 0xc5, 0xb9, 0x24, 0xc0, 0x62, 0xc7, 0xc0, 0x04, 0xeb, 0xaf, 0x9c, 0x90, 0x93, 0x34, 0x71, 0x86, 0x69, 0xe4, 0x29, 0xf9, 0x3a, 0xa5, 0x98,
0x41, 0xe8, 0x2f, 0xaa, 0x12, 0x06, 0x18, 0x73, 0x92, 0x8e, 0xfc, 0xf5, 0xe2, 0x49, 0x3d, 0xef, 0xcd, 0xe7, 0x90, 0x92, 0x3c, 0x4e, 0x76, 0x01,
0x32, 0x37, 0xc3, 0x75, 0x24, 0xa6, 0x76, 0x90, 0x1d, 0x16, 0x26, 0xc8, 0x1a, 0x3f, 0x02, 0x3e, 0xf8, 0x50, 0xed, 0x14, 0xd6, 0x14, 0xb2, 0xae,
0x30, 0xdb, 0x2f, 0xaf, 0xce, 0x04, 0x4b, 0xb6, 0x64, 0x96, 0x53, 0x55, 0x60, 0x88, 0x91, 0xa0, 0x98, 0x28, 0x04, 0xa0, 0x0a, 0x53, 0x5c, 0x49,
0x24, 0x0b, 0x95, 0xa9, 0x28, 0x09, 0x09, 0x42, 0x29, 0xe9, 0x95, 0x45, 0x82, 0x74, 0x0f, 0xba, 0xcb, 0xc6, 0x18, 0x59, 0x8c, 0x87, 0xea, 0xd3,
0xe5, 0x8c, 0xe9, 0x6b, 0x44, 0xc1, 0xf0, 0x59, 0x51, 0xc0, 0xac, 0xd0, 0x89, 0x64, 0x4b, 0x98, 0xce, 0x0b, 0xba, 0x8e, 0x54, 0xa9, 0x36, 0x91,
0xd1, 0x9c, 0xc1, 0x25, 0xac, 0x17, 0xc0, 0x16, 0x15, 0xaf, 0x0f, 0x7d, 0x15, 0x29, 0x45, 0x48, 0xa5, 0x03, 0x02, 0xe9, 0x82, 0x35, 0x59, 0x4b,
0x75, 0xb6, 0x24, 0x61, 0x78, 0xe6, 0x1a, 0xe8, 0x8a, 0x93, 0xe6, 0x04, 0x1e, 0x8c, 0x90, 0x97, 0x25, 0xcc, 0x0d, 0x1d, 0xf5, 0x39, 0x5c, 0xc2,
0x26, 0xf7, 0x56, 0x51, 0x31, 0x35, 0x9f, 0xa4, 0xa3, 0x39, 0x18, 0xa8, 0x07, 0x20, 0x1c, 0x81, 0xf1, 0x6a, 0x34, 0x58, 0xe9, 0x88, 0x13, 0x89,
0xbc, 0x46, 0x56, 0x0a, 0xe0, 0x16, 0x96, 0x96, 0x64, 0x45, 0x59, 0x46, 0xc9, 0xd6, 0x58, 0x57, 0x82, 0x32, 0x23, 0x40, 0x85, 0x57, 0x0b, 0x8c,
0xda, 0xe9, 0xa0, 0xdd, 0x02, 0xe4, 0x2d, 0x6a, 0x3e, 0x5b, 0x6f, 0xe4, 0xc9, 0x05, 0xe5, 0x1d, 0xce, 0xc0, 0x6c, 0xd5, 0x25, 0x12, 0x53, 0x00,
0x8b, 0x52, 0xf4, 0x71, 0x36, 0xbb, 0x17, 0x44, 0xed, 0x55, 0x8c, 0x11, 0x9f, 0xc8, 0xb4, 0x28, 0x2f, 0xab, 0x2a, 0x32, 0x8e, 0xfb, 0xed, 0x33,
0x0c, 0x2f, 0x5f, 0xed, 0xfb, 0xaa, 0xa8, 0xbd, 0x95, 0x2d, 0x42, 0x2f, 0xc0, 0xde, 0xa0, 0xc6, 0xb4, 0xf1, 0x5a, 0xd6, 0x28, 0xc9, 0x20, 0x73,
0xc0, 0x15, 0x36, 0xd4, 0x57, 0xb2, 0x85, 0x51, 0xfc, 0x7c, 0xe1, 0x41, 0xd3, 0x7b, 0x49, 0x36, 0xd6, 0xe3, 0x8d, 0xa0, 0xf8, 0x59, 0x6b, 0xdf,
0xf7, 0x76, 0xc6, 0x30, 0x45, 0xd2, 0x04, 0xfc, 0xf5, 0x8d, 0xe9, 0x29, 0x1f, 0xc9, 0xc6, 0xab, 0x39, 0x23, 0x04, 0xc3, 0x8c, 0x61, 0xc3, 0x5d,
0x8c, 0xcc, 0x0b, 0x45, 0x37, 0x2e, 0x34, 0x85, 0x47, 0xba, 0xde, 0x43, 0x97, 0x33, 0x8c, 0x13, 0x64, 0x0d, 0x0f, 0xc4, 0x37, 0xf0, 0x86, 0x49,
0x0f, 0x73, 0xa4, 0x1b, 0x09, 0x32, 0x84, 0xed, 0xd1, 0x33, 0x66, 0x12, 0x86, 0x4d, 0xd8, 0x10, 0xe2, 0x59, 0xa3, 0x16, 0xe8, 0xc1, 0x21, 0xf0,
0xe6, 0x20, 0xce, 0x02, 0xfb, 0xc2, 0xaa, 0x6f, 0x70, 0x06, 0x48, 0x75, 0x3e, 0xb6, 0x78, 0x8e, 0x3b, 0x37, 0x90, 0x69, 0x72, 0x35, 0xcb, 0x50,
0xc2, 0x14, 0x4d, 0x38, 0x07, 0xd2, 0x06, 0xd4, 0x01, 0x66, 0xae, 0x33, 0x72, 0x3d, 0x0e, 0x22, 0x1b, 0xc8, 0xaf, 0x3e, 0xa2, 0x2c, 0x2d, 0xb8,
0x9f, 0x9f, 0x60, 0xe7, 0x95, 0x64, 0x38, 0x09, 0x69, 0x20, 0x6f, 0xad, 0x25, 0x05, 0xe0, 0xa3, 0x34, 0x56, 0xd0, 0x9b, 0xc8, 0x23, 0x8b, 0x15,
0xd7, 0xeb, 0xf4, 0x7e, 0x64, 0x53, 0x5e, 0xa8, 0x14, 0xfb, 0x33, 0xc4, 0x1b, 0x48, 0xd2, 0xde, 0x60, 0xa0, 0x86, 0x40, 0x39, 0x0b, 0x38, 0xad,
0x5f, 0x29, 0xa7, 0x0d, 0x5d, 0x55, 0x64, 0x1d, 0x0d, 0xd0, 0x92, 0x0e, 0x09, 0x78, 0x9e, 0x73, 0xcd, 0xb4, 0xce, 0x0d, 0x4d, 0x04, 0xc6, 0x2e,
0x35, 0xe7, 0x83, 0x24, 0xdd, 0x8c, 0x79, 0x9c, 0x0f, 0xf1, 0x3d, 0x80, 0xd0, 0xc3, 0x0c, 0x99, 0x56, 0x2a, 0xed, 0x9b, 0xfa, 0xe5, 0x11, 0x97,
0x34, 0x06, 0xbc, 0xe9, 0x05, 0x18, 0x6d, 0x82, 0x8c, 0x83, 0x47, 0x3c, 0x62, 0x5e, 0x2a, 0x0f, 0x22, 0x4b, 0x4f, 0x3d, 0x0b, 0xe4, 0xe6, 0x0e,
0x00, 0x7c, 0xe8, 0x2f, 0xeb, 0x26, 0xd9, 0xa0, 0xab, 0xa3, 0xc4, 0x3c, 0x0f, 0xb9, 0x6d, 0x1b, 0xd0, 0x05, 0x75, 0x20, 0x4d, 0x00, 0x9a, 0x99,
0x32, 0x9a, 0x3c, 0x42, 0xaf, 0xc8, 0xe0, 0x79, 0x87, 0xed, 0x16, 0x7e, 0xdc, 0x67, 0x87, 0xd8, 0x4f, 0xa7, 0x39, 0x41, 0x41, 0x06, 0x28, 0xa9,
0xb2, 0xb5, 0x76, 0x14, 0x84, 0xcc, 0x2a, 0x32, 0xd1, 0x19, 0x96, 0x14, 0x7e, 0x71, 0xd1, 0xb9, 0xf8, 0x91, 0xcf, 0xf8, 0xa1, 0x32, 0xfc, 0xcf,
0xf1, 0x53, 0xc8, 0xa5, 0x83, 0xe6, 0x22, 0xd4, 0x4e, 0xd1, 0x1d, 0xf3, 0x65, 0xce, 0x2d, 0x04, 0x1d, 0xe9, 0x9a, 0x6a, 0xa2, 0x3e, 0x68, 0x94,
0x81, 0x08, 0x6f, 0x56, 0x05, 0x67, 0x65, 0xb6, 0x56, 0x37, 0x1f, 0x3d, 0xb2, 0xed, 0x7e, 0x90, 0x62, 0xda, 0xd1, 0xa0, 0xfb, 0x21, 0x0e, 0x16,
0xed, 0xd8, 0x40, 0x66, 0x9f, 0x27, 0xa8, 0x53, 0x48, 0x33, 0x6a, 0x38, 0xd0, 0x46, 0x80, 0x39, 0x39, 0x87, 0xd1, 0x98, 0x22, 0x23, 0xfc, 0x11,
0x37, 0x00, 0x93, 0x60, 0x2f, 0x2e, 0x07, 0x00, 0xc1, 0xe6, 0xb0, 0xbf, 0x0f, 0xed, 0x20, 0x81, 0x97, 0x15, 0xf1, 0x46, 0xd8, 0xa7, 0x53, 0x82,
0x66, 0x43, 0xe1, 0x74, 0x4c, 0xca, 0x22, 0x0d, 0x10, 0x41, 0x5d, 0xf9, 0x7e, 0x51, 0x19, 0xab, 0xd0, 0xa9, 0x2a, 0xcc, 0x34, 0x83, 0xf6, 0x19,
0x2c, 0x16, 0xe4, 0xe4, 0x25, 0x91, 0xbf, 0x67, 0x4e, 0x6c, 0x2d, 0x26, 0xfe, 0x65, 0xab, 0xcf, 0xdf, 0xa4, 0x2d, 0x95, 0xa6, 0x12, 0xe5, 0x61,
0x90, 0xcf, 0x8c, 0x5c, 0x1d, 0x93, 0x25, 0x69, 0xfd, 0xce, 0x38, 0xc1, 0x89, 0x91, 0x38, 0x81, 0x7d, 0x0d, 0x50, 0x61, 0x4c, 0x07, 0x50, 0x7c,
0x66, 0xd9, 0x24, 0x98, 0xd2, 0x09, 0x04, 0xaa, 0x49, 0x48, 0x0e, 0x1b, 0xd7, 0xf4, 0xb0, 0x05, 0x4c, 0x8f, 0xc0, 0x27, 0xb3, 0xf6, 0x1a, 0xec,
0x73, 0x4d, 0x76, 0xf1, 0x63, 0x76, 0xc4, 0x9a, 0x5e, 0x35, 0xe7, 0x9c, 0xa7, 0xbf, 0x25, 0x07, 0x8a, 0xf5, 0x7d, 0x8a, 0xfa, 0xbd, 0x2c, 0xa7,
0x2c, 0xf6, 0x28, 0x97, 0x9a, 0x14, 0x0e, 0xf5, 0xe2, 0x1b, 0xf6, 0xaf, 0xc7, 0x30, 0x04, 0x40, 0x29, 0xfe, 0xfc, 0xb2, 0x0f, 0x20, 0x7c, 0x01,
0x65, 0x56, 0x42, 0xf2, 0x04, 0x7c, 0xfc, 0x31, 0x53, 0xb0, 0x78, 0xf4, 0xcf, 0x4e, 0x7c, 0x34, 0xa0, 0x89, 0x89, 0xd9, 0xc4, 0x09, 0x48, 0x58,
0x77, 0x15, 0xf5, 0x3e, 0x0e, 0x8a, 0x97, 0x14, 0xd4, 0x7a, 0x05, 0xfe, 0x67, 0xc1, 0xf1, 0x08, 0xe2, 0x8a, 0x8a, 0x2c, 0xde, 0x73, 0x87, 0x8e,
0x9c, 0x08, 0x4c, 0x5a, 0x0c, 0x00, 0x4a, 0x9c, 0x6e, 0x9c, 0x59, 0xc0, 0x3a, 0x53, 0x28, 0x68, 0x57, 0x9e, 0x6e, 0xca, 0x93, 0x5d, 0x96, 0xce,
0x39, 0x53, 0x3b, 0xf9, 0xb0, 0x86, 0x19, 0xb3, 0x59, 0x8c, 0xa5, 0xcf, 0x28, 0xc5, 0xe7, 0xf9, 0x34, 0xd8, 0xd6, 0x21, 0x04, 0xf4, 0x69, 0xb0,
0x47, 0xba, 0xa1, 0xc1, 0xe4, 0x9e, 0x80, 0x2d, 0x87, 0x30, 0x32, 0x1e, 0x7a, 0x6b, 0x66, 0xa8, 0x5e, 0xa6, 0x58, 0x9f, 0x2c, 0xeb, 0x64, 0x36,
0xa5, 0xbd, 0x84, 0xab, 0xd8, 0xeb, 0xc1, 0x5e, 0xfc, 0x5e, 0x3c, 0x96, 0xd1, 0xe6, 0xb1, 0xe3, 0xbc, 0x34, 0x94, 0x18, 0xb0, 0x97, 0xa0, 0x73,
0xda, 0xe8, 0x5c, 0x8b, 0x4d, 0x42, 0x37, 0xf5, 0x46, 0x05, 0xf0, 0x09, 0x5b, 0x9b, 0x63, 0x05, 0xa9, 0x63, 0x98, 0xd4, 0x0e, 0xb8, 0x92, 0xcd,
0x1b, 0x94, 0xe6, 0xe5, 0xdf, 0x35, 0xcc, 0x48, 0x14, 0x91, 0x66, 0x5c, 0x68, 0xa8, 0xdf, 0xa8, 0x9b, 0x75, 0x71, 0x02, 0xc4, 0xa0, 0xda, 0x2f,
0xe2, 0xfe, 0x98, 0xff, 0x39, 0xed, 0x32, 0x81, 0x75, 0xe3, 0xaf, 0xd3, 0xf7, 0x67, 0x44, 0x6e, 0xda, 0x68, 0x08, 0x52, 0x11, 0x4c, 0xeb, 0xc4,
0x7f, 0xff, 0x00, 0x24, 0x2d, 0x83, 0xdc, 0x54, 0xda, 0xb7, 0xf5, 0x49, 0x86, 0x2e, 0x30, 0x2d, 0x15, 0x23, 0xdb, 0xe6, 0x58, 0xcb, 0x18, 0xcd,
0x84, 0x35, 0x63, 0x48, 0x1a, 0x63, 0xf8, 0xe4, 0x23, 0x91, 0x87, 0x1f, 0x9c, 0x0d, 0x4d, 0xcb, 0x80, 0xe0, 0x26, 0x05, 0x9b, 0x40, 0x51, 0x74,
0x1a, 0xdc, 0x34, 0x00, 0xe6, 0x12, 0xdf, 0x1d, 0xfe, 0x94, 0x4d, 0xfc, 0xfc, 0xca, 0x7b, 0x89, 0x51, 0x76, 0xc0, 0x5b, 0xbf, 0x84, 0xe6, 0xad,
0xf8, 0x4b, 0xf6, 0xe7, 0x54, 0x32, 0xf9, 0xdd, 0x97, 0xb9, 0x2c, 0x5a, 0x64, 0xfa, 0xa3, 0x71, 0x06, 0xb6, 0x10, 0x93, 0x29, 0x90, 0x8a, 0x11,
0x22, 0x3e, 0x61, 0x91, 0x4a, 0xfe, 0xb8, 0xfd, 0xb3, 0x1f, 0x11, 0x97, 0x90, 0x39, 0x4a, 0xa8, 0x97, 0x7f, 0xdf, 0x00, 0x24, 0x71, 0x54, 0x96,
0x13, 0xcc, 0xec, 0x37, 0xc9, 0x9f, 0xb2, 0x04, 0x33, 0x12, 0xcd, 0x11, 0xf3, 0x08, 0xfd, 0x63, 0xf1, 0xe7, 0xac, 0xc7, 0x20, 0x96, 0x8e, 0xcc,
0x06, 0x07, 0x46, 0xca, 0x98, 0x20, 0xe3, 0x71, 0x44, 0xf2, 0xe5, 0x63, 0x4e, 0xef, 0x5d, 0x86, 0x26, 0x69, 0x1d, 0xa4, 0xa7, 0x32, 0xbf, 0xb2,
0x58, 0x9d, 0x08, 0xc1, 0xe1, 0x84, 0x61, 0x2c, 0x81, 0xbf, 0x65, 0xf6, 0x7b, 0xe2, 0x2c, 0x1c, 0x83, 0xd2, 0x30, 0x2b, 0x20, 0x25, 0x09, 0xbe,
0x93, 0x66, 0x8b, 0xe4, 0xcb, 0x3b, 0x62, 0xf6, 0xbd, 0x33, 0x85, 0x5b, 0x42, 0xe0, 0xe0, 0xd1, 0x01, 0xb2, 0x90, 0xfa, 0xae, 0xfc, 0x53, 0x3e,
0x03, 0x7e, 0x91, 0x5f, 0xc2, 0xd8, 0xc1, 0x4a, 0xd8, 0xc4, 0x0d, 0x80, 0xf5, 0xe3, 0x2f, 0xf9, 0x9f, 0x33, 0xe9, 0xf4, 0x77, 0x5f, 0x14, 0xf2,
0x10, 0xb5, 0xb3, 0x78, 0x5b, 0x95, 0x4d, 0x12, 0x14, 0xfa, 0xc4, 0x06, 0x68, 0x81, 0xc4, 0x94, 0x4d, 0x2b, 0xfd, 0xe3, 0xe6, 0xcf, 0x21, 0x4c,
0x67, 0x39, 0x0f, 0xc2, 0x9d, 0x8a, 0x26, 0x26, 0x02, 0x79, 0x9a, 0xb0, 0x5c, 0x41, 0x50, 0xf3, 0x5f, 0xa7, 0x7f, 0xca, 0x13, 0xd4, 0x95, 0x78,
0x51, 0xdc, 0x3a, 0x3f, 0x53, 0x0c, 0x78, 0x1a, 0xf8, 0x1f, 0x90, 0xd6, 0x20, 0x10, 0x8e, 0x0f, 0xb5, 0x11, 0xc1, 0xc6, 0xa3, 0x8b, 0x6c, 0x52,
0x70, 0xef, 0x98, 0x2b, 0x6d, 0x29, 0xc7, 0x32, 0xbf, 0xfd, 0xe6, 0x32, 0x8c, 0x60, 0x1d, 0x27, 0x45, 0x0c, 0x32, 0x0c, 0x64, 0x4b, 0xfd, 0x2d,
0xe2, 0x08, 0x6f, 0xe4, 0x13, 0xce, 0x45, 0x85, 0xd0, 0x48, 0x59, 0x5c, 0xb7, 0x9b, 0x66, 0x6d, 0x92, 0x2f, 0xff, 0x30, 0xda, 0x0d, 0xcc, 0x2a,
0x78, 0x5a, 0xa6, 0x72, 0x45, 0x63, 0x3a, 0x0f, 0xde, 0xce, 0x59, 0xc7, 0x5e, 0x35, 0x84, 0xe4, 0x7e, 0x89, 0x64, 0x09, 0xab, 0x62, 0x25, 0x47,
0x4e, 0x6a, 0x3b, 0x69, 0x37, 0x16, 0x73, 0x09, 0xed, 0x9b, 0xe4, 0x07, 0x00, 0x43, 0xf4, 0xcf, 0xe3, 0xcd, 0x70, 0x3e, 0x4d, 0x70, 0xe8, 0x2f,
0x10, 0x3d, 0x58, 0x81, 0x53, 0xc4, 0x0a, 0xc6, 0x5a, 0x68, 0x9d, 0x44, 0x3e, 0x62, 0x5e, 0xf4, 0x61, 0xdc, 0xe9, 0x68, 0xcc, 0x30, 0xc8, 0xaf,
0x06, 0x5e, 0xac, 0x09, 0xc2, 0x7a, 0x03, 0x40, 0x12, 0x9a, 0xf4, 0x14, 0x31, 0x1f, 0xcb, 0xb2, 0xfb, 0x98, 0xe1, 0xc0, 0x0d, 0xc1, 0xdf, 0x80,
0x65, 0xdd, 0x4a, 0x47, 0x10, 0x1f, 0x5d, 0x58, 0x16, 0x06, 0x80, 0x81, 0xb5, 0x54, 0x04, 0xd7, 0x80, 0x69, 0x63, 0x05, 0x9e, 0xfb, 0xed, 0x37,
0xa8, 0xfa, 0x0f, 0x66, 0xa0, 0xef, 0xce, 0x9a, 0xbc, 0x35, 0x9e, 0xb7, 0x8f, 0x59, 0xc7, 0xf8, 0xaa, 0xa0, 0x84, 0x1e, 0x32, 0x84, 0x48, 0xc6,
0x28, 0x47, 0x44, 0x82, 0x78, 0x02, 0xad, 0x2a, 0x0b, 0x19, 0x7f, 0x13, 0x66, 0xc4, 0xdf, 0x38, 0x15, 0x6e, 0x09, 0xae, 0xfb, 0xc3, 0xdf, 0x4f,
0xb3, 0x20, 0x4a, 0xd8, 0xd4, 0xd2, 0x96, 0x60, 0xa2, 0x64, 0x48, 0x66, 0xcb, 0x38, 0xca, 0x6c, 0xa6, 0x9d, 0xe6, 0xd6, 0xc9, 0x41, 0x04, 0x82,
0x65, 0x2b, 0x99, 0xd5, 0x35, 0xde, 0xec, 0xca, 0x14, 0xfb, 0x9d, 0x55, 0x83, 0x3e, 0x44, 0x1e, 0x76, 0xd0, 0x15, 0xb7, 0xc4, 0xb3, 0x17, 0xa4,
0x7b, 0x62, 0x68, 0x73, 0xf7, 0x82, 0xed, 0x25, 0x92, 0x85, 0x0b, 0xaa, 0x87, 0xb1, 0x51, 0x1b, 0xcf, 0x40, 0xf8, 0x40, 0xcc, 0x49, 0x02, 0x9b,
0xc8, 0xf8, 0x1c, 0xb0, 0xb4, 0xcb, 0x58, 0x68, 0x19, 0x2f, 0x61, 0xb3, 0x0b, 0x4d, 0x5b, 0xb6, 0x14, 0x94, 0xe4, 0x47, 0x2f, 0x9a, 0x8d, 0x02,
0x66, 0xde, 0x12, 0x6b, 0x0d, 0xef, 0x5a, 0xb9, 0x47, 0x8a, 0xd5, 0x91, 0x70, 0x20, 0xb2, 0xf9, 0x03, 0x5b, 0x02, 0x79, 0x13, 0x51, 0xaf, 0x8e,
0x41, 0x48, 0x92, 0xdc, 0x0c, 0x03, 0xf5, 0x06, 0xe2, 0xc7, 0xe2, 0x6c, 0x23, 0x6d, 0xd2, 0xb4, 0xb9, 0x88, 0x80, 0x09, 0x4f, 0xb9, 0x47, 0xda,
0xc2, 0x80, 0x80, 0x27, 0xec, 0x56, 0x8a, 0x48, 0xb8, 0xc5, 0x32, 0x84, 0x5c, 0xc5, 0xdf, 0xc4, 0x48, 0xa8, 0x2a, 0x56, 0x35, 0xb6, 0x21, 0x31,
0xd6, 0x09, 0x3b, 0xe3, 0x96, 0xe6, 0x2e, 0xf6, 0x76, 0x3e, 0xff, 0xd5, 0x9c, 0x1c, 0x49, 0x56, 0x6d, 0xa4, 0xf3, 0xa6, 0x21, 0xb2, 0x6e, 0xcd,
0x11, 0x03, 0xcf, 0x66, 0xba, 0x84, 0x16, 0x58, 0xe9, 0x43, 0x6e, 0x6e, 0xf0, 0xdf, 0xd9, 0xb5, 0x87, 0x96, 0x31, 0xf3, 0xad, 0x6a, 0x5f, 0x96,
0x28, 0x47, 0x76, 0x72, 0x95, 0x26, 0x55, 0x59, 0x26, 0xf7, 0xed, 0xd6, 0xb0, 0x71, 0x4e, 0x35, 0xba, 0x06, 0x17, 0x3c, 0xed, 0x3d, 0x1e, 0x5a,
0x06, 0xe5, 0xe0, 0x81, 0x2d, 0xd5, 0x15, 0x09, 0x56, 0xdd, 0x78, 0x4b, 0xc7, 0x0b, 0xfe, 0x3c, 0xcb, 0x15, 0x63, 0xed, 0xe1, 0xed, 0x43, 0xdf,
0x39, 0x81, 0x93, 0xbb, 0x8e, 0x8e, 0x1c, 0x93, 0xc3, 0xbb, 0xbd, 0xeb, 0xf8, 0xb1, 0xfb, 0x34, 0x0c, 0x4a, 0x32, 0xca, 0x91, 0xb0, 0xfe, 0x25,
0xcc, 0x6d, 0x2e, 0x79, 0xe7, 0x1b, 0x24, 0x79, 0x8c, 0x04, 0x63, 0x27, 0xca, 0x81, 0x3c, 0x1d, 0x73, 0x20, 0xe6, 0x21, 0xbf, 0x91, 0x21, 0x72,
0xfd, 0x7e, 0x9a, 0x23, 0x1c, 0xac, 0x21, 0x2a, 0x89, 0x5e, 0xa2, 0x98, 0x6e, 0xf0, 0x1c, 0x21, 0x76, 0xc8, 0x4f, 0x85, 0x05, 0x3b, 0x7b, 0xb0,
0x8a, 0x87, 0x2c, 0xa5, 0x10, 0x20, 0x2c, 0xea, 0x15, 0x9a, 0xd7, 0x5c, 0x59, 0x2c, 0x7e, 0xb9, 0xcf, 0xc1, 0x6f, 0x96, 0x76, 0xa2, 0x05, 0x76,
0x33, 0xb4, 0x88, 0x90, 0x59, 0x33, 0xff, 0x19, 0x9c, 0x7a, 0x54, 0x59, 0x9e, 0x56, 0x98, 0x59, 0xda, 0xbe, 0x93, 0xd2, 0xa6, 0xa9, 0x6c, 0x9e,
0x78, 0x0f, 0x63, 0x84, 0x40, 0xd2, 0x37, 0xc3, 0x98, 0x6c, 0x05, 0x7c, 0x2b, 0x7c, 0xbb, 0x91, 0x40, 0x45, 0x60, 0xfa, 0x4a, 0x43, 0x53, 0x20,
0x38, 0x01, 0xf6, 0x58, 0x04, 0x7b, 0x8c, 0x53, 0xea, 0xdf, 0x56, 0x14, 0x4d, 0x81, 0x8f, 0x00, 0xa4, 0x70, 0x5a, 0xdd, 0xd5, 0x94, 0xc7, 0x02,
0x49, 0xe2, 0x54, 0x1d, 0x1d, 0xe7, 0xc8, 0x23, 0x7b, 0x14, 0x44, 0xdb, 0xf1, 0xce, 0xfc, 0x32, 0xeb, 0x9b, 0x29, 0x81, 0x99, 0x09, 0x29, 0x3e,
0x1c, 0x3b, 0xc1, 0x27, 0x9e, 0x12, 0x02, 0xf9, 0x0d, 0x87, 0x73, 0x1b, 0x93, 0xc1, 0xe8, 0xe9, 0x90, 0x33, 0x17, 0x08, 0x13, 0x4b, 0xc8, 0x2a,
0x7f, 0xa4, 0x08, 0x2b, 0x17, 0x11, 0xbd, 0xbc, 0xaa, 0x58, 0xfe, 0x24, 0x72, 0x80, 0x2c, 0xa6, 0xe3, 0x23, 0x4c, 0x49, 0x84, 0x49, 0xcb, 0x66,
0xb1, 0xe5, 0x3a, 0x9a, 0xb0, 0x95, 0xb4, 0xe7, 0x47, 0x1c, 0x0e, 0x78, 0x8d, 0xe6, 0x90, 0x97, 0x0c, 0x37, 0x22, 0x69, 0x9e, 0xe5, 0x9a, 0x23,
0xf1, 0x35, 0x34, 0x83, 0xcd, 0x6a, 0x53, 0x51, 0x92, 0x7f, 0x2d, 0x65, 0xe6, 0x28, 0x5d, 0x95, 0xde, 0xc4, 0x1b, 0xa1, 0x90, 0x0e, 0x4e, 0x45,
0x3d, 0x3a, 0xbd, 0x81, 0xd7, 0x60, 0xfa, 0xf4, 0x15, 0xdd, 0x11, 0xd2, 0x8c, 0xb3, 0xb0, 0xa3, 0x27, 0xe0, 0xfe, 0x95, 0xe2, 0x01, 0xde, 0xd5,
0x21, 0x94, 0x86, 0x0f, 0x8a, 0x16, 0x86, 0x69, 0xbe, 0x47, 0x97, 0x7d, 0xf8, 0xb6, 0xa6, 0x29, 0x8a, 0xa0, 0x9b, 0xe8, 0xa0, 0x40, 0x7e, 0xf2,
0x8e, 0xe2, 0x83, 0x68, 0xf1, 0x34, 0x4f, 0x86, 0x0e, 0xe2, 0xc6, 0x1b, 0xfb, 0x11, 0x78, 0x09, 0xc2, 0x2e, 0xf8, 0x24, 0x53, 0x45, 0x38, 0x2f,
0x2d, 0x51, 0xe5, 0x34, 0x28, 0xf8, 0x41, 0x11, 0xc2, 0xf4, 0x8f, 0x29, 0xe4, 0x72, 0xef, 0x10, 0x18, 0x6a, 0xd2, 0x93, 0x87, 0x8a, 0x59, 0x7d,
0x64, 0x79, 0x2c, 0x08, 0x00, 0xb8, 0x83, 0x2d, 0x66, 0x27, 0x49, 0xc8, 0xaa, 0xd9, 0x8e, 0x26, 0xb5, 0xe1, 0x39, 0x56, 0xb2, 0x91, 0x76, 0xe6,
0xbb, 0x75, 0xea, 0x87, 0xfe, 0xb1, 0xf0, 0x73, 0xd2, 0x47, 0x93, 0x44, 0x52, 0x1c, 0x3f, 0xf8, 0xf1, 0x0d, 0x34, 0x85, 0xf3, 0x04, 0x4c, 0x5b,
0xb0, 0x0d, 0x64, 0x10, 0x50, 0x73, 0xc0, 0xff, 0x83, 0xba, 0xdd, 0x9c, 0x4a, 0x68, 0x8d, 0xe6, 0xfc, 0x76, 0x7b, 0x05, 0xaf, 0xee, 0xcc, 0xc9,
0xd2, 0x63, 0x8e, 0x92, 0xda, 0x12, 0xfe, 0x17, 0xfe, 0xb2, 0x31, 0x82, 0x3a, 0xdd, 0x12, 0xd1, 0x31, 0x94, 0x48, 0x10, 0x8c, 0x96, 0x46, 0x75,
0xa7, 0x9c, 0xa3, 0xff, 0x7b, 0xf9, 0x03, 0x7a, 0xd9, 0xe7, 0x74, 0x49, 0xc0, 0x05, 0x5d, 0x52, 0xda, 0xfa, 0x8f, 0xc4, 0x4b, 0xd8, 0x01, 0x64,
0xd2, 0xf2, 0x5d, 0x5e, 0x97, 0x52, 0xf0, 0xc0, 0x90, 0xa2, 0x50, 0xb3, 0x2c, 0x21, 0x61, 0xb4, 0xd2, 0x2c, 0x61, 0xb1, 0x0e, 0x05, 0x3f, 0x68,
0x21, 0xd9, 0x42, 0xdb, 0x6c, 0x02, 0x38, 0xb1, 0xac, 0xc6, 0x4a, 0xd3, 0x52, 0x64, 0x37, 0x60, 0x12, 0x79, 0x11, 0x0b, 0x03, 0x10, 0xde, 0x20,
0xd6, 0xa4, 0x35, 0x3d, 0xef, 0xce, 0xc6, 0xda, 0x02, 0x38, 0xea, 0xa7, 0x8d, 0xdb, 0x4a, 0x13, 0xfa, 0x5e, 0xd5, 0x06, 0xa1, 0x7f, 0x2c, 0xfd,
0xf8, 0xa1, 0x8e, 0x03, 0xa2, 0xd5, 0x0b, 0x9a, 0x04, 0xa6, 0x40, 0x34, 0x9c, 0x0e, 0x12, 0x25, 0x11, 0x70, 0x13, 0x59, 0x04, 0x96, 0x39, 0x81,
0x58, 0x0d, 0xe9, 0x42, 0x13, 0x30, 0x18, 0x55, 0x1f, 0x33, 0xdb, 0x49, 0x7f, 0x56, 0xff, 0xb3, 0xf9, 0x3f, 0xe9, 0xa0, 0xa9, 0x2f, 0xe0, 0x6f,
0x0f, 0xb2, 0x15, 0x43, 0x99, 0x18, 0x3e, 0x5a, 0x64, 0xdc, 0x85, 0xc1, 0xe9, 0x2f, 0x1c, 0x32, 0x78, 0x56, 0xda, 0xff, 0xbf, 0xbb, 0xdf, 0xad,
0x3b, 0x81, 0x73, 0x64, 0x5b, 0x49, 0x2f, 0x4d, 0xa7, 0x97, 0xff, 0x2e, 0xbb, 0x83, 0xfe, 0x98, 0xa4, 0x7f, 0xdf, 0xe6, 0x90, 0x29, 0x09, 0x3f,
0x73, 0x7b, 0x09, 0x24, 0x53, 0x90, 0x84, 0x13, 0x9e, 0xef, 0xb1, 0x30, 0x10, 0x29, 0x8b, 0xb4, 0x20, 0x92, 0x73, 0x75, 0x2c, 0x28, 0x8c, 0x94,
0x93, 0x84, 0x07, 0xc8, 0x2c, 0x0b, 0xb3, 0xb1, 0x2a, 0x44, 0xcc, 0x86, 0xcc, 0x80, 0xec, 0xac, 0x77, 0x5d, 0x59, 0x62, 0x03, 0xde, 0xdc, 0xb6,
0x3d, 0x7d, 0xfb, 0x91, 0x62, 0xa5, 0xb7, 0xe8, 0x28, 0xa6, 0x84, 0xcc, 0x2b, 0x84, 0xdb, 0x0d, 0x94, 0x40, 0xb4, 0x37, 0x81, 0x48, 0xf7, 0x9c,
0xdc, 0xf9, 0x3f, 0x41, 0xa3, 0x91, 0xc1, 0x24, 0x11, 0xeb, 0xbf, 0x11, 0x66, 0xd5, 0x29, 0x14, 0x0d, 0x74, 0xa3, 0x3a, 0x93, 0x41, 0x86, 0xa3,
0x4a, 0x92, 0x90, 0x0d, 0x67, 0x8b, 0x41, 0x24, 0x53, 0xf7, 0xbe, 0xae, 0xf2, 0x03, 0x6e, 0x33, 0xed, 0xc3, 0xb6, 0x83, 0x2e, 0x86, 0x11, 0x24,
0xa1, 0x48, 0x61, 0x3d, 0x8f, 0xcf, 0x2d, 0xdb, 0xfd, 0x1e, 0xc0, 0x89, 0x46, 0x46, 0x62, 0x14, 0x82, 0x1b, 0x76, 0xc7, 0x36, 0x96, 0x0e, 0x12,
0x93, 0xf3, 0x0a, 0x49, 0x42, 0xfe, 0xe3, 0x3c, 0x38, 0xf1, 0x17, 0x54, 0x75, 0xfb, 0xfb, 0x6f, 0xb3, 0xbd, 0x97, 0x70, 0xc6, 0x06, 0x29, 0x38,
0x4f, 0x67, 0xf8, 0x30, 0xd9, 0x1b, 0x14, 0x65, 0x2e, 0xcc, 0xde, 0xaf, 0x75, 0xfc, 0x26, 0x6b, 0x63, 0x34, 0xfc, 0x50, 0xac, 0x30, 0xca, 0xde,
0x2b, 0xd7, 0x2a, 0xef, 0x9f, 0xa7, 0x28, 0x9f, 0xb9, 0xe2, 0xf5, 0xeb, 0x8e, 0x20, 0xd8, 0xb6, 0x9c, 0x49, 0x3e, 0x84, 0x95, 0x2c, 0x9b, 0x46,
0x7b, 0x27, 0x3b, 0x8b, 0x86, 0x07, 0xca, 0x2a, 0x0c, 0x75, 0x46, 0x66, 0x47, 0x36, 0x25, 0xc5, 0x76, 0x24, 0xfe, 0x21, 0x8a, 0x5d, 0x12, 0x82,
0x9d, 0xa5, 0x6a, 0x3f, 0x5e, 0xdc, 0x49, 0xcf, 0xbd, 0xa2, 0xff, 0x07, 0x12, 0xe1, 0xfe, 0x43, 0x01, 0x28, 0x89, 0xf2, 0x70, 0xda, 0x1a, 0xe4,
0x79, 0xa4, 0xff, 0x7d, 0xfc, 0x47, 0x6b, 0x34, 0xdc, 0xc7, 0xeb, 0x53, 0x62, 0xbd, 0x10, 0xec, 0x25, 0x8a, 0x16, 0x39, 0x71, 0xc1, 0xf2, 0xc3,
0x65, 0x51, 0x71, 0xda, 0x49, 0x20, 0xea, 0xe5, 0xd3, 0xb0, 0xea, 0x26, 0x31, 0x82, 0x30, 0x52, 0xa2, 0x0c, 0x5b, 0x44, 0xfa, 0xf3, 0x9f, 0xe8,
0x1b, 0x82, 0xcf, 0x81, 0x2d, 0x8c, 0x47, 0x0a, 0xfe, 0x8a, 0x6c, 0x15, 0xe2, 0x89, 0x1f, 0xa1, 0xda, 0x3a, 0xc1, 0x47, 0x01, 0x5f, 0xa3, 0x2e,
0xc1, 0xc4, 0x47, 0x82, 0x60, 0x01, 0x3c, 0x50, 0x20, 0x5f, 0xef, 0xe3, 0xb6, 0xc0, 0x7b, 0x0f, 0x8d, 0x79, 0xd6, 0x8b, 0xff, 0x48, 0x75, 0x05,
0xdf, 0xa9, 0xf9, 0x2e, 0xb2, 0xe6, 0xd0, 0xa9, 0xb1, 0x7e, 0x98, 0xcd, 0xad, 0x17, 0x2f, 0x88, 0xdf, 0x3c, 0x27, 0xda, 0x44, 0xfc, 0x60, 0x76,
0x39, 0x40, 0xe1, 0x2d, 0xb6, 0xe0, 0x70, 0x44, 0xb0, 0x49, 0xa7, 0xea, 0x69, 0xa4, 0x9f, 0x62, 0x75, 0xb6, 0xca, 0x43, 0x88, 0x89, 0xe7, 0x46,
0xbb, 0xc8, 0xaa, 0xcd, 0x8d, 0x62, 0x28, 0x7f, 0xab, 0x12, 0x6d, 0x0f, 0x6f, 0x9e, 0xe0, 0x9f, 0xe5, 0xac, 0xfe, 0x9f, 0x05, 0xfe, 0x24, 0xc5,
0x65, 0xc1, 0x4c, 0x00, 0x72, 0x08, 0xd9, 0xd5, 0x48, 0x60, 0x7c, 0xe2, 0xc6, 0xcd, 0x02, 0xe6, 0x44, 0x9b, 0xd7, 0xdc, 0xb6, 0x52, 0x88, 0xce,
0xc3, 0x05, 0x7b, 0x43, 0x60, 0x83, 0xd2, 0x38, 0x5a, 0xf7, 0x66, 0xfc, 0x03, 0x59, 0x58, 0xc8, 0x93, 0x4d, 0xd8, 0x8f, 0xe1, 0x3d, 0x95, 0x47,
0x3c, 0x16, 0x12, 0x0e, 0x1f, 0xc8, 0x62, 0x6d, 0x91, 0x6c, 0xd2, 0x7a, 0x0a, 0xbf, 0x4e, 0x52, 0x8c, 0xa0, 0xe2, 0xe3, 0x5c, 0xb0, 0xa2, 0xee,
0x68, 0x53, 0x04, 0xfc, 0x05, 0x1c, 0x6d, 0xa9, 0xcb, 0xf5, 0xe0, 0x54, 0x6b, 0xb0, 0x6d, 0x10, 0x90, 0xc2, 0xad, 0xf9, 0x2e, 0xb6, 0xa6, 0xec,
0x08, 0xf8, 0xdf, 0x06, 0xf6, 0x18, 0xbb, 0x69, 0x49, 0xde, 0x70, 0xc2, 0xd6, 0xd8, 0x0f, 0xac, 0x3d, 0x17, 0x28, 0xa6, 0xc9, 0x33, 0x38, 0xb0,
0x21, 0x12, 0x5c, 0xca, 0xd0, 0x79, 0xc8, 0x49, 0x65, 0x6d, 0x46, 0xf0, 0x12, 0x6e, 0xd3, 0xad, 0xfa, 0x2e, 0xb6, 0x6a, 0x75, 0xab, 0x18, 0x2a,
0xf4, 0xa0, 0x67, 0xf8, 0x3b, 0x68, 0x01, 0x83, 0x24, 0x89, 0x38, 0xe6, 0xd4, 0xac, 0x42, 0x1b, 0x44, 0x79, 0x30, 0x18, 0x00, 0x1d, 0x40, 0x4e,
0xc4, 0x2d, 0x8f, 0x32, 0x1e, 0xeb, 0xc8, 0xb8, 0xc6, 0x15, 0x7e, 0x68, 0x37, 0x1e, 0x1a, 0x1f, 0xc5, 0xf1, 0x00, 0xdf, 0x50, 0xe0, 0xb0, 0x40,
0x9a, 0xa6, 0x0b, 0x03, 0x3f, 0x25, 0x35, 0x11, 0x1a, 0x52, 0xe4, 0x99, 0xae, 0xea, 0xfd, 0xc9, 0x45, 0x9f, 0xad, 0xc4, 0x20, 0x84, 0x12, 0x65,
0x02, 0x77, 0x0a, 0xe0, 0x20, 0x6c, 0xd0, 0x61, 0x78, 0xb4, 0xe4, 0xd8, 0x1b, 0x24, 0x5f, 0xb5, 0x02, 0x9c, 0x89, 0x81, 0xbf, 0x80, 0xa9, 0x0d,
0xcb, 0x31, 0x51, 0x3c, 0xce, 0xb0, 0x3b, 0x65, 0xdf, 0x32, 0x09, 0xda, 0x7d, 0xb1, 0x02, 0x9e, 0x0a, 0x02, 0x7f, 0xbb, 0xd0, 0x3e, 0xd3, 0x67,
0x1b, 0x94, 0xeb, 0xa4, 0xbb, 0xf6, 0x06, 0x30, 0x40, 0xf9, 0x9e, 0x22, 0x36, 0xe5, 0x0f, 0x3d, 0x5c, 0x2a, 0xee, 0x7a, 0x28, 0x10, 0xf1, 0xba,
0x8c, 0x40, 0x3a, 0xc4, 0xe4, 0x1b, 0x66, 0xf0, 0xbf, 0x72, 0xfe, 0xf4, 0xd9, 0xb2, 0x04, 0x18, 0xbe, 0xae, 0xf4, 0xb9, 0x04, 0x17, 0x2f, 0x6c,
0x69, 0xdd, 0xf9, 0xbc, 0xbc, 0xc6, 0x37, 0x39, 0xa9, 0xf7, 0x16, 0xe2, 0x9b, 0x24, 0xe1, 0xc7, 0x1d, 0x7a, 0x65, 0xd2, 0x46, 0x23, 0x13, 0x59,
0xe8, 0xd2, 0x2a, 0x4d, 0x36, 0x5a, 0xd2, 0x0c, 0xbe, 0x1b, 0x15, 0x8c, 0xd7, 0xb8, 0x22, 0x04, 0x4e, 0xf3, 0x81, 0x51, 0xf0, 0xc7, 0xa4, 0x26,
0x44, 0x01, 0xea, 0x35, 0x53, 0x05, 0x80, 0xd3, 0x13, 0x36, 0x89, 0x04, 0x4e, 0x4f, 0x9a, 0x3a, 0xd5, 0xe0, 0x66, 0x09, 0x1c, 0x76, 0x8e, 0xf6,
0x21, 0xce, 0xd0, 0xbd, 0x8d, 0xe4, 0x77, 0x2c, 0x7b, 0x48, 0x4c, 0x2c, 0x22, 0xae, 0xae, 0x5c, 0xdb, 0x39, 0x20, 0x1d, 0x80, 0x33, 0xfc, 0x6e,
0x05, 0x4f, 0x29, 0xb2, 0xc1, 0x04, 0x36, 0xde, 0x52, 0x16, 0x48, 0xab, 0xd9, 0xb7, 0x5c, 0x8a, 0xf6, 0x0a, 0x65, 0x3c, 0xed, 0xad, 0xbd, 0x01,
0xc0, 0xd1, 0xfa, 0x84, 0xdf, 0x92, 0xe8, 0x69, 0xcb, 0x35, 0x2d, 0xe3, 0x0c, 0xe8, 0x03, 0x5f, 0x11, 0x46, 0x20, 0xfd, 0xc2, 0x38, 0x87, 0x89,
0xc9, 0xc4, 0xd3, 0x36, 0xc5, 0xc8, 0x62, 0x05, 0x55, 0xe8, 0xd1, 0x52, 0xfe, 0x2f, 0x9d, 0x63, 0x83, 0xaa, 0x77, 0x3f, 0x2f, 0xeb, 0x7a, 0x2c,
0x73, 0x0b, 0xc9, 0xd3, 0x4e, 0x80, 0x5b, 0x8f, 0x65, 0x13, 0x12, 0x01, 0x37, 0xf1, 0x7f, 0x86, 0x04, 0xba, 0x44, 0xcb, 0x92, 0x5d, 0x9f, 0x2c,
0x90, 0x38, 0xd3, 0x93, 0x37, 0x12, 0x36, 0xd5, 0x90, 0xdc, 0x10, 0xae, 0x87, 0xef, 0xd3, 0x45, 0x44, 0xb0, 0x00, 0xb6, 0xd6, 0x54, 0x02, 0xf0,
0x5a, 0x70, 0xa4, 0xc5, 0x0d, 0x41, 0xa3, 0x0d, 0xbb, 0x2e, 0xac, 0xb3, 0xf4, 0xe8, 0x53, 0x2a, 0x45, 0xc8, 0x73, 0x74, 0x8f, 0x25, 0xfd, 0x1d,
0x80, 0xe2, 0x59, 0x88, 0x2d, 0x9d, 0x69, 0x8e, 0xa0, 0xd8, 0xf9, 0x3a, 0xcf, 0x97, 0x89, 0xbd, 0x65, 0xe0, 0x57, 0x86, 0x6c, 0x79, 0x81, 0xc9,
0x19, 0x51, 0x16, 0xe7, 0xe6, 0x41, 0xb1, 0x55, 0x7a, 0xd2, 0xc9, 0x52, 0x9f, 0x69, 0x73, 0x64, 0xd4, 0xe0, 0x1e, 0x45, 0x2a, 0x64, 0x55, 0xf4,
0xa6, 0x53, 0xaf, 0xc3, 0xf8, 0x80, 0x2d, 0x5f, 0x95, 0x9b, 0x90, 0x93, 0x14, 0xed, 0x92, 0xb6, 0xf1, 0x64, 0xe3, 0x6f, 0x9d, 0xa2, 0xe4, 0xb1,
0xa4, 0x3e, 0x80, 0xb0, 0x89, 0xd1, 0x64, 0x38, 0x4d, 0x92, 0x46, 0xfe, 0xa6, 0x6a, 0xf4, 0xe8, 0x30, 0xdb, 0xd3, 0xf2, 0xb5, 0x14, 0x66, 0xd8,
0x69, 0xd6, 0xbf, 0x69, 0x4d, 0xa0, 0xe3, 0x5b, 0x78, 0x59, 0xe3, 0x60, 0x67, 0xe8, 0x84, 0x46, 0x18, 0x26, 0xd1, 0x04, 0xe6, 0x8f, 0xa1, 0x99,
0x8f, 0xd6, 0x63, 0xe3, 0xd6, 0xcd, 0x92, 0xf7, 0xda, 0x39, 0x46, 0x21, 0x2e, 0xd2, 0x2b, 0xc3, 0x5c, 0x06, 0x48, 0x1b, 0x5d, 0x11, 0x6a, 0x3a,
0x09, 0xaf, 0xd7, 0x1c, 0x3f, 0x63, 0x28, 0x8a, 0x7d, 0xc0, 0x8c, 0x3c, 0xc0, 0x4b, 0x43, 0x41, 0x1b, 0x2a, 0xb1, 0xc1, 0x38, 0x42, 0x32, 0x03,
0xc1, 0x45, 0x46, 0x36, 0x00, 0xf2, 0xfe, 0x21, 0xe4, 0xec, 0x8f, 0xda, 0x05, 0x15, 0xcf, 0x96, 0x8a, 0x8a, 0xf2, 0x78, 0x6b, 0x00, 0x54, 0x7c,
0xb7, 0x77, 0x3e, 0xc7, 0x74, 0xec, 0x5d, 0x52, 0x96, 0xf9, 0xfa, 0x6b, 0x44, 0xcf, 0xa2, 0x39, 0x6a, 0x75, 0x01, 0x4c, 0x18, 0x34, 0xb0, 0x37,
0x47, 0x1d, 0x66, 0xb3, 0xd6, 0x33, 0xe6, 0xce, 0xfa, 0xcd, 0xae, 0x1d, 0xad, 0x0b, 0x63, 0x72, 0x4a, 0x38, 0x08, 0x11, 0x35, 0x7d, 0x32, 0xb6,
0x31, 0x04, 0xef, 0xd5, 0x83, 0x97, 0xd4, 0x87, 0x8d, 0x5e, 0xd8, 0x77, 0xb3, 0x24, 0x31, 0x15, 0x9e, 0x90, 0x83, 0x7b, 0xec, 0x04, 0x7e, 0x2d,
0x07, 0x34, 0x4b, 0x07, 0x7f, 0xfa, 0xe8, 0x26, 0x0d, 0xc5, 0xd8, 0xc9, 0xb3, 0xaf, 0x1a, 0x02, 0x6c, 0x26, 0xfb, 0x0c, 0xdf, 0xbe, 0x5e, 0xf4,
0x27, 0xfa, 0xa4, 0xc0, 0xbc, 0xb5, 0x41, 0xf1, 0x97, 0x67, 0x27, 0x49, 0x76, 0xe3, 0xc7, 0x38, 0x24, 0xb7, 0xb6, 0xd6, 0x69, 0x41, 0x8e, 0xe2,
0xcb, 0xaf, 0x19, 0xdc, 0x58, 0xdc, 0x98, 0xbe, 0xeb, 0xf3, 0xf5, 0xc2, 0x38, 0xc7, 0x01, 0xc9, 0x2f, 0xb8, 0x15, 0xcb, 0x87, 0x61, 0xde, 0x61,
0xd9, 0xb5, 0x4e, 0x86, 0xf7, 0x6f, 0x48, 0xcf, 0x92, 0xf6, 0x23, 0xdd, 0x64, 0xb9, 0x9b, 0xb8, 0xce, 0x65, 0xae, 0xcf, 0x30, 0x21, 0x67, 0x2b,
0xe5, 0x1a, 0x9e, 0x9d, 0x9d, 0x9b, 0xb8, 0xaa, 0xfb, 0xdb, 0xfd, 0xa2, 0x97, 0xe7, 0xbe, 0xfa, 0xca, 0xd5, 0x09, 0x6b, 0xd7, 0xfe, 0x8d, 0xf9,
0x25, 0x6b, 0x9a, 0xf0, 0xed, 0xf3, 0x8c, 0x6f, 0x73, 0x8c, 0x70, 0x04, 0xb3, 0x9f, 0xf9, 0xe5, 0xe3, 0x88, 0x20, 0xae, 0x3f, 0xaa, 0x49, 0x7d,
0xb9, 0x05, 0x2b, 0xb9, 0x04, 0xcd, 0xb0, 0xdb, 0x6b, 0x12, 0x03, 0xcd, 0xe4, 0xb0, 0xc6, 0x47, 0xc9, 0x0e, 0x1d, 0x3d, 0xfc, 0x15, 0xe3, 0x9e,
0xf4, 0xf7, 0x26, 0xa0, 0x28, 0xc9, 0xcd, 0x49, 0x28, 0x09, 0x9c, 0x02, 0xb4, 0x95, 0xe4, 0xf4, 0x01, 0x51, 0x2b, 0x85, 0x16, 0xed, 0x7d, 0x92,
0x69, 0xd1, 0xb2, 0x0d, 0xdf, 0x41, 0x9f, 0x04, 0xd9, 0x9b, 0x04, 0x98, 0xbf, 0x21, 0x23, 0x4a, 0xda, 0x5e, 0x73, 0xd4, 0x63, 0xa9, 0x93, 0xfa,
0xfc, 0x11, 0x7c, 0x1d, 0x03, 0x3c, 0x7c, 0xa7, 0x52, 0xc1, 0x9c, 0x32, 0xb6, 0xcf, 0x56, 0x88, 0xe8, 0x54, 0xbb, 0xd9, 0xe5, 0xbf, 0x25, 0x33,
0x21, 0x62, 0xd1, 0xfa, 0x51, 0xfc, 0xf9, 0x28, 0x14, 0xa0, 0x26, 0x05, 0x4c, 0x38, 0x88, 0x77, 0xa8, 0x2b, 0xf9, 0x26, 0x1b, 0x49, 0x6b, 0xe8,
0x56, 0x89, 0xb8, 0xd8, 0x74, 0xc0, 0x27, 0xd6, 0x71, 0x66, 0xbf, 0xb9, 0xf0, 0x9f, 0xe0, 0x39, 0x6d, 0x99, 0xb3, 0x84, 0xfb, 0xa0, 0xef, 0x7c,
0x9b, 0xb8, 0x40, 0x3e, 0x34, 0x5a, 0x22, 0x24, 0xb0, 0xeb, 0x31, 0x7f, 0xbd, 0xeb, 0x84, 0xc3, 0xe5, 0x67, 0xb0, 0x3c, 0x4c, 0xd1, 0x5c, 0xbf,
0xe2, 0xb8, 0x29, 0x9e, 0x49, 0x5a, 0x74, 0x03, 0x73, 0x94, 0x8f, 0x72, 0xb3, 0xc0, 0xb1, 0xd0, 0xd4, 0x7c, 0x7b, 0xbe, 0x8b, 0x12, 0x4d, 0x90,
0x80, 0xdc, 0xfa, 0x9d, 0x3b, 0x4a, 0x36, 0xc4, 0x44, 0x36, 0x18, 0x84, 0xf3, 0x52, 0xc0, 0x65, 0x90, 0x46, 0x6d, 0x63, 0x09, 0x9e, 0x5d, 0x4a,
0x3f, 0x75, 0xf7, 0xfc, 0x9a, 0xe3, 0x45, 0x18, 0x83, 0x9c, 0x11, 0x7a, 0x91, 0xfd, 0x53, 0x00, 0x2a, 0xee, 0xc3, 0xd7, 0x01, 0x20, 0xc0, 0x77,
0xd3, 0xa1, 0x1c, 0x7d, 0x21, 0x1a, 0x20, 0x36, 0x80, 0x05, 0x7d, 0x0d, 0x26, 0x13, 0x91, 0xd8, 0x26, 0x64, 0x6c, 0x6a, 0x3f, 0xca, 0x3f, 0xef,
0x38, 0x72, 0x38, 0x7c, 0x0d, 0x67, 0xaf, 0x0f, 0x43, 0x6a, 0xc8, 0xa9, 0x47, 0x43, 0xd4, 0x95, 0xf0, 0xea, 0x13, 0x97, 0x33, 0x37, 0x7d, 0x68,
0x9d, 0xe8, 0x1a, 0x29, 0xa2, 0xea, 0x4e, 0x8f, 0xac, 0x50, 0xe4, 0x88, 0x1f, 0x54, 0x0f, 0x8d, 0x02, 0x86, 0x0d, 0x2d, 0x44, 0x06, 0x5b, 0x84,
0x2a, 0x3e, 0xaa, 0x99, 0x28, 0x78, 0x55, 0x8d, 0xaa, 0xd1, 0xa3, 0x9a, 0x06, 0xf6, 0x4d, 0xec, 0x11, 0x87, 0x5d, 0x49, 0xed, 0xd4, 0xa6, 0x1c,
0x5f, 0x06, 0x38, 0x76, 0x06, 0x35, 0xf1, 0xb2, 0x71, 0x8e, 0xd1, 0x5a, 0x9a, 0xcf, 0x02, 0xb4, 0xc3, 0x04, 0x57, 0xec, 0x2d, 0x52, 0xc2, 0x91,
0x08, 0xa6, 0x8b, 0xdb, 0xd8, 0xeb, 0x24, 0xa6, 0xfc, 0x67, 0x76, 0x3b, 0x36, 0xb3, 0xda, 0x42, 0x82, 0x59, 0xc3, 0x8f, 0x6b, 0x1d, 0x9c, 0xc2,
0x5c, 0xb5, 0x8d, 0xea, 0x28, 0x35, 0xaa, 0x66, 0x22, 0x8e, 0x23, 0x6a, 0x28, 0xe4, 0xf0, 0xd3, 0x2b, 0x4f, 0x1a, 0x99, 0x73, 0xd9, 0x02, 0x05,
0x44, 0x5e, 0xf9, 0x8b, 0xb4, 0x6b, 0x4c, 0x45, 0xdd, 0x7d, 0x12, 0xda, 0x00, 0x5c, 0x84, 0x3f, 0x02, 0xb7, 0x0f, 0xc7, 0xeb, 0xe1, 0x6c, 0x73,
0x35, 0x5d, 0x58, 0x4a, 0xf6, 0x6e, 0x69, 0xf9, 0xf7, 0x87, 0xb6, 0x72, 0x39, 0xaa, 0x8a, 0x1c, 0x46, 0x5a, 0x52, 0xa5, 0xc4, 0xd5, 0xdd, 0x99,
0x5b, 0x64, 0x2f, 0xca, 0x7f, 0xbe, 0x8b, 0xd2, 0x82, 0x5a, 0xda, 0xb0, 0xf1, 0x35, 0x9a, 0x1a, 0x57, 0x27, 0xc6, 0x36, 0x15, 0x8b, 0xa1, 0xeb,
0xff, 0xb0, 0x92, 0x67, 0x42, 0xb5, 0x0a, 0xdd, 0x93, 0x6a, 0x9e, 0x4c, 0xb1, 0x55, 0x66, 0x2c, 0x0f, 0x8b, 0x30, 0xe3, 0xee, 0xb0, 0x27, 0x3e,
0xaa, 0xc1, 0x29, 0xd5, 0x06, 0x4e, 0x93, 0xd8, 0x72, 0xe3, 0xde, 0x32, 0x39, 0xe1, 0xb1, 0x62, 0x1b, 0x87, 0x7a, 0x94, 0x04, 0xbe, 0x82, 0x85,
0x65, 0x84, 0x7c, 0x05, 0x8e, 0x88, 0x05, 0x25, 0x01, 0x7a, 0x1f, 0xba, 0xa9, 0xff, 0x5c, 0x53, 0x80, 0x5b, 0xdb, 0xb1, 0x3d, 0xa7, 0xc7, 0x56,
0xf9, 0xfb, 0xf1, 0xb1, 0x45, 0xd4, 0xc6, 0x6f, 0xf0, 0x14, 0x5b, 0xe8, 0x8d, 0xe5, 0x51, 0x5c, 0x95, 0x2c, 0x6a, 0x7f, 0xad, 0xae, 0xad, 0x89,
0xa1, 0x2d, 0x9c, 0xb9, 0xac, 0x8c, 0xcc, 0xae, 0x0d, 0x98, 0x8a, 0xd3, 0x6c, 0x7a, 0x4f, 0x8b, 0x7b, 0x66, 0x1a, 0x47, 0xe5, 0xfe, 0x5d, 0xb8,
0xf7, 0xa4, 0xf2, 0x2d, 0x07, 0xfa, 0xa3, 0x8f, 0xf4, 0x07, 0x00, 0x99, 0xe0, 0x7e, 0xd6, 0x46, 0x61, 0x83, 0x6c, 0x9e, 0x85, 0x0e, 0xb4, 0x51,
0x8f, 0x3a, 0xe3, 0x1f, 0xe8, 0xfa, 0x37, 0x99, 0x6c, 0x94, 0xe1, 0x7e, 0x6a, 0x50, 0xcd, 0x5a, 0x0f, 0x1e, 0xca, 0xf2, 0x4d, 0xca, 0x76, 0xa1,
0x8c, 0xf9, 0xc6, 0x35, 0xe2, 0x50, 0x79, 0x3e, 0xcc, 0xa0, 0x3f, 0xc8, 0x77, 0x62, 0x2e, 0xd2, 0x89, 0x39, 0x3c, 0x2d, 0x3b, 0xd0, 0x59, 0x12,
0xac, 0xff, 0x2c, 0xe3, 0x8e, 0x65, 0xe2, 0x96, 0xa1, 0xfb, 0x9e, 0x63, 0xb0, 0x26, 0xd8, 0x21, 0xa7, 0xcc, 0x90, 0xaf, 0xd0, 0xa9, 0xb8, 0xb0,
0x78, 0xc4, 0xf0, 0x79, 0xc5, 0x49, 0xd0, 0xdb, 0x67, 0x88, 0xff, 0x8c, 0x38, 0x98, 0xe2, 0xfb, 0x6e, 0x60, 0xff, 0x09, 0x41, 0x4a, 0xfc, 0xe6,
0x0b, 0x1c, 0x64, 0xe0, 0x39, 0x2d, 0x7c, 0xcc, 0x91, 0x72, 0xf3, 0xe6, 0x75, 0xf8, 0xec, 0x5e, 0xcc, 0x19, 0x35, 0x9c, 0x4c, 0xad, 0x0d, 0x59,
0x86, 0x49, 0x75, 0xdd, 0x01, 0xf2, 0x6a, 0xad, 0x55, 0x1b, 0xd4, 0xde, 0x3f, 0x87, 0x6d, 0xc7, 0xb5, 0x04, 0x5a, 0xfb, 0xaa, 0x6b, 0x10, 0xf1,
0x71, 0x84, 0x3c, 0xa8, 0x38, 0x30, 0x99, 0xca, 0xc8, 0x8e, 0xca, 0xff, 0x17, 0x21, 0xc2, 0x90, 0xdc, 0xbb, 0x5d, 0x8d, 0x08, 0xdb, 0xc1, 0xeb,
0x4c, 0x97, 0x92, 0xcb, 0xf1, 0x60, 0x0c, 0x1a, 0xc9, 0x18, 0x81, 0xb5, 0x8c, 0x38, 0xd6, 0x94, 0xdf, 0xc9, 0xa0, 0x13, 0x9b, 0x75, 0xb4, 0x50,
0x6f, 0x74, 0x38, 0x27, 0xd4, 0xe1, 0x44, 0xac, 0x1c, 0xce, 0xfb, 0x9d, 0xef, 0x67, 0xe2, 0xef, 0x65, 0xe8, 0x7f, 0x9a, 0xb9, 0x27, 0x33, 0x7a,
0x1f, 0xb0, 0x69, 0xc3, 0xba, 0x3b, 0xd4, 0xb9, 0xc4, 0xbe, 0x02, 0x14, 0xc7, 0xf4, 0x03, 0x05, 0xc9, 0x9c, 0x66, 0xdc, 0x3c, 0xe4, 0xee, 0x23,
0x50, 0x89, 0x69, 0xba, 0xde, 0x06, 0xe3, 0x1b, 0x93, 0x1b, 0x2b, 0xbe, 0x38, 0xe7, 0xab, 0xff, 0x9c, 0x2b, 0x30, 0x64, 0x3c, 0xba, 0x6d, 0xbc,
0x61, 0x91, 0x6e, 0x88, 0x81, 0x4b, 0xcc, 0xa0, 0x51, 0xa3, 0xd7, 0x08, 0xd7, 0xd1, 0x7b, 0x76, 0xf7, 0x85, 0xd1, 0x5d, 0x7a, 0xd0, 0xfe, 0xa8,
0x70, 0x2c, 0xfe, 0x1d, 0x5c, 0xde, 0x38, 0x61, 0xc9, 0xb1, 0x54, 0x9a, 0x7e, 0x56, 0xef, 0xd7, 0xdf, 0x76, 0xd4, 0x3e, 0x42, 0x83, 0x60, 0x44,
0xc6, 0x8a, 0xb6, 0x09, 0x79, 0x2e, 0xd1, 0x38, 0xdd, 0xe9, 0x11, 0x60, 0xb5, 0xa1, 0x13, 0xf3, 0xff, 0xc9, 0x0e, 0xa7, 0x50, 0x10, 0xc1, 0x3e,
0x42, 0x33, 0xac, 0x1e, 0xf1, 0xaa, 0x25, 0xae, 0xb7, 0xa3, 0x16, 0x42, 0x0c, 0x92, 0xbf, 0x82, 0x31, 0xb0, 0xda, 0x1f, 0x1d, 0x52, 0x7f, 0x14,
0x62, 0x90, 0xa3, 0x0d, 0x67, 0xae, 0xc9, 0xcb, 0xc2, 0xec, 0xdb, 0xa3, 0xb3, 0x36, 0x39, 0xed, 0x75, 0x7e, 0xc0, 0x06, 0x0f, 0x4b, 0xfe, 0x48,
0xd4, 0xe2, 0xd3, 0xe4, 0x45, 0x63, 0x69, 0xc0, 0x87, 0x42, 0xf8, 0x5a, 0xd7, 0xb3, 0xd6, 0xad, 0xaa, 0xb0, 0x6e, 0x98, 0x4d, 0xfb, 0x5b, 0x5d,
0xa9, 0x74, 0xe0, 0x06, 0xcd, 0xb4, 0x05, 0x70, 0x75, 0xb8, 0x83, 0x5d, 0xc3, 0xbc, 0xbc, 0x68, 0x6b, 0x98, 0x1a, 0xe9, 0x91, 0x24, 0xc8, 0xc4,
0xa7, 0xe3, 0xc4, 0x3f, 0xd0, 0x9d, 0x61, 0x48, 0x28, 0x92, 0x7b, 0x92, 0x2c, 0x9a, 0x75, 0x7a, 0xfd, 0x02, 0x47, 0xfa, 0xdf, 0xc1, 0xf5, 0x97,
0x12, 0x27, 0xca, 0xec, 0x87, 0xdc, 0x5b, 0xf8, 0xc0, 0x28, 0x93, 0x2c, 0x43, 0x9e, 0x1c, 0xd4, 0xa5, 0x79, 0xb5, 0x25, 0x36, 0xa2, 0xce, 0x14,
0x2e, 0xfc, 0x3c, 0x32, 0x23, 0xd0, 0xd0, 0xfd, 0x51, 0xd4, 0xca, 0xc2, 0xb6, 0x0c, 0x70, 0x3b, 0x07, 0xf8, 0x30, 0x2c, 0xbb, 0x73, 0x42, 0xea,
0x46, 0xa0, 0xeb, 0x8c, 0xf5, 0xf0, 0x77, 0xba, 0x0b, 0xfc, 0x8e, 0x7b, 0x49, 0xec, 0x13, 0xa9, 0xc9, 0x90, 0x00, 0x66, 0x7f, 0xf5, 0xd9, 0x74,
0xe4, 0xe8, 0xc5, 0xde, 0xf5, 0x48, 0xbc, 0x0b, 0x87, 0xff, 0x15, 0x56, 0xf2, 0x52, 0x3c, 0xe7, 0x1a, 0x32, 0x1d, 0x0b, 0x59, 0xf2, 0x4a, 0xbd,
0x13, 0xeb, 0xc1, 0x01, 0xe0, 0x95, 0x08, 0x91, 0xab, 0x10, 0x3d, 0xba, 0x2c, 0x90, 0x80, 0x42, 0xf8, 0x7a, 0xd2, 0xd9, 0xb0, 0x0e, 0x1b, 0xef,
0x4a, 0x9d, 0xaa, 0x6f, 0x59, 0x6d, 0x29, 0xf2, 0xab, 0x16, 0x3c, 0x54, 0x19, 0x00, 0x36, 0xe0, 0xda, 0x7f, 0x83, 0x0e, 0xa1, 0x90, 0x1f, 0x70,
0x0a, 0xdc, 0xb1, 0x71, 0x7c, 0x86, 0x65, 0xf1, 0x04, 0xcd, 0xe7, 0x5d, 0xc7, 0x28, 0xa1, 0x49, 0x2e, 0xda, 0x2a, 0x82, 0xac, 0xf2, 0xef, 0x74,
0x83, 0xd6, 0x42, 0x2f, 0x82, 0x7a, 0x73, 0x9f, 0x49, 0xb3, 0x14, 0x06, 0xeb, 0xe3, 0x5d, 0xa3, 0x56, 0xb2, 0x80, 0x09, 0xf2, 0xc9, 0x0d, 0x41,
0x12, 0xb9, 0x1d, 0x96, 0xb5, 0xae, 0x82, 0x04, 0xf1, 0x49, 0x23, 0x01, 0x4f, 0xf7, 0xfb, 0xb1, 0x8b, 0x17, 0x07, 0x83, 0x2e, 0x65, 0x56, 0x20,
0xfc, 0xe7, 0xcf, 0xfc, 0xcc, 0x47, 0x8e, 0x8f, 0xe4, 0x46, 0x0e, 0xc9, 0xdc, 0x99, 0x1e, 0xf8, 0x3b, 0xe1, 0x51, 0xa0, 0x57, 0xc5, 0x57, 0x60,
0xc0, 0x0b, 0x34, 0x41, 0x8a, 0xed, 0x8b, 0xc8, 0x33, 0x18, 0xbc, 0x51, 0x89, 0x1e, 0x24, 0xf1, 0x57, 0x58, 0xad, 0xac, 0x80, 0x07, 0x88, 0x75,
0x1c, 0xe2, 0xaf, 0xb5, 0x1c, 0xba, 0x6f, 0x34, 0x43, 0xea, 0xd8, 0x56, 0x31, 0xe2, 0x97, 0x39, 0xe6, 0x92, 0x3a, 0x7d, 0xa2, 0xbf, 0x6e, 0x5d,
0x9b, 0x43, 0xc9, 0x14, 0xd2, 0x36, 0xa4, 0xa4, 0x17, 0x87, 0x0e, 0x91, 0xa7, 0xa9, 0x6b, 0xae, 0xaa, 0xa8, 0x30, 0xb8, 0x97, 0x13, 0x7a, 0x15,
0x80, 0x20, 0xce, 0x88, 0x76, 0xfc, 0x31, 0x76, 0x71, 0x47, 0xee, 0x3a, 0x7b, 0x20, 0x10, 0xcc, 0xb0, 0x27, 0x0e, 0x1b, 0x10, 0xbd, 0x55, 0xec,
0x73, 0xcf, 0x03, 0xaa, 0xe0, 0x8d, 0x0f, 0x59, 0xfc, 0x60, 0xdf, 0x92, 0x4f, 0xd1, 0xa6, 0x59, 0x29, 0x8c, 0x31, 0x72, 0x07, 0x2f, 0x4f, 0x6e,
0xf0, 0xc8, 0x93, 0xcb, 0xa9, 0x70, 0x61, 0xec, 0x5f, 0x7e, 0x51, 0xd6, 0xd5, 0xc4, 0x50, 0x20, 0x2d, 0x05, 0x29, 0xf8, 0x6c, 0x8d, 0x41, 0xc4,
0x35, 0xb1, 0x45, 0x4b, 0x62, 0xbb, 0xb8, 0x34, 0x83, 0xef, 0xb2, 0x11, 0x0e, 0x9c, 0x74, 0x12, 0x3e, 0xc9, 0xa8, 0x0c, 0x35, 0x43, 0x8a, 0x9d,
0x97, 0xfb, 0xa7, 0xc4, 0x4a, 0x7f, 0xc1, 0x2d, 0x3c, 0x8c, 0x51, 0x96, 0x5b, 0xee, 0x53, 0x18, 0xd9, 0xf1, 0x7c, 0xe2, 0xaf, 0xe5, 0x7c, 0x7a,
0x94, 0x51, 0xe2, 0x47, 0x5c, 0x00, 0xd7, 0xf0, 0x9e, 0x89, 0x34, 0x87, 0x6f, 0xcc, 0x43, 0xae, 0xdb, 0x55, 0xa1, 0x4b, 0x8b, 0x09, 0xeb, 0xd8,
0xd4, 0x7e, 0x5e, 0x92, 0xb1, 0x82, 0xaa, 0x0f, 0xb9, 0x95, 0x97, 0xcb, 0x57, 0xda, 0x8f, 0x64, 0x8f, 0xf2, 0xb0, 0x3c, 0xee, 0x90, 0x77, 0xdd,
0xc1, 0x08, 0x8c, 0x0a, 0x25, 0x3e, 0xc8, 0x7a, 0x36, 0xdf, 0x42, 0x8a, 0x37, 0x76, 0x87, 0xfb, 0xbe, 0x4a, 0xb6, 0x75, 0x03, 0x75, 0xf0, 0x2a,
0x71, 0x17, 0xe6, 0x4d, 0x37, 0x6a, 0xac, 0x7b, 0x32, 0xf1, 0x02, 0x36, 0x92, 0x3c, 0xfe, 0xe1, 0x5c, 0x37, 0x09, 0xc8, 0x55, 0x28, 0xe8, 0x70,
0x4a, 0x07, 0x94, 0x46, 0xdf, 0x46, 0x90, 0xd8, 0x68, 0xb7, 0xf4, 0x7c, 0x37, 0xef, 0x3f, 0x70, 0x71, 0xd9, 0x3b, 0x25, 0x2e, 0x11, 0xc7, 0x71,
0x40, 0x00, 0x8f, 0xf5, 0x2d, 0xaa, 0x2c, 0x00, 0x12, 0x46, 0xf6, 0x61, 0x86, 0x59, 0x0e, 0x5f, 0x1d, 0x24, 0xfe, 0xf9, 0x4f, 0x0a, 0xbb, 0xfe,
0x18, 0xd3, 0x90, 0xf4, 0x75, 0x43, 0x80, 0x84, 0x32, 0x53, 0x74, 0xa9, 0x92, 0x8b, 0x8f, 0x18, 0xa5, 0xaa, 0x68, 0xc3, 0xd4, 0x8f, 0xb8, 0x00,
0xd1, 0x23, 0xbd, 0x6f, 0xb1, 0xfa, 0x18, 0x76, 0x1f, 0xe8, 0x73, 0x8c, 0x6e, 0x3e, 0x7e, 0x24, 0x12, 0x95, 0xa9, 0x3d, 0xbd, 0xa4, 0x93, 0xc5,
0xbf, 0x3e, 0x9c, 0xa3, 0x4c, 0xb9, 0x62, 0xb8, 0x78, 0x51, 0x1c, 0x71, 0x67, 0xef, 0x75, 0x11, 0xb2, 0x50, 0x80, 0xc1, 0x19, 0x1b, 0x8c, 0xbc,
0x86, 0x7e, 0x5f, 0xfa, 0xf9, 0x89, 0x1d, 0x59, 0x58, 0xdd, 0x81, 0x7b, 0x9b, 0x2d, 0xad, 0xbe, 0xe4, 0x95, 0xe4, 0x82, 0xd1, 0xab, 0xee, 0x29,
0xbb, 0x0f, 0xfc, 0x10, 0x8d, 0x61, 0x1d, 0xb7, 0x15, 0x01, 0x54, 0x0c, 0x39, 0x97, 0x8f, 0x92, 0xc5, 0x7e, 0x94, 0x10, 0xe8, 0x8e, 0xbe, 0x05,
0x5e, 0x31, 0x37, 0x83, 0x5f, 0xa6, 0x63, 0x76, 0x08, 0xbb, 0x7a, 0x63, 0x23, 0xb5, 0xda, 0x8e, 0xe9, 0x79, 0x88, 0x10, 0x22, 0x1f, 0x5c, 0xb9,
0x00, 0x53, 0x81, 0x09, 0x8a, 0x67, 0x05, 0x0c, 0x4b, 0xbe, 0x83, 0xc0, 0xd9, 0x10, 0x24, 0x28, 0xed, 0xc1, 0xe8, 0xa6, 0x21, 0xee, 0xda, 0x83,
0x5f, 0x12, 0x43, 0xe9, 0x93, 0x03, 0x2f, 0x22, 0x99, 0x97, 0xce, 0xe8, 0x82, 0x44, 0x43, 0x13, 0x74, 0x69, 0xb0, 0x33, 0xd0, 0xaf, 0x1a, 0x07,
0x4b, 0x7a, 0x56, 0x36, 0x68, 0x14, 0x3b, 0x97, 0x3a, 0xea, 0x2b, 0x63, 0x09, 0x46, 0x42, 0xa8, 0xfb, 0x09, 0x81, 0xe5, 0x91, 0x21, 0xe5, 0xcb,
0x63, 0x00, 0xef, 0x50, 0x49, 0x10, 0x15, 0x6c, 0xc4, 0x00, 0xd0, 0x3e, 0x1b, 0x0e, 0x26, 0x0c, 0x08, 0x99, 0xbb, 0x0c, 0x3a, 0xdc, 0xcf, 0x0e,
0x24, 0xbf, 0x13, 0x85, 0x50, 0xa6, 0x4f, 0xe1, 0x90, 0x84, 0x04, 0xff, 0x9d, 0xc8, 0xc4, 0xee, 0x1a, 0xdc, 0xf5, 0x3d, 0x60, 0x8a, 0xe8, 0x0e,
0x8c, 0x12, 0x8f, 0xdf, 0x3b, 0xda, 0x82, 0x79, 0xc9, 0xa2, 0x1b, 0x04, 0xab, 0xbb, 0xad, 0x49, 0xa0, 0x6d, 0x70, 0x9b, 0x85, 0x29, 0x3c, 0x31,
0xee, 0xc3, 0x16, 0xc8, 0x05, 0x2c, 0xc1, 0x8d, 0x36, 0xb9, 0xad, 0x95, 0xf7, 0xed, 0xa5, 0xed, 0xf6, 0x4c, 0x1f, 0x26, 0x0d, 0x06, 0x8b, 0xe7,
0xb0, 0x76, 0x3d, 0xfc, 0x86, 0xa7, 0xcc, 0x66, 0x70, 0x95, 0x41, 0xcf, 0x0f, 0x0c, 0x4c, 0xbe, 0x23, 0xa0, 0xbf, 0x20, 0x76, 0xd3, 0x23, 0x67,
0xc2, 0x92, 0xa4, 0x42, 0x7f, 0x27, 0xbc, 0x46, 0x84, 0x5d, 0xcd, 0x21, 0x7e, 0x64, 0x32, 0x8b, 0x9d, 0xd0, 0x77, 0x4c, 0x3d, 0xb9, 0xb0, 0x71,
0xb3, 0xa5, 0x73, 0x8f, 0xc8, 0x04, 0xd8, 0x4a, 0x7b, 0x00, 0x46, 0x30, 0x1c, 0x5d, 0x9a, 0xa8, 0xa7, 0x8d, 0xac, 0x3e, 0xbc, 0xe1, 0x27, 0x45,
0xe3, 0x37, 0x11, 0xbc, 0x5e, 0xeb, 0x79, 0x21, 0xca, 0x00, 0x59, 0x31, 0x34, 0xb1, 0x1a, 0x05, 0x60, 0x7b, 0x90, 0xb1, 0x4f, 0x95, 0xa2, 0x19,
0x34, 0x29, 0xd3, 0xdf, 0x4a, 0xe3, 0xf7, 0x4c, 0xf1, 0xf0, 0x6c, 0x62, 0x3f, 0x86, 0xf3, 0x21, 0x0a, 0xfc, 0x6f, 0x55, 0x44, 0xfc, 0x52, 0xde,
0x41, 0xd1, 0x8b, 0x17, 0x11, 0x47, 0xa7, 0x87, 0xce, 0x3a, 0xcc, 0xbc, 0x33, 0x98, 0xc3, 0x1c, 0xca, 0x61, 0xe8, 0x1e, 0x6c, 0xe3, 0x9c, 0xc3,
0xb0, 0xe8, 0x4f, 0x2e, 0x78, 0xbd, 0x7c, 0xda, 0x56, 0x9d, 0x35, 0xa4, 0xb2, 0xdf, 0x6a, 0x93, 0x4b, 0x71, 0x29, 0x67, 0xe7, 0x26, 0x68, 0x89,
0x60, 0xf7, 0x96, 0x25, 0x1e, 0xdf, 0x6f, 0x62, 0xbe, 0xd6, 0xb0, 0x59, 0xda, 0x74, 0x0a, 0xf7, 0x42, 0xcc, 0x3c, 0x2c, 0x78, 0x6a, 0xf4, 0x39,
0x77, 0x64, 0xfc, 0x4a, 0x5a, 0xa2, 0x0a, 0xc7, 0xda, 0xde, 0xa1, 0x14, 0x15, 0x30, 0x29, 0xec, 0x87, 0xca, 0xdc, 0x06, 0x7e, 0x25, 0x07, 0x83,
0x08, 0x0f, 0x94, 0x57, 0x28, 0xe5, 0x36, 0xa8, 0x94, 0xdb, 0x37, 0x2a, 0xd8, 0xc8, 0xfa, 0x21, 0x86, 0x10, 0x29, 0xb4, 0x10, 0xbc, 0x3e, 0xee,
0x25, 0xc4, 0x80, 0xf0, 0xc3, 0x25, 0x30, 0xd4, 0xe6, 0x64, 0x48, 0x47, 0xe3, 0x5c, 0x56, 0x01, 0x94, 0xbe, 0xa6, 0x63, 0x23, 0x8b, 0x5f, 0x9d,
0x6b, 0x50, 0x80, 0xd9, 0x23, 0x1d, 0xff, 0x37, 0xa8, 0x46, 0x43, 0xaf, 0x26, 0xc2, 0x6f, 0x86, 0x06, 0x45, 0x2f, 0x01, 0x4c, 0x1c, 0xea, 0x96,
0x52, 0x4d, 0x7f, 0x2a, 0x8e, 0x8d, 0x10, 0x05, 0xd1, 0x8a, 0x3f, 0x57, 0xdd, 0xb5, 0x1e, 0xbb, 0x28, 0x1a, 0xca, 0x6a, 0xf8, 0x67, 0x82, 0xac,
0x4d, 0x1a, 0xfa, 0x38, 0x35, 0x99, 0x9e, 0xd2, 0x0a, 0x54, 0xc3, 0x8f, 0xa3, 0x41, 0x7b, 0xa0, 0xc1, 0xfe, 0x34, 0x4f, 0x66, 0x85, 0x90, 0xc5,
0xa9, 0xb8, 0x92, 0xd9, 0xa1, 0x2b, 0x3e, 0x2b, 0x98, 0xb6, 0xea, 0x8e, 0x05, 0x1b, 0xc4, 0x86, 0xde, 0x51, 0xf1, 0x2b, 0x9c, 0x89, 0x46, 0x3c,
0xde, 0x14, 0x1c, 0xc7, 0x0e, 0x53, 0x3f, 0xc2, 0xb5, 0x46, 0x4a, 0xfe, 0xd6, 0xf7, 0x26, 0xe5, 0xe0, 0xd7, 0x93, 0xac, 0xa3, 0x9c, 0xdb, 0xb0,
0xe2, 0x5b, 0x55, 0x9b, 0x0d, 0x38, 0xeb, 0x6a, 0xdf, 0x84, 0xa6, 0xc8, 0x72, 0x6e, 0x5f, 0xad, 0x9c, 0x08, 0x7b, 0xc2, 0x3f, 0x2e, 0x81, 0xa7,
0x65, 0x38, 0xa8, 0xd5, 0xc2, 0x07, 0x7d, 0xbd, 0x77, 0x97, 0xf1, 0x3f, 0xb6, 0xa0, 0x42, 0xd6, 0xdc, 0x80, 0x02, 0xcc, 0x21, 0xb1, 0x82, 0xbf,
0x1d, 0xa4, 0x79, 0x7e, 0xf1, 0xbf, 0xb3, 0x48, 0x33, 0x70, 0x39, 0x18, 0x4b, 0x45, 0x06, 0x5a, 0x4f, 0x45, 0xf4, 0x35, 0x2f, 0x61, 0x45, 0xd1,
0x13, 0x1c, 0x29, 0x06, 0x15, 0xf3, 0x64, 0x4b, 0x38, 0x3b, 0xd5, 0x10, 0x8a, 0x3f, 0x5b, 0x5d, 0x06, 0x7a, 0x5f, 0x75, 0x31, 0x6f, 0xea, 0xc4,
0xce, 0xf2, 0xa9, 0x12, 0x30, 0x9d, 0xc8, 0xfd, 0xf8, 0xdd, 0xd7, 0x3f, 0xbc, 0xd1, 0xc7, 0x75, 0x3c, 0x29, 0xf7, 0xe8, 0x65, 0xa5, 0x1d, 0x9c,
0xa7, 0x60, 0x69, 0x7c, 0x02, 0x5f, 0xc9, 0x13, 0xf8, 0xf1, 0xf5, 0xcf, 0xdb, 0x95, 0xfb, 0xaf, 0x0c, 0xb5, 0x93, 0xc7, 0xbb, 0xef, 0xe2, 0x7e,
0xdf, 0x24, 0x73, 0x13, 0x31, 0xed, 0xf4, 0xc4, 0x2c, 0x0d, 0x6f, 0x55, 0xe3, 0xe5, 0x7f, 0x09, 0xae, 0xe2, 0x59, 0x1b, 0xee, 0x3a, 0x3e, 0xb4,
0x4b, 0xd3, 0x17, 0x1e, 0x30, 0xcf, 0xa4, 0xb9, 0x1f, 0xa1, 0xe4, 0x67, 0x8a, 0xd7, 0xd4, 0x2a, 0x1c, 0x63, 0x3b, 0xc3, 0x67, 0xa4, 0x03, 0x57,
0xa0, 0x4d, 0x0a, 0x8f, 0xcc, 0x8e, 0x0e, 0x06, 0xe2, 0x9e, 0x5c, 0x80, 0xca, 0xf1, 0xff, 0x26, 0x08, 0xf5, 0xf1, 0x25, 0xfc, 0x8e, 0x22, 0x0b,
0x1d, 0x74, 0xa4, 0x09, 0x09, 0xf2, 0xc2, 0x01, 0xf3, 0x27, 0xd6, 0x99, 0x57, 0x80, 0x79, 0xc1, 0x81, 0x6c, 0xd0, 0xb6, 0x48, 0x36, 0xbf, 0xf3,
0xf9, 0x93, 0xce, 0x36, 0xc1, 0x2b, 0xd6, 0x9e, 0xbd, 0xcc, 0x04, 0x8b, 0x13, 0x03, 0xe1, 0xe4, 0xa3, 0xae, 0x00, 0xef, 0xa9, 0xc2, 0x8f, 0xdf,
0x8b, 0x58, 0xcb, 0xe7, 0x39, 0xe0, 0x61, 0x2f, 0xb0, 0x62, 0xe7, 0xe6, 0x7d, 0xf5, 0x73, 0x06, 0x16, 0xe2, 0x87, 0xf0, 0x95, 0x3e, 0x84, 0x87,
0x2f, 0x80, 0xc7, 0x68, 0x01, 0x2c, 0x53, 0x6f, 0xc7, 0x39, 0xba, 0x76, 0xaf, 0x7e, 0xfe, 0x3a, 0x5d, 0x18, 0xcb, 0x59, 0xb7, 0x53, 0xa6, 0x59,
0xf6, 0xbc, 0x21, 0x8b, 0x5e, 0x05, 0xc6, 0x5d, 0xa8, 0x1f, 0x42, 0x52, 0x78, 0x75, 0x60, 0x96, 0xbe, 0xa3, 0x82, 0xfb, 0x48, 0xda, 0xfb, 0x11,
0x4b, 0x90, 0xef, 0x74, 0x88, 0x49, 0x94, 0xb9, 0x30, 0x96, 0x20, 0x7f, 0x4a, 0x7e, 0x06, 0xda, 0xa4, 0x70, 0xdf, 0xee, 0xf5, 0x70, 0x54, 0xef,
0x83, 0x47, 0x7d, 0x8e, 0xbb, 0xe3, 0x96, 0x90, 0x9e, 0x19, 0xe9, 0x39, 0xcb, 0x3e, 0x38, 0xd1, 0x4a, 0x96, 0xd0, 0x20, 0xaf, 0x87, 0x60, 0x8f,
0x6c, 0x05, 0xdb, 0xd9, 0xed, 0xec, 0x01, 0xfe, 0x95, 0x85, 0xa5, 0xb9, 0x58, 0x77, 0xec, 0x91, 0x4d, 0x4c, 0xe1, 0xbb, 0xef, 0xbe, 0x7d, 0xda,
0xfb, 0xc5, 0xe8, 0xae, 0xc5, 0x39, 0xec, 0xb9, 0xe3, 0x64, 0x96, 0x71, 0x14, 0x8f, 0x8b, 0x78, 0xdb, 0x2b, 0x7a, 0xe0, 0xa3, 0xde, 0xbe, 0xc6,
0xc2, 0xce, 0x8d, 0x71, 0x66, 0x9f, 0xfd, 0xd6, 0x69, 0x1a, 0xb3, 0x61, 0xcf, 0xd8, 0x13, 0x20, 0x60, 0xbc, 0x30, 0x9a, 0xad, 0xbc, 0x83, 0x02,
0xbd, 0x7f, 0xfd, 0x18, 0x9f, 0xcc, 0x63, 0x14, 0x7a, 0xbb, 0x9a, 0x75, 0x5d, 0xa9, 0xfb, 0x5f, 0xf1, 0x46, 0x2f, 0x67, 0xe3, 0xee, 0x34, 0xcb,
0xf7, 0xff, 0x11, 0x6b, 0x32, 0x09, 0x47, 0xf5, 0x18, 0x11, 0x2a, 0x2d, 0x90, 0x5d, 0x93, 0xd4, 0x3b, 0x13, 0xc2, 0x19, 0x6d, 0x26, 0x8d, 0x14,
0x11, 0x31, 0x29, 0x28, 0xf3, 0xd5, 0x62, 0xa9, 0x43, 0x6b, 0xcc, 0x1e, 0x48, 0x20, 0x61, 0x7f, 0x50, 0x10, 0xee, 0x84, 0x05, 0xa4, 0x87, 0x86,
0x09, 0xad, 0xb3, 0x22, 0x4d, 0xfb, 0xfa, 0xb3, 0x75, 0xa1, 0x99, 0xbc, 0x66, 0x01, 0x9b, 0xc4, 0x66, 0x7e, 0x33, 0xbf, 0x87, 0x9f, 0xf2, 0x90,
0x28, 0xd8, 0x8b, 0x22, 0x92, 0x9b, 0xe1, 0x18, 0xcb, 0x7b, 0x57, 0xdc, 0x09, 0xf0, 0xfe, 0xb3, 0x03, 0x9e, 0x5c, 0x00, 0x1c, 0x31, 0xc0, 0x49,
0x44, 0xdd, 0xf2, 0xa0, 0x6e, 0x01, 0x2a, 0x45, 0xa0, 0xe2, 0x62, 0x29, 0x35, 0xeb, 0x90, 0x9f, 0x59, 0xa3, 0xdc, 0x2e, 0xff, 0xad, 0xa7, 0x6d,
0xe1, 0x45, 0xf4, 0x39, 0xfa, 0x42, 0xfa, 0x3f, 0x00, 0x33, 0xfc, 0x14, 0xcc, 0x88, 0xf3, 0x0f, 0x1c, 0x1c, 0xe0, 0x13, 0x8c, 0x9c, 0x46, 0xef,
0xf6, 0xa1, 0x5e, 0x00, 0x00 0xbd, 0xf3, 0x5e, 0x4b, 0xd8, 0xe7, 0x6d, 0x3e, 0xe1, 0x4c, 0x23, 0x27,
0x43, 0xad, 0x2d, 0x28, 0xa6, 0x06, 0x65, 0xc1, 0x6a, 0x2c, 0x7c, 0x74,
0x15, 0xeb, 0x9b, 0xe8, 0x4a, 0x3b, 0x5c, 0x75, 0xae, 0xa5, 0xdb, 0x17,
0xcd, 0xc9, 0xbb, 0xb4, 0x03, 0x38, 0x32, 0xb9, 0xb8, 0x8f, 0xd1, 0xfc,
0x57, 0xf9, 0x19, 0xee, 0x86, 0x0f, 0x77, 0x03, 0x70, 0x29, 0x02, 0x93,
0x1a, 0xcb, 0x0a, 0x8f, 0x07, 0x05, 0xf6, 0x6f, 0x3f, 0xfc, 0x01, 0x35,
0x65, 0x9f, 0x7f, 0x0d, 0x62, 0x00, 0x00
}; };
File diff suppressed because it is too large Load Diff
+269
View File
@@ -0,0 +1,269 @@
#include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
#if defined(ARDUINOJSON_VERSION)
#if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR >= 8)
#error "Install ArduinoJson v6.8.x or higher"
#endif
#endif
char * listStateJSONfull() {
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(20) + 250;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["segment"] = segment;
root["start"] = seg_start;
root["stop"] = seg_stop;
root["mode"] = (uint8_t) mode;
//getSegmentParams(segment);
root["ws2812fx_mode"] = ws2812fx_mode;
root["ws2812fx_mode_name"] = strip->getModeName(ws2812fx_mode);
root["speed"] = ws2812fx_speed;
root["brightness"] = brightness;
JsonArray color = root.createNestedArray("color");
color.add(main_color.white);
color.add(main_color.red);
color.add(main_color.green);
color.add(main_color.blue);
color.add(back_color.white);
color.add(back_color.red);
color.add(back_color.green);
color.add(back_color.blue);
color.add(xtra_color.white);
color.add(xtra_color.red);
color.add(xtra_color.green);
color.add(xtra_color.blue);
root["hostname"] = HOSTNAME;
#if defined(ENABLE_MQTT)
root["mqtt_host"] = mqtt_host;
root["mqtt_port"] = mqtt_port;
root["mqtt_user"] = mqtt_user;
root["mqtt_pass"] = mqtt_pass;
#endif
root["ws_seg"] = num_segments;
root["ws_cnt"] = WS2812FXStripSettings.stripSize;
root["ws_rgbo"] = WS2812FXStripSettings.RGBOrder;
root["ws_pin"] = WS2812FXStripSettings.pin;
root["ws_fxopt"] = WS2812FXStripSettings.fxoptions;
root["transEffect"] = transEffect;
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
char * listStateJSON() {
const size_t bufferSize = JSON_OBJECT_SIZE(3) + 25;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["segment"] = segment;
root["mode"] = (uint8_t) mode;
root["brightness"] = brightness;
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
char * listSegmentStateJSON(uint8_t seg) {
const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(7) + 100;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["segment"] = seg;
if (seg == segment) {
root["start"] = seg_start;
root["stop"] = seg_stop;
} else {
root["start"] = strip->getSegment(seg)->start;
root["stop"] = strip->getSegment(seg)->stop;
}
//getSegmentParams(seg);
root["ws2812fx_mode"] = strip->getMode(seg);
root["ws2812fx_mode_name"] = strip->getModeName(strip->getMode(seg));
root["speed"] = ws2812fx_speed;
JsonArray color = root.createNestedArray("color");
color.add((strip->getColors(seg)[0] >> 24) & 0xFF);
color.add((strip->getColors(seg)[0] >> 16) & 0xFF);
color.add((strip->getColors(seg)[0] >> 8) & 0xFF);
color.add((strip->getColors(seg)[0]) & 0xFF);
color.add((strip->getColors(seg)[1] >> 24) & 0xFF);
color.add((strip->getColors(seg)[1] >> 16) & 0xFF);
color.add((strip->getColors(seg)[1] >> 8) & 0xFF);
color.add((strip->getColors(seg)[1]) & 0xFF);
color.add((strip->getColors(seg)[2] >> 24) & 0xFF);
color.add((strip->getColors(seg)[2] >> 16) & 0xFF);
color.add((strip->getColors(seg)[2] >> 8) & 0xFF);
color.add((strip->getColors(seg)[2]) & 0xFF);
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
void getStateJSON() {
char * buffer = listStateJSONfull();
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send ( 200, "application/json", buffer);
free (buffer);
}
char * listConfigJSON() {
#if defined(ENABLE_MQTT)
const size_t bufferSize = JSON_OBJECT_SIZE(11) + 150;
#else
const size_t bufferSize = JSON_OBJECT_SIZE(7) + 100;
#endif
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["hostname"] = HOSTNAME;
#if defined(ENABLE_MQTT)
root["mqtt_host"] = mqtt_host;
root["mqtt_port"] = mqtt_port;
root["mqtt_user"] = mqtt_user;
root["mqtt_pass"] = mqtt_pass;
#endif
root["ws_seg"] = num_segments;
root["ws_cnt"] = WS2812FXStripSettings.stripSize;
root["ws_rgbo"] = WS2812FXStripSettings.RGBOrder;
root["ws_pin"] = WS2812FXStripSettings.pin;
root["ws_fxopt"] = WS2812FXStripSettings.fxoptions;
root["transEffect"] = transEffect;
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
void getConfigJSON() {
char * buffer = listConfigJSON();
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send ( 200, "application/json", buffer);
free (buffer);
}
char * listModesJSON() {
const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount() + 1) + (strip->getModeCount() + 1)*JSON_OBJECT_SIZE(2) + 2000;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonArray root = jsonBuffer.to<JsonArray>();
JsonObject objectoff = root.createNestedObject();
objectoff["mode"] = "off";
objectoff["name"] = "OFF";
for (uint8_t i = 0; i < strip->getModeCount(); i++) {
JsonObject object = root.createNestedObject();
object["mode"] = i;
object["name"] = strip->getModeName(i);
}
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
void getModesJSON() {
char * buffer = listModesJSON();
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send ( 200, "application/json", buffer);
free (buffer);
}
char * listESPStateJSON() {
const size_t bufferSize = JSON_OBJECT_SIZE(31) + 1500;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["HOSTNAME"] = HOSTNAME;
root["version"] = SKETCH_VERSION;
root["heap"] = ESP.getFreeHeap();
root["sketch_size"] = ESP.getSketchSize();
root["free_sketch_space"] = ESP.getFreeSketchSpace();
root["flash_chip_size"] = ESP.getFlashChipSize();
root["flash_chip_real_size"] = ESP.getFlashChipRealSize();
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
root["sdk_version"] = ESP.getSdkVersion();
root["core_version"] = ESP.getCoreVersion();
root["cpu_freq"] = ESP.getCpuFreqMHz();
root["chip_id"] = ESP.getFlashChipId();
#if defined(USE_WS2812FX_DMA)
#if USE_WS2812FX_DMA == 0
root["animation_lib"] = "WS2812FX_DMA";
#endif
#if USE_WS2812FX_DMA == 1
root["animation_lib"] = "WS2812FX_UART1";
#endif
#if USE_WS2812FX_DMA == 2
root["animation_lib"] = "WS2812FX_UART2";
#endif
#else
root["animation_lib"] = "WS2812FX";
#endif
root["ws2812_pin"] = WS2812FXStripSettings.pin;
root["led_count"] = WS2812FXStripSettings.stripSize;
root["rgb_order"] = WS2812FXStripSettings.RGBOrder;
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) {
root["rgbw_mode"] = "ON";
} else {
root["rgbw_mode"] = "OFF";
}
#if defined(ENABLE_BUTTON)
root["button_mode"] = "ON";
root["button_pin"] = ENABLE_BUTTON;
#else
root["button_mode"] = "OFF";
#endif
#if defined(ENABLE_BUTTON_GY33)
root["button_gy33"] = "ON";
root["gy33_pin"] = ENABLE_BUTTON_GY33;
#else
root["button_gy33"] = "OFF";
#endif
#if defined(ENABLE_REMOTE)
root["ir_remote"] = "ON";
root["tsop_ir_pin"] = ENABLE_REMOTE;
#else
root["ir_remote"] = "OFF";
#endif
#if defined(ENABLE_MQTT)
#if ENABLE_MQTT == 0
root["mqtt"] = "MQTT";
#endif
#if ENABLE_MQTT == 1
root["mqtt"] = "AMQTT";
#endif
#else
root["mqtt"] = "OFF";
#endif
#if defined(ENABLE_HOMEASSISTANT)
root["home_assistant"] = "ON";
#else
root["home_assistant"] = "OFF";
#endif
#if defined(ENABLE_OTA)
#if ENABLE_OTA == 0
root["ota"] = "ARDUINO";
#endif
#if ENABLE_OTA == 1
root["ota"] = "HTTP";
#endif
#else
root["ota"] = "OFF";
#endif
#if defined(ENABLE_STATE_SAVE)
root["state_save"] = "SPIFFS";
#else
root["state_save"] = "OFF";
#endif
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
void getESPStateJSON() {
char * buffer = listESPStateJSON();
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "application/json", buffer);
free (buffer);
}
@@ -1,3 +1,7 @@
// Prototypes
uint16_t convertSpeed(uint8_t mcl_speed);
uint32_t trans(uint32_t newcolor, uint32_t oldcolor, uint8_t level);
// End Prototypes
/* /*
Example of adding the example: https://github.com/kitesurfer1404/WS2812FX/blob/master/examples/ws2812fx_custom_FastLED/ws2812fx_custom_FastLED.ino Example of adding the example: https://github.com/kitesurfer1404/WS2812FX/blob/master/examples/ws2812fx_custom_FastLED/ws2812fx_custom_FastLED.ino
@@ -68,7 +72,7 @@ void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint16_t led) {
void updateLed (uint16_t led, uint8_t brightness) { void updateLed (uint16_t led, uint8_t brightness) {
ledstates[led] = brightness; ledstates[led] = brightness;
for (uint16_t i=0; i<WS2812FXStripSettings.stripSize; i++) { for (uint16_t i=seg_start; i<=seg_stop; i++) {
uint16_t index = (i%3 == 0) ? 400 : random(0,767); uint16_t index = (i%3 == 0) ? 400 : random(0,767);
hsb2rgbAN1(index, 200, ledstates[i], i); hsb2rgbAN1(index, 200, ledstates[i], i);
} }
@@ -200,12 +204,12 @@ void Fire2012() {
// Array of temperature readings at each simulation cell // Array of temperature readings at each simulation cell
// Step 1. Cool down every cell a little // Step 1. Cool down every cell a little
for( uint16_t i = 0; i < WS2812FXStripSettings.stripSize; i++) { for( uint16_t i = seg_start; i <= seg_stop; i++) {
ledstates[i] = qsub8( ledstates[i], random8(0, ((COOLING * 10) / WS2812FXStripSettings.stripSize) + 2)); ledstates[i] = qsub8( ledstates[i], random8(0, ((COOLING * 10) / WS2812FXStripSettings.stripSize) + 2));
} }
// Step 2. Heat from each cell drifts 'up' and diffuses a little // Step 2. Heat from each cell drifts 'up' and diffuses a little
for( uint16_t k= WS2812FXStripSettings.stripSize - 1; k >= 2; k--) { for( uint16_t k= seg_stop-seg_start - 1; k >= 2; k--) {
ledstates[k] = (ledstates[k - 1] + ledstates[k - 2] + ledstates[k - 2]) / 3; ledstates[k] = (ledstates[k - 1] + ledstates[k - 2] + ledstates[k - 2]) / 3;
} }
@@ -216,11 +220,11 @@ void Fire2012() {
} }
// Step 4. Map from heat cells to LED colors // Step 4. Map from heat cells to LED colors
for( uint16_t j = 0; j < WS2812FXStripSettings.stripSize; j++) { for( uint16_t j = seg_start; j <= seg_stop; j++) {
CRGB color = HeatColor( ledstates[j]); CRGB color = HeatColor( ledstates[j]);
uint16_t pixelnumber; uint16_t pixelnumber;
if( gReverseDirection ) { if( gReverseDirection ) {
pixelnumber = (WS2812FXStripSettings.stripSize - 1) - j; pixelnumber = seg_stop - j;
} else { } else {
pixelnumber = j; pixelnumber = j;
} }
@@ -229,15 +233,15 @@ void Fire2012() {
} }
void Gradient() { void Gradient() {
for( uint16_t j = 0; j < WS2812FXStripSettings.stripSize; j++) { for( uint16_t j = seg_start; j <= seg_stop; j++) {
uint16_t pixelnumber; uint16_t pixelnumber;
uint32_t color; uint32_t color;
if( gReverseDirection ) { if( gReverseDirection ) {
pixelnumber = (WS2812FXStripSettings.stripSize - 1) - j; pixelnumber = seg_stop - j;
} else { } else {
pixelnumber = j; pixelnumber = j;
} }
color = trans(strip->getColors(segment)[1], strip->getColors(segment)[0], (j*255)/(WS2812FXStripSettings.stripSize - 1)); color = trans(strip->getColors(segment)[1], strip->getColors(segment)[0], (j*255)/(seg_stop - seg_start));
strip->setPixelColor(pixelnumber, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF), ((color >> 24) & 0xFF)); strip->setPixelColor(pixelnumber, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), ((color >> 0) & 0xFF), ((color >> 24) & 0xFF));
} }
} }
File diff suppressed because it is too large Load Diff
+375 -328
View File
@@ -1,359 +1,406 @@
// *************************************************************************** // ***************************************************************************
// Setup: Webserver handler // Setup: Webserver handler
// *************************************************************************** // ***************************************************************************
//list directory //list directory
server.on("/list", HTTP_GET, handleFileList); server.on("/list", HTTP_GET, handleFileList);
//create file //create file
server.on("/edit", HTTP_PUT, handleFileCreate); server.on("/edit", HTTP_PUT, handleFileCreate);
//delete file //delete file
server.on("/edit", HTTP_DELETE, handleFileDelete); server.on("/edit", HTTP_DELETE, handleFileDelete);
//first callback is called after the request has ended with all parsed arguments //first callback is called after the request has ended with all parsed arguments
//second callback handles file uploads at that location //second callback handles file uploads at that location
server.on("/edit", HTTP_POST, []() { server.on("/edit", HTTP_POST, []() {
server.sendHeader("Access-Control-Allow-Origin", "*"); server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", ""); server.send(200, "text/plain", "");
}, handleFileUpload); }, handleFileUpload);
// *************************************************************************** // ***************************************************************************
// Setup: SPIFFS Webserver handler // Setup: SPIFFS Webserver handler
// *************************************************************************** // ***************************************************************************
server.on("/", HTTP_GET, [&](){ server.on("/", HTTP_GET, [&](){
#if defined(USE_HTML_MIN_GZ) #if defined(USE_HTML_MIN_GZ)
server.sendHeader("Content-Encoding", "gzip", true); server.sendHeader("Content-Encoding", "gzip", true);
server.send_P(200, PSTR("text/html"), index_htm_gz, index_htm_gz_len); server.send_P(200, PSTR("text/html"), index_htm_gz, index_htm_gz_len);
#else #else
if (!handleFileRead(server.uri()))
handleNotFound();
#endif
});
server.on("/edit", HTTP_GET, [&](){
#if defined(USE_HTML_MIN_GZ)
server.sendHeader("Content-Encoding", "gzip", true);
server.send_P(200, PSTR("text/html"), edit_htm_gz, edit_htm_gz_len);
#else
if (!handleFileRead("/edit.htm"))
handleNotFound();
#endif
});
//called when the url is not defined here
//use it to load content from SPIFFS
server.onNotFound([]() {
if (!handleFileRead(server.uri())) if (!handleFileRead(server.uri()))
handleNotFound(); handleNotFound();
}); #endif
});
server.on("/upload", handleMinimalUpload); server.on("/edit", HTTP_GET, [&](){
#if defined(USE_HTML_MIN_GZ)
server.sendHeader("Content-Encoding", "gzip", true);
server.send_P(200, PSTR("text/html"), edit_htm_gz, edit_htm_gz_len);
#else
if (!handleFileRead("/edit.htm"))
handleNotFound();
#endif
});
server.on("/esp_status", HTTP_GET, []() { //get heap status, analog input value and all GPIO statuses in one json call
const size_t bufferSize = JSON_OBJECT_SIZE(31) + 1500; //called when the url is not defined here
DynamicJsonDocument jsonBuffer(bufferSize); //use it to load content from SPIFFS
JsonObject root = jsonBuffer.to<JsonObject>(); server.onNotFound([]() {
root["HOSTNAME"] = HOSTNAME; if (!handleFileRead(server.uri()))
root["version"] = SKETCH_VERSION; handleNotFound();
root["heap"] = ESP.getFreeHeap(); });
root["sketch_size"] = ESP.getSketchSize();
root["free_sketch_space"] = ESP.getFreeSketchSpace(); server.on("/upload", handleMinimalUpload);
root["flash_chip_size"] = ESP.getFlashChipSize();
root["flash_chip_real_size"] = ESP.getFlashChipRealSize(); server.on("/esp_status", HTTP_GET, []() { //get heap status, analog input value and all GPIO statuses in one json call
root["flash_chip_speed"] = ESP.getFlashChipSpeed(); getESPStateJSON();
root["sdk_version"] = ESP.getSdkVersion(); });
root["core_version"] = ESP.getCoreVersion();
root["cpu_freq"] = ESP.getCpuFreqMHz(); server.on("/restart", []() {
root["chip_id"] = ESP.getFlashChipId(); DBG_OUTPUT_PORT.printf("/restart\r\n");
#if defined(USE_WS2812FX_DMA) server.sendHeader("Access-Control-Allow-Origin", "*");
#if USE_WS2812FX_DMA == 0 server.send(200, "text/plain", "restarting..." );
root["animation_lib"] = "WS2812FX_DMA"; ESP.restart();
#endif });
#if USE_WS2812FX_DMA == 1
root["animation_lib"] = "WS2812FX_UART1"; server.on("/reset_wlan", []() {
#endif DBG_OUTPUT_PORT.printf("/reset_wlan\r\n");
#if USE_WS2812FX_DMA == 2 server.sendHeader("Access-Control-Allow-Origin", "*");
root["animation_lib"] = "WS2812FX_UART2"; server.send(200, "text/plain", "Resetting WLAN and restarting..." );
#endif WiFiManager wifiManager;
#else wifiManager.resetSettings();
root["animation_lib"] = "WS2812FX"; ESP.restart();
#endif });
root["ws2812_pin"] = WS2812FXStripSettings.pin;
root["led_count"] = WS2812FXStripSettings.stripSize; server.on("/start_config_ap", []() {
root["rgb_order"] = WS2812FXStripSettings.RGBOrder; DBG_OUTPUT_PORT.printf("/start_config_ap\r\n");
if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) { server.sendHeader("Access-Control-Allow-Origin", "*");
root["rgbw_mode"] = "ON"; server.send(200, "text/plain", "Starting config AP ..." );
} else { WiFiManager wifiManager;
root["rgbw_mode"] = "OFF"; wifiManager.startConfigPortal(HOSTNAME);
} });
#if defined(ENABLE_BUTTON)
root["button_mode"] = "ON"; server.on("/format_spiffs", []() {
root["button_pin"] = ENABLE_BUTTON; DBG_OUTPUT_PORT.printf("/format_spiffs\r\n");
#else server.send(200, "text/plain", "Formatting SPIFFS ..." );
root["button_mode"] = "OFF"; SPIFFS.format();
#endif });
#if defined(ENABLE_BUTTON_GY33)
root["button_gy33"] = "ON"; server.on("/get_brightness", []() {
root["gy33_pin"] = ENABLE_BUTTON_GY33; char str_brightness[4];
#else snprintf(str_brightness, sizeof(str_brightness), "%i", (int) (brightness / 2.55));
root["button_gy33"] = "OFF"; str_brightness[sizeof(str_brightness) - 1] = 0x00;
#endif server.sendHeader("Access-Control-Allow-Origin", "*");
#if defined(ENABLE_REMOTE) server.send(200, "text/plain", str_brightness );
root["ir_remote"] = "ON"; DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (brightness / 2.55));
root["tsop_ir_pin"] = ENABLE_REMOTE; });
#else
root["ir_remote"] = "OFF"; server.on("/get_speed", []() {
#endif char str_speed[4];
#if defined(ENABLE_MQTT) snprintf(str_speed, sizeof(str_speed), "%i", ws2812fx_speed);
#if ENABLE_MQTT == 0 str_speed[sizeof(str_speed) - 1] = 0x00;
root["mqtt"] = "MQTT"; server.sendHeader("Access-Control-Allow-Origin", "*");
#endif server.send(200, "text/plain", str_speed );
#if ENABLE_MQTT == 1 DBG_OUTPUT_PORT.printf("/get_speed: %i\r\n", ws2812fx_speed);
root["mqtt"] = "AMQTT"; });
#endif
#else server.on("/get_switch", []() {
root["mqtt"] = "OFF"; server.sendHeader("Access-Control-Allow-Origin", "*");
#endif server.send(200, "text/plain", (mode == OFF) ? "0" : "1" );
#if defined(ENABLE_HOMEASSISTANT) DBG_OUTPUT_PORT.printf("/get_switch: %s\r\n", (mode == OFF) ? "0" : "1");
root["home_assistant"] = "ON"; });
#else
root["home_assistant"] = "OFF"; server.on("/get_color", []() {
#endif char rgbcolor[10];
#if defined(ENABLE_OTA) snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue);
#if ENABLE_OTA == 0 rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
root["ota"] = "ARDUINO"; server.sendHeader("Access-Control-Allow-Origin", "*");
#endif server.send(200, "text/plain", rgbcolor );
#if ENABLE_OTA == 1 DBG_OUTPUT_PORT.print("/get_color: ");
root["ota"] = "HTTP"; DBG_OUTPUT_PORT.println(rgbcolor);
#endif });
#else
root["ota"] = "OFF"; server.on("/get_color2", []() {
#endif char rgbcolor[10];
#if defined(ENABLE_STATE_SAVE) snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", back_color.white, back_color.red, back_color.green, back_color.blue);
root["state_save"] = "SPIFFS"; rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
#else server.sendHeader("Access-Control-Allow-Origin", "*");
root["state_save"] = "OFF"; server.send(200, "text/plain", rgbcolor );
#endif DBG_OUTPUT_PORT.print("/get_color2: ");
uint16_t msg_len = measureJson(root) + 1; DBG_OUTPUT_PORT.println(rgbcolor);
char * buffer = (char *) malloc(msg_len); });
serializeJson(root, buffer, msg_len);
jsonBuffer.clear(); server.on("/get_color3", []() {
server.sendHeader("Access-Control-Allow-Origin", "*"); char rgbcolor[10];
server.send(200, "application/json", buffer); snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", xtra_color.white, xtra_color.red, xtra_color.green, xtra_color.blue);
free (buffer); rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
}); server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", rgbcolor );
server.on("/restart", []() { DBG_OUTPUT_PORT.print("/get_color3: ");
DBG_OUTPUT_PORT.printf("/restart\r\n"); DBG_OUTPUT_PORT.println(rgbcolor);
server.sendHeader("Access-Control-Allow-Origin", "*"); });
server.send(200, "text/plain", "restarting..." );
ESP.restart(); server.on("/get_modes", []() {
}); getModesJSON();
});
server.on("/reset_wlan", []() {
DBG_OUTPUT_PORT.printf("/reset_wlan\r\n"); server.on("/status", []() {
server.sendHeader("Access-Control-Allow-Origin", "*"); getStateJSON();
server.send(200, "text/plain", "Resetting WLAN and restarting..." ); });
WiFiManager wifiManager;
wifiManager.resetSettings(); server.on("/config", []() {
ESP.restart();
}); /*
server.on("/start_config_ap", []() { // This will be used later when web-interface is ready and HTTP_GET will not be allowed to update the Strip Settings
DBG_OUTPUT_PORT.printf("/start_config_ap\r\n");
server.sendHeader("Access-Control-Allow-Origin", "*"); if(server.args() == 0 and server.method() != HTTP_POST)
server.send(200, "text/plain", "Starting config AP ..." ); {
WiFiManager wifiManager; server.sendHeader("Access-Control-Allow-Origin", "*");
wifiManager.startConfigPortal(HOSTNAME); server.send(200, "text/plain", "Only HTTP POST method is allowed and check the number of arguments!");
}); return;
}
server.on("/format_spiffs", []() {
DBG_OUTPUT_PORT.printf("/format_spiffs\r\n"); */
server.send(200, "text/plain", "Formatting SPIFFS ..." ); // ToDo do not save if no change
SPIFFS.format(); bool _updateStrip = false;
}); bool _updateConfig = false;
if(server.hasArg("ws_seg")){
server.on("/get_brightness", []() { uint8_t wsseg = server.arg("ws_seg").toInt();
char str_brightness[4]; num_segments = constrain(wsseg, 1, MAX_NUM_SEGMENTS - 1);
snprintf(str_brightness, sizeof(str_brightness), "%i", (int) (brightness / 2.55)); _updateStrip = true;
str_brightness[sizeof(str_brightness) - 1] = 0x00; }
server.sendHeader("Access-Control-Allow-Origin", "*"); if(server.hasArg("ws_cnt")){
server.send(200, "text/plain", str_brightness ); uint16_t pixelCt = server.arg("ws_cnt").toInt();
DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (brightness / 2.55)); if (pixelCt > 0) {
}); WS2812FXStripSettings.stripSize = constrain(pixelCt, 1, MAXLEDS);
_updateStrip = true;
server.on("/get_speed", []() {
char str_speed[4];
snprintf(str_speed, sizeof(str_speed), "%i", ws2812fx_speed);
str_speed[sizeof(str_speed) - 1] = 0x00;
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", str_speed );
DBG_OUTPUT_PORT.printf("/get_speed: %i\r\n", ws2812fx_speed);
});
server.on("/get_switch", []() {
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", (mode == OFF) ? "0" : "1" );
DBG_OUTPUT_PORT.printf("/get_switch: %s\r\n", (mode == OFF) ? "0" : "1");
});
server.on("/get_color", []() {
char rgbcolor[10];
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue);
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", rgbcolor );
DBG_OUTPUT_PORT.print("/get_color: ");
DBG_OUTPUT_PORT.println(rgbcolor);
});
server.on("/get_color2", []() {
char rgbcolor[10];
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", back_color.white, back_color.red, back_color.green, back_color.blue);
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", rgbcolor );
DBG_OUTPUT_PORT.print("/get_color2: ");
DBG_OUTPUT_PORT.println(rgbcolor);
});
server.on("/get_color3", []() {
char rgbcolor[10];
snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", xtra_color.white, xtra_color.red, xtra_color.green, xtra_color.blue);
rgbcolor[sizeof(rgbcolor) - 1] = 0x00;
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", rgbcolor );
DBG_OUTPUT_PORT.print("/get_color3: ");
DBG_OUTPUT_PORT.println(rgbcolor);
});
server.on("/get_modes", []() {
getModesJSON();
});
server.on("/status", []() {
getStatusJSON();
});
server.on("/config", []() {
/*
// This will be used later when web-interface is ready and HTTP_GET will not be allowed to update the Strip Settings
if(server.args() == 0 and server.method() != HTTP_POST)
{
server.sendHeader("Access-Control-Allow-Origin", "*");
server.send(200, "text/plain", "Only HTTP POST method is allowed and check the number of arguments!");
return;
}
*/
bool updateStrip = false;
bool updateConf = false;
if(server.hasArg("ws_seg")){
uint8_t wsseg = server.arg("ws_seg").toInt();
num_segments = constrain(wsseg, 1, MAX_NUM_SEGMENTS - 1);
updateStrip = true;
}
if(server.hasArg("ws_cnt")){
uint16_t pixelCt = server.arg("ws_cnt").toInt();
if (pixelCt > 0) {
WS2812FXStripSettings.stripSize = constrain(pixelCt, 1, MAXLEDS);
updateStrip = true;
}
}
if(server.hasArg("ws_rgbo")){
char tmp_rgbOrder[5];
snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", server.arg("ws_rgbo").c_str());
tmp_rgbOrder[sizeof(tmp_rgbOrder) - 1] = 0x00;
checkRGBOrder(tmp_rgbOrder);
updateStrip = true;
} }
}
if(server.hasArg("ws_rgbo")){
char tmp_rgbOrder[5];
snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", server.arg("ws_rgbo").c_str());
tmp_rgbOrder[sizeof(tmp_rgbOrder) - 1] = 0x00;
checkRGBOrder(tmp_rgbOrder);
_updateStrip = true;
}
#if !defined(USE_WS2812FX_DMA) #if !defined(USE_WS2812FX_DMA)
if(server.hasArg("ws_pin")){ if(server.hasArg("ws_pin")){
if (checkPin(server.arg("ws_pin").toInt())) { if (checkPin(server.arg("ws_pin").toInt())) {
updateStrip = true; _updateStrip = true;
DBG_OUTPUT_PORT.print("Pin was set to: "); DBG_OUTPUT_PORT.print("Pin was set to: ");
DBG_OUTPUT_PORT.println(WS2812FXStripSettings.pin); DBG_OUTPUT_PORT.println(WS2812FXStripSettings.pin);
} else { } else {
DBG_OUTPUT_PORT.println("invalid input!"); DBG_OUTPUT_PORT.println("invalid input!");
}
} }
}
#endif #endif
if(server.hasArg("ws_fxopt")){ if(server.hasArg("ws_fxopt")){
WS2812FXStripSettings.fxoptions = ((constrain(server.arg("ws_fxopt").toInt(), 0, 255)>>1)<<1); WS2812FXStripSettings.fxoptions = ((constrain(server.arg("ws_fxopt").toInt(), 0, 255)>>1)<<1);
updateStrip = true; _updateStrip = true;
} }
if(updateStrip) { if(_updateStrip) {
mode = INIT_STRIP; initStrip();
} }
if(server.hasArg("hostname")){ if(server.hasArg("hostname")){
snprintf(HOSTNAME, sizeof(HOSTNAME), "%s", server.arg("hostname").c_str()); snprintf(HOSTNAME, sizeof(HOSTNAME), "%s", server.arg("hostname").c_str());
HOSTNAME[sizeof(HOSTNAME) - 1] = 0x00; HOSTNAME[sizeof(HOSTNAME) - 1] = 0x00;
updateConf = true; _updateConfig = true;
} }
#if defined(ENABLE_MQTT) #if defined(ENABLE_MQTT)
if(server.hasArg("mqtt_host")){ if(server.hasArg("mqtt_host")){
snprintf(mqtt_host, sizeof(mqtt_host), "%s", server.arg("mqtt_host").c_str()); snprintf(mqtt_host, sizeof(mqtt_host), "%s", server.arg("mqtt_host").c_str());
mqtt_host[sizeof(mqtt_host) - 1] = 0x00; mqtt_host[sizeof(mqtt_host) - 1] = 0x00;
updateConf = true; _updateConfig = true;
} }
if(server.hasArg("mqtt_port")){ if(server.hasArg("mqtt_port")){
if ((server.arg("mqtt_port").toInt() >= 0) && (server.arg("mqtt_port").toInt() <=65535)) { if ((server.arg("mqtt_port").toInt() >= 0) && (server.arg("mqtt_port").toInt() <=65535)) {
mqtt_port = server.arg("mqttport").toInt(); mqtt_port = server.arg("mqttport").toInt();
updateConf = true; _updateConfig = true;
}
}
if(server.hasArg("mqtt_user")){
snprintf(mqtt_user, sizeof(mqtt_user), "%s", server.arg("mqtt_user").c_str());
mqtt_user[sizeof(mqtt_user) - 1] = 0x00;
updateConf = true;
}
if(server.hasArg("mqtt_pass")){
snprintf(mqtt_pass, sizeof(mqtt_pass), "%s", server.arg("mqtt_pass").c_str());
mqtt_pass[sizeof(mqtt_pass) - 1] = 0x00;
updateConf = true;
}
if (updateConf) {
initMqtt();
} }
}
if(server.hasArg("mqtt_user")){
snprintf(mqtt_user, sizeof(mqtt_user), "%s", server.arg("mqtt_user").c_str());
mqtt_user[sizeof(mqtt_user) - 1] = 0x00;
_updateConfig = true;
}
if(server.hasArg("mqtt_pass")){
snprintf(mqtt_pass, sizeof(mqtt_pass), "%s", server.arg("mqtt_pass").c_str());
mqtt_pass[sizeof(mqtt_pass) - 1] = 0x00;
_updateConfig = true;
}
if (_updateConfig) {
initMqtt();
}
#endif #endif
if(server.hasArg("trans_effect")){ if(server.hasArg("trans_effect")){
transEffect = server.arg("trans_effect").toInt(); transEffect = server.arg("trans_effect").toInt();
updateConf = true; _updateConfig = true;
} }
#if defined(ENABLE_STATE_SAVE) #if defined(ENABLE_STATE_SAVE)
if (updateStrip || updateConf) { if (_updateStrip || _updateConfig) {
if(!settings_save_conf.active()) settings_save_conf.once(3, tickerSaveConfig); if(!save_conf.active()) save_conf.once(3, tickerSaveConfig);
} }
#endif #endif
updateStrip = false; _updateStrip = false;
updateConf = false; _updateConfig = false;
getConfigJSON(); getConfigJSON();
}); });
server.on("/off", []() { server.on("/off", []() {
if (prevmode != OFF) {
mode = OFF; mode = OFF;
getStatusJSON(); getStateJSON();
}); #if defined(ENABLE_STATE_SAVE)
if(!save_state.active()) save_state.once(3, tickerSaveState);
#endif
}
});
server.on("/on", []() { server.on("/on", []() {
if (prevmode == OFF) {
mode = SET; mode = SET;
getStatusJSON(); getStateJSON();
}); #if defined(ENABLE_STATE_SAVE)
if(!save_state.active()) save_state.once(3, tickerSaveState);
#endif
}
});
server.on("/set", []() { server.on("/set", []() {
prevmode = HOLD; prevmode = HOLD;
ws2812fx_mode = FX_MODE_STATIC; ws2812fx_mode = FX_MODE_STATIC;
boolean _updateState = false;
boolean _updateSegState = false;
// Segment
if ((server.arg("seg") != "") && (server.arg("seg").toInt() >= 0) && (server.arg("seg").toInt() <= MAX_NUM_SEGMENTS)) {
segment = server.arg("seg").toInt();
if (prevsegment != segment) {
prevsegment = segment;
getSegmentParams(segment);
memcpy(hex_colors_trans, hex_colors, sizeof(hex_colors_trans));
mode = SET;
_updateState = true;
}
}
//color wrgb
if (server.arg("rgb") != "") {
uint32_t rgb = (uint32_t) strtoul(server.arg("rgb").c_str(), NULL, 16);
main_color.white = ((rgb >> 24) & 0xFF);
main_color.red = ((rgb >> 16) & 0xFF);
main_color.green = ((rgb >> 8) & 0xFF);
main_color.blue = ((rgb >> 0) & 0xFF);
} else {
if ((server.arg("r") != "") && (server.arg("r").toInt() >= 0) && (server.arg("r").toInt() <= 255)) {
main_color.red = server.arg("r").toInt();
}
if ((server.arg("g") != "") && (server.arg("g").toInt() >= 0) && (server.arg("g").toInt() <= 255)) {
main_color.green = server.arg("g").toInt();
}
if ((server.arg("b") != "") && (server.arg("b").toInt() >= 0) && (server.arg("b").toInt() <= 255)) {
main_color.blue = server.arg("b").toInt();
}
if ((server.arg("w") != "") && (server.arg("w").toInt() >= 0) && (server.arg("w").toInt() <= 255)){
main_color.white = server.arg("w").toInt();
}
}
if (server.arg("rgb2") != "") {
uint32_t rgb2 = (uint32_t) strtoul(server.arg("rgb2").c_str(), NULL, 16);
back_color.white = ((rgb2 >> 24) & 0xFF);
back_color.red = ((rgb2 >> 16) & 0xFF);
back_color.green = ((rgb2 >> 8) & 0xFF);
back_color.blue = ((rgb2 >> 0) & 0xFF);
} else {
if ((server.arg("r2") != "") && (server.arg("r2").toInt() >= 0) && (server.arg("r2").toInt() <= 255)) {
back_color.red = server.arg("r2").toInt();
}
if ((server.arg("g2") != "") && (server.arg("g2").toInt() >= 0) && (server.arg("g2").toInt() <= 255)) {
back_color.green = server.arg("g2").toInt();
}
if ((server.arg("b2") != "") && (server.arg("b2").toInt() >= 0) && (server.arg("b2").toInt() <= 255)) {
back_color.blue = server.arg("b2").toInt();
}
if ((server.arg("w2") != "") && (server.arg("w2").toInt() >= 0) && (server.arg("w2").toInt() <= 255)){
back_color.white = server.arg("w2").toInt();
}
}
if (server.arg("rgb3") != "") {
uint32_t rgb3 = (uint32_t) strtoul(server.arg("rgb3").c_str(), NULL, 16);
xtra_color.white = ((rgb3 >> 24) & 0xFF);
xtra_color.red = ((rgb3 >> 16) & 0xFF);
xtra_color.green = ((rgb3 >> 8) & 0xFF);
xtra_color.blue = ((rgb3 >> 0) & 0xFF);
} else {
if ((server.arg("r3") != "") && (server.arg("r3").toInt() >= 0) && (server.arg("r3").toInt() <= 255)) {
xtra_color.red = server.arg("r3").toInt();
}
if ((server.arg("g3") != "") && (server.arg("g3").toInt() >= 0) && (server.arg("g3").toInt() <= 255)) {
xtra_color.green = server.arg("g3").toInt();
}
if ((server.arg("b3") != "") && (server.arg("b3").toInt() >= 0) && (server.arg("b3").toInt() <= 255)) {
xtra_color.blue = server.arg("b3").toInt();
}
if ((server.arg("w3") != "") && (server.arg("w3").toInt() >= 0) && (server.arg("w3").toInt() <= 255)){
xtra_color.white = server.arg("w3").toInt();
}
}
main_color.red = constrain(main_color.red, 0, 255);
main_color.green = constrain(main_color.green, 0, 255);
main_color.blue = constrain(main_color.blue, 0, 255);
main_color.white = constrain(main_color.white, 0, 255);
back_color.red = constrain(back_color.red, 0, 255);
back_color.green = constrain(back_color.green, 0, 255);
back_color.blue = constrain(back_color.blue, 0, 255);
back_color.white = constrain(back_color.white, 0, 255);
xtra_color.red = constrain(xtra_color.red, 0, 255);
xtra_color.green = constrain(xtra_color.green, 0, 255);
xtra_color.blue = constrain(xtra_color.blue, 0, 255);
xtra_color.white = constrain(xtra_color.white, 0, 255);
// Speed
if ((server.arg("s") != "") && (server.arg("s").toInt() >= 0) && (server.arg("s").toInt() <= 255)) {
ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255);
mode = SET; mode = SET;
getArgs(); _updateSegState = true;
getStatusJSON(); }
}); //Mode
if ((server.arg("m") != "") && (server.arg("m").toInt() >= 0) && (server.arg("m").toInt() <= strip->getModeCount())) {
ws2812fx_mode = constrain(server.arg("m").toInt(), 0, strip->getModeCount() - 1);
if (ws2812fx_mode != strip->getMode(segment)) {
mode = SET;
_updateSegState = true;
}
}
// Brightness
if ((server.arg("c") != "") && (server.arg("c").toInt() >= 0) && (server.arg("c").toInt() <= 100)) {
brightness = constrain((int) server.arg("c").toInt() * 2.55, 0, 255);
} else if ((server.arg("p") != "") && (server.arg("p").toInt() >= 0) && (server.arg("p").toInt() <= 255)) {
brightness = constrain(server.arg("p").toInt(), 0, 255);
}
if (strip->getBrightness() != brightness) {
mode = SET;
_updateState = true;
}
DBG_OUTPUT_PORT.printf("Get Args: %s\r\n", listStateJSONfull());
getStateJSON();
#if defined(ENABLE_STATE_SAVE)
if (_updateState) {
DBG_OUTPUT_PORT.println("Saving stripstate.json!");
if(!save_state.active()) save_state.once(3, tickerSaveState);
}
if (_updateSegState) {
DBG_OUTPUT_PORT.println("Saving stripstate_segment.json!");
if(!save_seg_state.active()) save_seg_state.once(3, tickerSaveSegmentState);
}
#endif
_updateState = false;
_updateSegState = false;
});
-33
View File
@@ -1,33 +0,0 @@
char * listStatusJSON2() {
const size_t bufferSize = 10*JSON_ARRAY_SIZE(12) + 10*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(12) + 600;
DynamicJsonDocument jsonBuffer(bufferSize);
JsonObject root = jsonBuffer.to<JsonObject>();
root["mode"] = (uint8_t) mode;
root["brightness"] = brightness;
for(uint8_t i=0; i<10; i++) {
char int2char[3];
itoa(i, int2char, 10);
JsonObject segments = root.createNestedObject(int2char);
segments["ws2812fx_mode"] = strip->getMode(i);
segments["ws2812fx_mode_name"] = strip->getModeName(strip->getMode(i));
segments["speed"] = ws2812fx_speed;
JsonArray color = segments.createNestedArray("color");
color.add(main_color.white);
color.add(main_color.red);
color.add(main_color.green);
color.add(main_color.blue);
color.add(back_color.white);
color.add(back_color.red);
color.add(back_color.green);
color.add(back_color.blue);
color.add(xtra_color.white);
color.add(xtra_color.red);
color.add(xtra_color.green);
color.add(xtra_color.blue);
}
uint16_t msg_len = measureJson(root) + 1;
char * buffer = (char *) malloc(msg_len);
serializeJson(root, buffer, msg_len);
jsonBuffer.clear();
return buffer;
}
+1 -1
View File
@@ -1 +1 @@
#define SKETCH_VERSION "3.0.0.BETA1" #define SKETCH_VERSION "3.1.0.ALPHA2"
+6
View File
@@ -195,4 +195,10 @@
* removal of saving to EEPROM * removal of saving to EEPROM
* first integration of multi segments * first integration of multi segments
* *
* * 3 October 2019
* Version Bump to 3.1.0.ALPHA2
* further code changes
* further integration of multi segments
* integration of multi segments to GUI
*
*/ */