diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index 9dba564..707e68a 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -14,8 +14,9 @@ #include #include #include -#include - +#if ENABLE_STATE_SAVE == 0 + #include +#endif #include //https://github.com/Links2004/arduinoWebSockets #include @@ -37,7 +38,7 @@ // *************************************************************************** #include WiFiClient espClient; - PubSubClient mqtt_client(espClient); + PubSubClient* mqtt_client = NULL; #endif #if ENABLE_MQTT == 1 @@ -46,15 +47,15 @@ // *************************************************************************** #include //https://github.com/marvinroger/async-mqtt-client //https://github.com/me-no-dev/ESPAsyncTCP - AsyncMqttClient amqttClient; + AsyncMqttClient* mqtt_client = NULL; WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; #endif #endif #if defined(ARDUINOJSON_VERSION) - #if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR == 7) - #error "Install ArduinoJson v6.7.0-beta" + #if !(ARDUINOJSON_VERSION_MAJOR == 6 and ARDUINOJSON_VERSION_MINOR == 9) + #error "Install ArduinoJson v6.9.x" #endif #endif @@ -64,7 +65,7 @@ // *************************************************************************** #include //https://github.com/me-no-dev/ESPAsyncUDP #include //https://github.com/forkineye/ESPAsyncE131 - ESPAsyncE131 e131(END_UNIVERSE - START_UNIVERSE + 1); + ESPAsyncE131* e131 = NULL; //(END_UNIVERSE - START_UNIVERSE + 1); #endif #if defined(ENABLE_REMOTE) @@ -76,6 +77,12 @@ #include #endif +#if defined(USE_HTML_MIN_GZ) +#include "htm_index_gz.h" +#include "htm_edit_gz.h" +#endif + + // *************************************************************************** // Instanciate HTTP(80) / WebSockets(81) Server // *************************************************************************** @@ -97,59 +104,70 @@ WebSocketsServer webSocket = WebSocketsServer(81); #endif // *************************************************************************** -// Load libraries / Instanciate WS2812FX library +// Load and instanciate WS2812FX library // *************************************************************************** #include // https://github.com/kitesurfer1404/WS2812FX -#if defined(RGBW) - WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRBW + NEO_KHZ800); -#else - WS2812FX strip = WS2812FX(NUMLEDS, PIN, NEO_GRB + NEO_KHZ800); -#endif -const uint8_t ws2812fx_options = SIZE_SMALL + FADE_MEDIUM; // WS2812FX setSegment OPTIONS, see: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md - -// 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. +WS2812FX* strip = NULL; #if defined(USE_WS2812FX_DMA) - #if USE_WS2812FX_DMA == 0// Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #if defined(RGBW) - NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 4); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #include + + #if USE_WS2812FX_DMA == 0 // Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #if !defined(LED_TYPE_WS2811) + NeoEsp8266Dma800KbpsMethod* dma = NULL ; //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) #else - NeoEsp8266Dma800KbpsMethod dma = NeoEsp8266Dma800KbpsMethod(NUMLEDS, 3); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + NeoEsp8266Dma400KbpsMethod* dma = NULL; //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #endif - //NeoEsp8266Dma400KbpsMethod dma = NeoEsp8266Dma400KbpsMethod(NUMLEDS, 3); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #endif #if USE_WS2812FX_DMA == 1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #if defined(RGBW) - NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 4); + #if !defined(LED_TYPE_WS2811) + NeoEsp8266Uart0800KbpsMethod* dma = NULL; //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) #else - NeoEsp8266Uart0800KbpsMethod dma = NeoEsp8266Uart0800KbpsMethod(NUMLEDS, 3); + NeoEsp8266Uart0400KbpsMethod* dma = NULL; //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #endif #endif #if USE_WS2812FX_DMA == 2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods - #include - #if defined(RGBW) - NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 4); + #if !defined(LED_TYPE_WS2811) + NeoEsp8266Uart1800KbpsMethod* dma = NULL; //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) #else - NeoEsp8266Uart1800KbpsMethod dma = NeoEsp8266Uart1800KbpsMethod(NUMLEDS, 3); + NeoEsp8266Uart1400KbpsMethod* dma = NULL; //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #endif #endif + + void initDMA(uint16_t stripSize = NUMLEDS){ + if (dma) delete dma; + uint8_t ledcolors = 3; + if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) { + ledcolors = 4; + } + #if USE_WS2812FX_DMA == 0 // Uses GPIO3/RXD0/RX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #if !defined(LED_TYPE_WS2811) + dma = new NeoEsp8266Dma800KbpsMethod(stripSize, ledcolors); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #else + dma = new NeoEsp8266Dma400KbpsMethod(stripSize, ledcolors); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) + #endif + #endif + #if USE_WS2812FX_DMA == 1 // Uses UART1: GPIO1/TXD0/TX, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #if !defined(LED_TYPE_WS2811) + dma = new NeoEsp8266Uart0800KbpsMethod(stripSize, ledcolors); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #else + dma = new NeoEsp8266Uart0400KbpsMethod(stripSize, ledcolors); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) + #endif + #endif + #if USE_WS2812FX_DMA == 2 // Uses UART2: GPIO2/TXD1/D4, more info: https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods + #if !defined(LED_TYPE_WS2811) + dma = new NeoEsp8266Uart1800KbpsMethod(stripSize, ledcolors); //800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) + #else + dma = new NeoEsp8266Uart1400KbpsMethod(stripSize, ledcolors); //400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) + #endif + #endif + dma->Initialize(); + } + void DMA_Show(void) { - if(dma.IsReadyToUpdate()) { - memcpy(dma.getPixels(), strip.getPixels(), dma.getPixelsSize()); - dma.Update(); + if(dma->IsReadyToUpdate()) { + memcpy(dma->getPixels(), strip->getPixels(), dma->getPixelsSize()); + dma->Update(); } } #endif @@ -170,8 +188,7 @@ Ticker ticker; #endif #endif -void tick() -{ +void tick() { //toggle state int state = digitalRead(LED_BUILTIN); // get the current state of GPIO1 pin digitalWrite(LED_BUILTIN, !state); // set pin to the opposite state @@ -202,8 +219,9 @@ String getValue(String data, char separator, int index) strIndex[1] = (i == maxIndex) ? i+1 : i; } } - - return found>index ? data.substring(strIndex[0], strIndex[1]) : ""; + String return_value = data.substring(strIndex[0], strIndex[1]); + return_value.replace(" ", ""); + return found>index ? return_value : ""; } // *************************************************************************** @@ -217,12 +235,6 @@ void configModeCallback (WiFiManager *myWiFiManager) { DBG_OUTPUT_PORT.println(myWiFiManager->getConfigPortalSSID()); //entered config mode, make led toggle faster ticker.attach(0.2, tick); - - uint16_t i; - for (i = 0; i < strip.numPixels(); i++) { - strip.setPixelColor(i, 0, 0, 0, 255); - } - strip.show(); } //callback notifying us of the need to save config @@ -248,6 +260,123 @@ void saveConfigCallback () { #include "mode_tv.h" #endif +#if defined(CUSTOM_WS2812FX_ANIMATIONS) +// *************************************************************************** +// Include: Custom animations +// *************************************************************************** + #include "mode_custom_ws2812fx_animations.h" // Add animations in this file +#endif + + +// 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 ){ + if (strip != NULL) { + DBG_OUTPUT_PORT.println("Deleting strip!"); + delete(strip); + WS2812FXStripSettings.stripSize = stripSize; + strcpy(WS2812FXStripSettings.RGBOrder, RGBOrder); + WS2812FXStripSettings.pin = pin; + WS2812FXStripSettings.fxoptions = fxoptions; + } + DBG_OUTPUT_PORT.println("Initializing strip!"); +#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. + +#if defined(CUSTOM_WS2812FX_ANIMATIONS) + if (heat != NULL) { + delete(heat); + } + heat = new byte [WS2812FXStripSettings.stripSize]; +#endif +#if defined(ENABLE_TV) + if (ledStates != NULL) { + delete(ledStates); + } + ledStates = new uint8_t [WS2812FXStripSettings.stripSize]; +#endif +/* + if (ledstates != NULL) { + delete(ledstates); + } + ledStates = new LEDState ledstates[WS2812FXStripSettings.stripSize]; +*/ + strip->init(); + #if defined(USE_WS2812FX_DMA) + initDMA(stripSize); + strip->setCustomShow(DMA_Show); + #endif + strip->setBrightness(brightness); +//parameters: index, start, stop, mode, color, speed, options + strip->setSegment(0, 0, WS2812FXStripSettings.stripSize - 1, ws2812fx_mode, hex_colors, convertSpeed(ws2812fx_speed), WS2812FXStripSettings.fxoptions); +#if defined(CUSTOM_WS2812FX_ANIMATIONS) + strip->setCustomMode(0, F("Fire 2012"), myCustomEffect0); +//strip->setCustomMode(1, F("CustEffect"), myCustomEffect1); +#endif +} + +#if defined(ENABLE_MQTT) +void initMqtt() { + DBG_OUTPUT_PORT.println("Initializing Mqtt_Client!"); + // *************************************************************************** + // Configure MQTT + // *************************************************************************** + #if ENABLE_MQTT == 0 + mqtt_client = new PubSubClient(espClient); + #endif + #if ENABLE_MQTT == 1 + mqtt_client = new AsyncMqttClient(); + #endif + + #if defined(ENABLE_MQTT_HOSTNAME_CHIPID) + snprintf(mqtt_clientid, sizeof(mqtt_clientid), "%s-%08X", HOSTNAME, ESP.getChipId()); + #else + snprintf(mqtt_clientid, sizeof(mqtt_clientid), "%s", HOSTNAME); + #endif + snprintf(mqtt_will_topic, sizeof(mqtt_will_topic), "%s/config", HOSTNAME); + snprintf(mqtt_intopic, sizeof(mqtt_intopic), "%s/in", HOSTNAME); + snprintf(mqtt_outtopic, sizeof(mqtt_outtopic), "%s/out", HOSTNAME); + #if defined(MQTT_HOME_ASSISTANT_SUPPORT) + snprintf(mqtt_ha_config, sizeof(mqtt_ha_config), "homeassistant/light/%s/config", HOSTNAME); + snprintf(mqtt_ha_state_in, sizeof(mqtt_ha_state_in), "home/%s_ha/state/in", HOSTNAME); + snprintf(mqtt_ha_state_out, sizeof(mqtt_ha_state_out), "home/%s_ha/state/out", HOSTNAME); + #endif + if ((strlen(mqtt_host) != 0) && (mqtt_port != 0)) { + #if ENABLE_MQTT == 0 + DBG_OUTPUT_PORT.printf("MQTT active: %s:%d\r\n", mqtt_host, mqtt_port); + mqtt_client->setServer(mqtt_host, mqtt_port); + mqtt_client->setCallback(mqtt_callback); + #endif + #if ENABLE_MQTT == 1 + DBG_OUTPUT_PORT.printf("AMQTT active: %s:%d\r\n", mqtt_host, mqtt_port); + mqtt_client->onConnect(onMqttConnect); + mqtt_client->onDisconnect(onMqttDisconnect); + mqtt_client->onMessage(onMqttMessage); + if ((strlen(mqtt_user) != 0) || (strlen(mqtt_pass) != 0)) mqtt_client->setCredentials(mqtt_user, mqtt_pass); + mqtt_client->setClientId(mqtt_clientid); + mqtt_client->setWill(mqtt_will_topic, 2, true, mqtt_will_payload, 0); + mqtt_client->setServer(mqtt_host, mqtt_port); + connectToMqtt(); + #endif + } +} +#endif + + // *************************************************************************** // MAIN Setup // *************************************************************************** @@ -255,27 +384,30 @@ void setup() { // system_update_cpu_freq(160); DBG_OUTPUT_PORT.begin(115200); + delay(500); + DBG_OUTPUT_PORT.println(""); + DBG_OUTPUT_PORT.println("Starting...Main Setup"); +#if ENABLE_STATE_SAVE == 0 EEPROM.begin(512); - +#endif // set builtin led pin as output pinMode(LED_BUILTIN, OUTPUT); // button pin setup #if defined(ENABLE_BUTTON) + DBG_OUTPUT_PORT.printf("Enabled Button Mode on PIN: %d\r\n", ENABLE_BUTTON); pinMode(ENABLE_BUTTON,INPUT_PULLUP); #endif #if defined(ENABLE_BUTTON_GY33) + DBG_OUTPUT_PORT.printf("Enabled GY-33 Button Mode on PIN: %d\r\n", ENABLE_BUTTON_GY33); pinMode(ENABLE_BUTTON_GY33, INPUT_PULLUP); if (tcs.begin()) { DBG_OUTPUT_PORT.println("Found GY-33 sensor"); } else { - DBG_OUTPUT_PORT.println("No GY33 sensor found ... check your connections"); + DBG_OUTPUT_PORT.println("No GY33 sensor found ... check your I2C connections"); } #endif -DBG_OUTPUT_PORT.println(""); -DBG_OUTPUT_PORT.println("Starting...."); - // start ticker with 0.5 because we start in AP mode and try to connect ticker.attach(0.5, tick); @@ -288,92 +420,95 @@ DBG_OUTPUT_PORT.println("Starting...."); while (dir.next()) { String fileName = dir.fileName(); size_t fileSize = dir.fileSize(); - DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str()); + DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\r\n", fileName.c_str(), formatBytes(fileSize).c_str()); } FSInfo fs_info; SPIFFS.info(fs_info); - DBG_OUTPUT_PORT.printf("FS Usage: %d/%d bytes\n\n", fs_info.usedBytes, fs_info.totalBytes); + DBG_OUTPUT_PORT.printf("FS Usage: %d/%d bytes\r\n", fs_info.usedBytes, fs_info.totalBytes); } - wifi_station_set_hostname(const_cast(HOSTNAME)); - - // *************************************************************************** - // Setup: Neopixel - // *************************************************************************** - strip.init(); - #if defined(USE_WS2812FX_DMA) - dma.Initialize(); - strip.setCustomShow(DMA_Show); - #endif - strip.setBrightness(brightness); -// parameters: index, start, stop, mode, color, speed, options - strip.setSegment(0, 0, NUMLEDS-1, FX_MODE_COMET, hex_colors, convertSpeed(ws2812fx_speed), ws2812fx_options); - strip.start(); - // *************************************************************************** // Setup: WiFiManager // *************************************************************************** // The extra parameters to be configured (can be either global or just in the setup) // After connecting, parameter.getValue() will get you the configured value // id/name placeholder/prompt default length - #if defined(ENABLE_MQTT) - #if defined(ENABLE_STATE_SAVE) - #if ENABLE_STATE_SAVE == 1 - (readConfigFS()) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Read success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Read failure!"); - #endif - #if ENABLE_STATE_SAVE == 0 - String settings_available = readEEPROM(134, 1); - if (settings_available == "1") { - readEEPROM(0, 64).toCharArray(mqtt_host, 64); // 0-63 - readEEPROM(64, 6).toCharArray(mqtt_port, 6); // 64-69 - readEEPROM(70, 32).toCharArray(mqtt_user, 32); // 70-101 - readEEPROM(102, 32).toCharArray(mqtt_pass, 32); // 102-133 - DBG_OUTPUT_PORT.printf("MQTT host: %s\n", mqtt_host); - DBG_OUTPUT_PORT.printf("MQTT port: %s\n", mqtt_port); - DBG_OUTPUT_PORT.printf("MQTT user: %s\n", mqtt_user); - DBG_OUTPUT_PORT.printf("MQTT pass: %s\n", mqtt_pass); - } - #endif - #endif - WiFiManagerParameter custom_mqtt_host("host", "MQTT hostname", mqtt_host, 64); - WiFiManagerParameter custom_mqtt_port("port", "MQTT port", mqtt_port, 6); - WiFiManagerParameter custom_mqtt_user("user", "MQTT user", mqtt_user, 32); - WiFiManagerParameter custom_mqtt_pass("pass", "MQTT pass", mqtt_pass, 32); + +#if defined(ENABLE_STATE_SAVE) + //Strip Config + #if ENABLE_STATE_SAVE == 1 + (readConfigFS()) ? DBG_OUTPUT_PORT.println("WiFiManager config FS read success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Read failure!"); + delay(500); + (readStateFS()) ? DBG_OUTPUT_PORT.println("Strip state config FS read Success!") : DBG_OUTPUT_PORT.println("Strip state config FS read failure!"); #endif + #if ENABLE_STATE_SAVE == 0 + (setConfByConfString(readEEPROM(0, 222)))? DBG_OUTPUT_PORT.println("WiFiManager config EEPROM read success!"): DBG_OUTPUT_PORT.println("WiFiManager config EEPROM Read failure!"); + (setModeByStateString(readEEPROM(256, 66)))? DBG_OUTPUT_PORT.println("Strip state config EEPROM read Success!") : DBG_OUTPUT_PORT.println("Strip state config EEPROM read failure!"); + #endif + char tmp_strip_size[6], tmp_fxoptions[5], tmp_rgbOrder[5]; //needed tempararily for WiFiManager Settings + WiFiManagerParameter custom_hostname("hostname", "Hostname", HOSTNAME, 64, " maxlength=64"); + #if defined(ENABLE_MQTT) + char tmp_mqtt_port[6]; //needed tempararily for WiFiManager Settings + WiFiManagerParameter custom_mqtt_host("host", "MQTT hostname", mqtt_host, 64, " maxlength=64"); + snprintf(tmp_mqtt_port, sizeof(tmp_mqtt_port), "%d", mqtt_port); + WiFiManagerParameter custom_mqtt_port("port", "MQTT port", tmp_mqtt_port, 5, " maxlength=5 type=\"number\""); + WiFiManagerParameter custom_mqtt_user("user", "MQTT user", mqtt_user, 32, " maxlength=32"); + WiFiManagerParameter custom_mqtt_pass("pass", "MQTT pass", mqtt_pass, 32, " maxlength=32 type=\"password\""); + #endif + snprintf(tmp_strip_size, sizeof(tmp_strip_size), "%d", WS2812FXStripSettings.stripSize); + WiFiManagerParameter custom_strip_size("strip_size", "Number of LEDs", tmp_strip_size, 4, " maxlength=4 type=\"number\""); + #if !defined(USE_WS2812FX_DMA) + char tmp_led_pin[3]; + snprintf(tmp_led_pin, sizeof(tmp_led_pin), "%d", WS2812FXStripSettings.pin); + WiFiManagerParameter custom_led_pin("led_pin", "LED GPIO", tmp_led_pin, 2, " maxlength=2 type=\"number\""); + #endif + snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", WS2812FXStripSettings.RGBOrder); + WiFiManagerParameter custom_rgbOrder("rgbOrder", "RGBOrder", tmp_rgbOrder, 4, " maxlength=4"); + snprintf(tmp_fxoptions, sizeof(tmp_fxoptions), "%d", WS2812FXStripSettings.fxoptions); + WiFiManagerParameter custom_fxoptions("fxoptions", "fxOptions", tmp_fxoptions, 3, " maxlength=3"); +#endif + //Local intialization. Once its business is done, there is no need to keep it around + wifi_station_set_hostname(const_cast(HOSTNAME)); WiFiManager wifiManager; //reset settings - for testing //wifiManager.resetSettings(); //set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode wifiManager.setAPCallback(configModeCallback); - + //set config save notify callback + wifiManager.setSaveConfigCallback(saveConfigCallback); + + wifiManager.addParameter(&custom_hostname); #if defined(ENABLE_MQTT) - //set config save notify callback - wifiManager.setSaveConfigCallback(saveConfigCallback); - //add all your parameters here wifiManager.addParameter(&custom_mqtt_host); wifiManager.addParameter(&custom_mqtt_port); wifiManager.addParameter(&custom_mqtt_user); wifiManager.addParameter(&custom_mqtt_pass); #endif - + wifiManager.addParameter(&custom_strip_size); + #if !defined(USE_WS2812FX_DMA) + wifiManager.addParameter(&custom_led_pin); + #endif + wifiManager.addParameter(&custom_rgbOrder); + wifiManager.addParameter(&custom_fxoptions); + WiFi.setSleepMode(WIFI_NONE_SLEEP); // Uncomment if you want to restart ESP8266 if it cannot connect to WiFi. // Value in brackets is in seconds that WiFiManger waits until restart - #if defined(WIFIMGR_PORTAL_TIMEOUT) +#if defined(WIFIMGR_PORTAL_TIMEOUT) wifiManager.setConfigPortalTimeout(WIFIMGR_PORTAL_TIMEOUT); - #endif +#endif // Uncomment if you want to set static IP // Order is: IP, Gateway and Subnet - #if defined(WIFIMGR_SET_MANUAL_IP) +#if defined(WIFIMGR_SET_MANUAL_IP) wifiManager.setSTAStaticIPConfig(IPAddress(_ip[0], _ip[1], _ip[2], _ip[3]), IPAddress(_gw[0], _gw[1], _gw[2], _gw[3]), IPAddress(_sn[0], _sn[1], _sn[2], _sn[3])); - #endif +#endif //fetches ssid and pass and tries to connect //if it does not connect it starts an access point with the specified name @@ -385,38 +520,46 @@ DBG_OUTPUT_PORT.println("Starting...."); ESP.reset(); //Will be removed when upgrading to standalone offline McLightingUI version delay(1000); //Will be removed when upgrading to standalone offline McLightingUI version } - - #if defined(ENABLE_MQTT) - //read updated parameters - strcpy(mqtt_host, custom_mqtt_host.getValue()); - strcpy(mqtt_port, custom_mqtt_port.getValue()); - strcpy(mqtt_user, custom_mqtt_user.getValue()); - strcpy(mqtt_pass, custom_mqtt_pass.getValue()); - - //save the custom parameters to FS/EEPROM - #if defined(ENABLE_STATE_SAVE) - #if ENABLE_STATE_SAVE == 1 - (writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!"); - #endif - #if ENABLE_STATE_SAVE == 0 - if (shouldSaveConfig) { - DBG_OUTPUT_PORT.println("Saving WiFiManager config"); - writeEEPROM(0, 64, mqtt_host); // 0-63 - writeEEPROM(64, 6, mqtt_port); // 64-69 - writeEEPROM(70, 32, mqtt_user); // 70-101 - writeEEPROM(102, 32, mqtt_pass); // 102-133 - writeEEPROM(134, 1, "1"); // 134 --> always "1" - EEPROM.commit(); - } - #endif + //save the custom parameters to FS/EEPROM + #if defined(ENABLE_STATE_SAVE) + strcpy(HOSTNAME, custom_hostname.getValue()); + #if defined(ENABLE_MQTT) + //read updated parameters + strcpy(mqtt_host, custom_mqtt_host.getValue()); + mqtt_port = atoi(custom_mqtt_port.getValue()); + strcpy(mqtt_user, custom_mqtt_user.getValue()); + strcpy(mqtt_pass, custom_mqtt_pass.getValue()); #endif - - #if ENABLE_MQTT == 1 - wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); - wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); + strcpy(tmp_strip_size, custom_strip_size.getValue()); + WS2812FXStripSettings.stripSize = atoi(custom_strip_size.getValue()); + #if !defined(USE_WS2812FX_DMA) + checkPin(atoi(custom_led_pin.getValue())); + #endif + strcpy(tmp_rgbOrder, custom_rgbOrder.getValue()); + checkRGBOrder(tmp_rgbOrder); + WS2812FXStripSettings.fxoptions = atoi(custom_fxoptions.getValue()); + #if ENABLE_STATE_SAVE == 1 + (writeConfigFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("WiFiManager config FS Save success!"): DBG_OUTPUT_PORT.println("WiFiManager config FS Save failure!"); + (writeStateFS(shouldSaveConfig)) ? DBG_OUTPUT_PORT.println("State config FS Save success!"): DBG_OUTPUT_PORT.println("State config FS Save failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + if (shouldSaveConfig) { + char last_conf[223]; + DBG_OUTPUT_PORT.println("Saving WiFiManager config"); + #if defined(ENABLE_MQTT) + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, mqtt_host, mqtt_port, mqtt_user, mqtt_pass, WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #else + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, "", "", "", "", WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #endif + writeEEPROM(0, 222, last_conf); + EEPROM.commit(); + } #endif #endif + + initStrip(); + //if you get here you have connected to the WiFi DBG_OUTPUT_PORT.println("connected...yeey :)"); ticker.detach(); @@ -425,89 +568,61 @@ DBG_OUTPUT_PORT.println("Starting...."); //switch LED off //digitalWrite(LED_BUILTIN, HIGH); - #if defined(ENABLE_OTA) - #if ENABLE_OTA == 0 - // *************************************************************************** - // Configure Arduino OTA - // *************************************************************************** - DBG_OUTPUT_PORT.println("Arduino OTA activated."); - - // Port defaults to 8266 - ArduinoOTA.setPort(8266); - - // Hostname defaults to esp8266-[ChipID] - ArduinoOTA.setHostname(HOSTNAME); - - // No authentication by default - // ArduinoOTA.setPassword("admin"); - - // Password can be set with it's md5 value as well - // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 - // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); - - ArduinoOTA.onStart([]() { - DBG_OUTPUT_PORT.println("Arduino OTA: Start updating"); - }); - ArduinoOTA.onEnd([]() { - DBG_OUTPUT_PORT.println("Arduino OTA: End"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - DBG_OUTPUT_PORT.printf("Arduino OTA Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - DBG_OUTPUT_PORT.printf("Arduino OTA Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Auth Failed"); - else if (error == OTA_BEGIN_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Begin Failed"); - else if (error == OTA_CONNECT_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Connect Failed"); - else if (error == OTA_RECEIVE_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Receive Failed"); - else if (error == OTA_END_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: End Failed"); - }); - - ArduinoOTA.begin(); - DBG_OUTPUT_PORT.println(""); - #endif - #if ENABLE_OTA == 1 - httpUpdater.setup(&server, "/update"); - #endif - #endif - +#if defined(ENABLE_OTA) + #if ENABLE_OTA == 0 // *************************************************************************** - // Configure MQTT + // Configure Arduino OTA // *************************************************************************** - #if defined(ENABLE_MQTT_HOSTNAME_CHIPID) - snprintf(mqtt_clientid, 64, "%s-%08X", HOSTNAME, ESP.getChipId()); - #endif + DBG_OUTPUT_PORT.println("Arduino OTA activated."); - #if defined(ENABLE_MQTT) - snprintf(mqtt_intopic, sizeof mqtt_intopic, "%s/in", HOSTNAME); - snprintf(mqtt_outtopic, sizeof mqtt_outtopic, "%s/out", HOSTNAME); - #if ENABLE_MQTT == 0 - if (mqtt_host != "" && atoi(mqtt_port) > 0) { - DBG_OUTPUT_PORT.printf("MQTT active: %s:%s\n", mqtt_host, mqtt_port); - mqtt_client.setServer(mqtt_host, atoi(mqtt_port)); - mqtt_client.setCallback(mqtt_callback); - } - #endif - - #if ENABLE_MQTT == 1 - if (mqtt_host != "" && atoi(mqtt_port) > 0) { - DBG_OUTPUT_PORT.printf("AMQTT active: %s:%s\n", mqtt_host, mqtt_port); - amqttClient.onConnect(onMqttConnect); - amqttClient.onDisconnect(onMqttDisconnect); - amqttClient.onMessage(onMqttMessage); - amqttClient.setServer(mqtt_host, atoi(mqtt_port)); - if (mqtt_user != "" or mqtt_pass != "") amqttClient.setCredentials(mqtt_user, mqtt_pass); - amqttClient.setClientId(mqtt_clientid); - - connectToMqtt(); - } - #endif - #if defined(ENABLE_HOMEASSISTANT) - snprintf(mqtt_ha_state_in, sizeof mqtt_ha_state_in, "home/%s_ha/state/in", HOSTNAME); - snprintf(mqtt_ha_state_out, sizeof mqtt_ha_state_out , "home/%s_ha/state/out", HOSTNAME); - #endif - #endif + // Port defaults to 8266 + ArduinoOTA.setPort(8266); + // Hostname defaults to esp8266-[ChipID] + ArduinoOTA.setHostname(HOSTNAME); + + // No authentication by default + // ArduinoOTA.setPassword("admin"); + + // Password can be set with it's md5 value as well + // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 + // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); + + ArduinoOTA.onStart([]() { + DBG_OUTPUT_PORT.println("Arduino OTA: Start updating"); + }); + ArduinoOTA.onEnd([]() { + DBG_OUTPUT_PORT.println("Arduino OTA: End"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + DBG_OUTPUT_PORT.printf("Arduino OTA Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + DBG_OUTPUT_PORT.printf("Arduino OTA Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Auth Failed"); + else if (error == OTA_BEGIN_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Begin Failed"); + else if (error == OTA_CONNECT_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: Receive Failed"); + else if (error == OTA_END_ERROR) DBG_OUTPUT_PORT.println("Arduino OTA: End Failed"); + }); + + ArduinoOTA.begin(); + DBG_OUTPUT_PORT.println(""); + #endif + #if ENABLE_OTA == 1 + httpUpdater.setup(&server, "/update"); + #endif +#endif + +#if defined(ENABLE_MQTT) + initMqtt(); +#endif + +#if ENABLE_MQTT == 1 + wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); + wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); +#endif + // *************************************************************************** // Setup: MDNS responder // *************************************************************************** @@ -527,340 +642,13 @@ DBG_OUTPUT_PORT.println("Starting...."); DBG_OUTPUT_PORT.println(""); - // *************************************************************************** // Setup: WebSocket server // *************************************************************************** webSocket.begin(); webSocket.onEvent(webSocketEvent); - // *************************************************************************** - // Setup: SPIFFS Webserver handler - // *************************************************************************** - //list directory - server.on("/list", HTTP_GET, handleFileList); - //load editor - server.on("/edit", HTTP_GET, []() { - if (!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound"); - }); - //create file - server.on("/edit", HTTP_PUT, handleFileCreate); - //delete file - server.on("/edit", HTTP_DELETE, handleFileDelete); - //first callback is called after the request has ended with all parsed arguments - //second callback handles file uploads at that location - server.on("/edit", HTTP_POST, []() { - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "text/plain", ""); - }, handleFileUpload); - //get heap status, analog input value and all GPIO statuses in one json call - server.on("/esp_status", HTTP_GET, []() { - const size_t bufferSize = JSON_OBJECT_SIZE(31) + 600; - DynamicJsonDocument jsonBuffer(bufferSize); - JsonObject json = jsonBuffer.to(); - json["HOSTNAME"] = HOSTNAME; - json["version"] = SKETCH_VERSION; - json["heap"] = ESP.getFreeHeap(); - json["sketch_size"] = ESP.getSketchSize(); - json["free_sketch_space"] = ESP.getFreeSketchSpace(); - json["flash_chip_size"] = ESP.getFlashChipSize(); - json["flash_chip_real_size"] = ESP.getFlashChipRealSize(); - json["flash_chip_speed"] = ESP.getFlashChipSpeed(); - json["sdk_version"] = ESP.getSdkVersion(); - json["core_version"] = ESP.getCoreVersion(); - json["cpu_freq"] = ESP.getCpuFreqMHz(); - json["chip_id"] = ESP.getFlashChipId(); - #if defined(USE_WS2812FX_DMA) - #if USE_WS2812FX_DMA == 0 - json["animation_lib"] = "WS2812FX_DMA"; - json["ws2812_pin"] = 3; - #endif - #if USE_WS2812FX_DMA == 1 - json["animation_lib"] = "WS2812FX_UART1"; - json["ws2812_pin"] = 2; - #endif - #if USE_WS2812FX_DMA == 2 - json["animation_lib"] = "WS2812FX_UART2"; - json["ws2812_pin"] = 1; - #endif - #else - json["animation_lib"] = "WS2812FX"; - json["ws2812_pin"] = PIN; - #endif - json["number_leds"] = NUMLEDS; - #if defined(RGBW) - json["rgbw_mode"] = "ON"; - #else - json["rgbw_mode"] = "OFF"; - #endif - #if defined(ENABLE_BUTTON) - json["button_mode"] = "ON"; - json["button_pin"] = ENABLE_BUTTON; - #else - json["button_mode"] = "OFF"; - #endif - #if defined(ENABLE_BUTTON_GY33) - json["button_gy33"] = "ON"; - json["gy33_pin"] = ENABLE_BUTTON_GY33; - #else - json["button_gy33"] = "OFF"; - #endif - #if defined(ENABLE_REMOTE) - json["ir_remote"] = "ON"; - json["tsop_ir_pin"] = ENABLE_REMOTE; - #else - json["ir_remote"] = "OFF"; - #endif - #if defined(ENABLE_MQTT) - #if ENABLE_MQTT == 0 - json["mqtt"] = "MQTT"; - #endif - #if ENABLE_MQTT == 1 - json["mqtt"] = "AMQTT"; - #endif - #else - json["mqtt"] = "OFF"; - #endif - #if defined(ENABLE_HOMEASSISTANT) - json["home_assistant"] = "ON"; - #else - json["home_assistant"] = "OFF"; - #endif - #if defined(ENABLE_LEGACY_ANIMATIONS) - json["legacy_animations"] = "ON"; - #else - json["legacy_animations"] = "OFF"; - #endif - #if defined(ENABLE_TV) - json["tv_animation"] = "ON"; - #else - json["tv_animation"] = "OFF"; - #endif - #if defined(ENABLE_E131) - json["e131_animations"] = "ON"; - #else - json["e131_animations"] = "OFF"; - #endif - #if defined(ENABLE_OTA) - #if ENABLE_OTA == 0 - json["ota"] = "ARDUINO"; - #endif - #if ENABLE_OTA == 1 - json["ota"] = "HTTP"; - #endif - #else - json["ota"] = "OFF"; - #endif - #if defined(ENABLE_STATE_SAVE) - #if ENABLE_STATE_SAVE == 1 - json["state_save"] = "SPIFFS"; - #endif - #if ENABLE_STATE_SAVE == 0 - json["state_save"] = "EEPROM"; - #endif - #else - json["state_save"] = "OFF"; - #endif - - String json_str; - serializeJson(json, json_str); - jsonBuffer.clear(); - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "application/json", json_str); - }); - -// *************************************************************************** -// Setup: SPIFFS Webserver handler -// *************************************************************************** - //called when the url is not defined here - //use it to load content from SPIFFS - server.onNotFound([]() { - if (!handleFileRead(server.uri())) - handleNotFound(); - }); - - server.on("/upload", handleMinimalUpload); - - server.on("/restart", []() { - DBG_OUTPUT_PORT.printf("/restart\n"); - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "text/plain", "restarting..." ); - ESP.restart(); - }); - - server.on("/reset_wlan", []() { - DBG_OUTPUT_PORT.printf("/reset_wlan\n"); - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "text/plain", "Resetting WLAN and restarting..." ); - WiFiManager wifiManager; - wifiManager.resetSettings(); - ESP.restart(); - }); - - server.on("/start_config_ap", []() { - DBG_OUTPUT_PORT.printf("/start_config_ap\n"); - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "text/plain", "Starting config AP ..." ); - WiFiManager wifiManager; - wifiManager.startConfigPortal(HOSTNAME); - }); - - server.on("/format_spiffs", []() { - DBG_OUTPUT_PORT.printf("/format_spiffs\n"); - server.send(200, "text/plain", "Formatting SPIFFS ..." ); - SPIFFS.format(); - }); - - server.on("/set_brightness", []() { - getArgs(); - mode = SET_BRIGHTNESS; - getStatusJSON(); - }); - - server.on("/get_brightness", []() { - char str_brightness[3]; - sprintf(str_brightness, "%i", (int) (brightness / 2.55)); - server.sendHeader("Access-Control-Allow-Origin", "*"); - server.send(200, "text/plain", str_brightness ); - DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (brightness / 2.55)); - }); - - server.on("/set_speed", []() { - getArgs(); - mode = SET_SPEED; - getStatusJSON(); - }); - - server.on("/get_speed", []() { - char str_speed[3]; - sprintf(str_speed, "%i", ws2812fx_speed); - 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[9]; - snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", main_color.white, main_color.red, main_color.green, main_color.blue); - 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[9]; - snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", back_color.white, back_color.red, back_color.green, back_color.blue); - 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[9]; - snprintf(rgbcolor, sizeof(rgbcolor), "%02X%02X%02X%02X", xtra_color.white, xtra_color.red, xtra_color.green, xtra_color.blue); - 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("/status", []() { - getStatusJSON(); - }); - - server.on("/off", []() { - mode = OFF; - getStatusJSON(); - }); - - server.on("/auto", []() { - mode = AUTO; - getStatusJSON(); - }); - - server.on("/all", []() { - getArgs(); - ws2812fx_mode = FX_MODE_STATIC; - mode = SET_ALL; - getStatusJSON(); - }); - - #if defined(ENABLE_LEGACY_ANIMATIONS) - server.on("/wipe", []() { - getArgs(); - ws2812fx_mode = FX_MODE_COLOR_WIPE; - mode = SET_ALL; - getStatusJSON(); - }); - - server.on("/rainbow", []() { - getArgs(); - ws2812fx_mode = FX_MODE_RAINBOW; - mode = SET_ALL; - getStatusJSON(); - }); - - server.on("/rainbowcycle", []() { - getArgs(); - ws2812fx_mode = FX_MODE_RAINBOW_CYCLE; - mode = SET_ALL; - getStatusJSON(); - }); - - server.on("/theaterchase", []() { - getArgs(); - ws2812fx_mode = FX_MODE_THEATER_CHASE; - mode = SET_ALL; - getStatusJSON(); - }); - - server.on("/twinklerandom", []() { - getArgs(); - ws2812fx_mode = FX_MODE_TWINKLE_RANDOM; - mode = SET_ALL; - getStatusJSON(); - }); - - server.on("/theaterchaserainbow", []() { - getArgs(); - ws2812fx_mode = FX_MODE_THEATER_CHASE_RAINBOW; - mode = SET_ALL; - getStatusJSON(); - }); - #endif - - #if defined(ENABLE_E131) - server.on("/e131", []() { - mode = E131; - getStatusJSON(); - }); - #endif - - #if defined(ENABLE_TV) - server.on("/tv", []() { - mode = TV; - getStatusJSON(); - }); - #endif - - server.on("/get_modes", []() { - getModesJSON(); - }); - - server.on("/set_mode", []() { - getArgs(); - mode = SET_MODE; - getStatusJSON(); - }); +#include "rest_api.h" server.begin(); @@ -871,38 +659,27 @@ DBG_OUTPUT_PORT.println("Starting...."); #if defined(ENABLE_E131) // Choose one to begin listening for E1.31 data + e131 = new ESPAsyncE131(END_UNIVERSE - START_UNIVERSE + 1); // if (e131.begin(E131_UNICAST)) // Listen via Unicast - if (e131.begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) // Listen via Multicast + if (e131->begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) {// Listen via Multicast DBG_OUTPUT_PORT.println(F("Listening for data...")); - else + } else { DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***")); + } #endif + DBG_OUTPUT_PORT.println("You are here!: 1117"); + prevmode = mode; - #if defined(ENABLE_STATE_SAVE) - #if ENABLE_STATE_SAVE == 1 - (readStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); - #endif - #if ENABLE_STATE_SAVE == 0 - // Load state string from EEPROM - String saved_state_string = readEEPROM(256, 66); - String chk = getValue(saved_state_string, '|', 0); - if (chk == "STA") { - DBG_OUTPUT_PORT.printf("Found saved state: %s\n", saved_state_string.c_str()); - setModeByStateString(saved_state_string); - mode = SET_ALL; - } - #endif - #endif #if defined(ENABLE_BUTTON_GY33) tcs.setConfig(MCU_LED_06, MCU_WHITE_ON); // delay(2000); // tcs.setConfig(MCU_LED_OFF, MCU_WHITE_OFF); #endif - prevmode = mode; #if defined(ENABLE_REMOTE) irrecv.enableIRIn(); // Start the receiver - sprintf(last_state, "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, 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); + snprintf(last_state, sizeof(last_state), "STA|%2d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|%3d", mode, 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); #endif + DBG_OUTPUT_PORT.println("finished Main Setup!"); } // *************************************************************************** @@ -938,52 +715,56 @@ void loop() { WiFi.mode(WIFI_STA); WiFi.begin(); } else { - if (mqtt_host != "" && String(mqtt_port).toInt() > 0 && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { - if (!mqtt_client.connected()) { + if ((strlen(mqtt_host) != 0) && (mqtt_port != 0) && (mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES)) { + if (!mqtt_client->connected()) { #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); #endif DBG_OUTPUT_PORT.println("MQTT disconnected, reconnecting!"); mqtt_reconnect(); } else { - mqtt_client.loop(); + mqtt_client->loop(); } } } #endif + + #if defined(ENABLE_HOMEASSISTANT) + if (new_ha_mqtt_msg) sendState(); + #endif #endif // *************************************************************************** // Simple statemachine that handles the different modes // *************************************************************************** - if ((mode != OFF) && (mode != TV) && (mode != E131)) { // strip.start() is only needed for modes with WS2812FX functionality - if(!strip.isRunning()) strip.start(); + if ((mode != OFF) && (mode != TV) && (mode != E131)) { // strip->start() is only needed for modes with WS2812FX functionality + if(!strip->isRunning()) strip->start(); } if ((mode == OFF) || (mode == TV) || (mode == E131)) { - if(strip.isRunning()) { - strip.strip_off(); // Workaround: to be shure, - delay(10); // that strip is really off. Sometimes strip.stop isn't enought - strip.stop(); // should clear memory + if(strip->isRunning()) { + strip->strip_off(); // Workaround: to be shure, + delay(10); // that strip is really off. Sometimes strip->stop isn't enought + strip->stop(); // should clear memory } else { if (prevmode != mode) { // Start temporarily to clear strip - strip.start(); - strip.strip_off(); // Workaround: to be shure, - delay(10); // that strip is really off. Sometimes strip.stop isn't enought - strip.stop(); // should clear memory + strip->start(); + strip->strip_off(); // Workaround: to be shure, + delay(10); // that strip is really off. Sometimes strip->stop isn't enought + strip->stop(); // should clear memory } } } - if (( mode == AUTO) || (mode == HOLD)) { // strip.service() is only needed for modes with WS2812FX functionality - strip.service(); + if (( mode == AUTO) || (mode == HOLD)) { // strip->service() is only needed for modes with WS2812FX functionality + strip->service(); } if ((prevmode == AUTO) && (mode != AUTO)) { handleAutoStop(); } // stop auto mode if (mode == OFF) { #if defined(ENABLE_MQTT) - if (prevmode != mode) { sprintf(mqtt_buf, "OK =off", ""); } + if (prevmode != mode) { snprintf(mqtt_buf, sizeof(mqtt_buf), "OK =off", ""); } #endif } @@ -991,7 +772,7 @@ void loop() { if (prevmode != mode) { handleAutoStart(); #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK =auto", ""); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK =auto", ""); #endif } } @@ -1000,7 +781,7 @@ void loop() { if (mode == TV) { handleTV(); #if defined(ENABLE_MQTT) - if (prevmode != mode) { sprintf(mqtt_buf, "OK =tv", ""); } + if (prevmode != mode) { snprintf(mqtt_buf, sizeof(mqtt_buf), "OK =tv", ""); } #endif } #endif @@ -1009,60 +790,70 @@ void loop() { if (mode == E131) { handleE131(); #if defined(ENABLE_MQTT) - if (prevmode != mode) { sprintf(mqtt_buf, "OK =e131", ""); } + if (prevmode != mode) { snprintf(mqtt_buf, sizeof(mqtt_buf), "OK =e131", ""); } #endif } #endif + + if (mode == INIT_STRIP) { + mode = prevmode; + //ws2812fx_mode = strip->getMode(); + strip->strip_off(); + delay(10); + if(strip->isRunning()) strip->stop(); + initStrip(); + prevmode = INIT_STRIP; + } if (mode == SET_ALL) { mode = HOLD; if ((prevmode == OFF) || (prevmode == AUTO) || (prevmode == TV) || (prevmode == E131)) { setModeByStateString(last_state); } #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK /%i", ws2812fx_mode); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", ws2812fx_mode); #endif - strip.setMode(ws2812fx_mode); + strip->setMode(ws2812fx_mode); convertColors(); - strip.setColors(0, hex_colors); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - strip.setBrightness(brightness); + strip->setColors(0, hex_colors); + strip->setSpeed(convertSpeed(ws2812fx_speed)); + strip->setBrightness(brightness); prevmode = SET_ALL; - strip.trigger(); + strip->trigger(); } if (mode == SET_MODE) { mode = HOLD; #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK /%i", ws2812fx_mode); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", ws2812fx_mode); #endif - strip.setMode(ws2812fx_mode); + strip->setMode(ws2812fx_mode); prevmode = SET_MODE; - strip.trigger(); + strip->trigger(); } if (mode == SET_COLOR) { convertColors(); - strip.setColors(0, hex_colors); + strip->setColors(0, hex_colors); mode = prevmode; prevmode = SET_COLOR; - if (mode == HOLD) strip.trigger(); + if (mode == HOLD) strip->trigger(); } if (mode == SET_SPEED) { #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK ?%i", ws2812fx_speed); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", ws2812fx_speed); #endif - strip.setSpeed(convertSpeed(ws2812fx_speed)); + strip->setSpeed(convertSpeed(ws2812fx_speed)); mode = prevmode; prevmode = SET_SPEED; - if (mode == HOLD) strip.trigger(); + if (mode == HOLD) strip->trigger(); } if (mode == SET_BRIGHTNESS) { #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK %%%i", brightness); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %%%i", brightness); #endif - strip.setBrightness(brightness); + strip->setBrightness(brightness); mode = prevmode; prevmode = SET_BRIGHTNESS; - if (mode == HOLD) strip.trigger(); + if (mode == HOLD) strip->trigger(); } if (prevmode != mode) { @@ -1070,14 +861,14 @@ void loop() { #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); + 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); } #if defined(ENABLE_MQTT) #if ENABLE_MQTT == 0 - mqtt_client.publish(mqtt_outtopic, mqtt_buf); + mqtt_client->publish(mqtt_outtopic, mqtt_buf); #endif #if ENABLE_MQTT == 1 - amqttClient.publish(mqtt_outtopic, qospub, false, mqtt_buf); + mqtt_client->publish(mqtt_outtopic, qospub, false, mqtt_buf); #endif #if defined(ENABLE_HOMEASSISTANT) if(!ha_send_data.active()) ha_send_data.once(3, tickerSendState); @@ -1087,21 +878,16 @@ void loop() { #if defined(ENABLE_STATE_SAVE) if (updateState){ #if ENABLE_STATE_SAVE == 1 - (writeStateFS()) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); + (writeStateFS(true)) ? DBG_OUTPUT_PORT.println(" Success!") : DBG_OUTPUT_PORT.println(" Failure!"); #endif #if ENABLE_STATE_SAVE == 0 - writeEEPROM(256, 66, last_state); // 256 --> last_state (reserved 66 bytes) - EEPROM.commit(); - updateState = false; - settings_save_state.detach(); + writeEEPROM(384, 66, last_state); // 384 --> last_state (reserved 66 bytes) + EEPROM.commit(); + updateState = false; + settings_save_state.detach(); #endif #endif } - #if defined(ENABLE_MQTT) - #if defined(ENABLE_HOMEASSISTANT) - if (new_ha_mqtt_msg) sendState(); - #endif - #endif prevmode = mode; diff --git a/Arduino/McLighting/McLighting.ino.nodemcu.bin b/Arduino/McLighting/McLighting.ino.nodemcu.bin new file mode 100644 index 0000000..c33d374 Binary files /dev/null and b/Arduino/McLighting/McLighting.ino.nodemcu.bin differ diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index 64458c0..c0a8117 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -1,13 +1,14 @@ -; #define USE_WS2812FX_DMA 0 // 0 = Used PIN is ignored & set to RX/GPIO3; 1 = Used PIN is ignored & set to D4/GPIO2; 2 = Uses PIN is ignored & set to TX/GPIO1; Uses WS2812FX, see: https://github.com/kitesurfer1404/WS2812FX // Neopixel -#define PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached -#define NUMLEDS 144 // Number of leds in the strip +#define LED_PIN 3 // PIN (15 / D8) where neopixel / WS2811 strip is attached; is configurable just for the start +#define NUMLEDS 144 // Number of leds in the; is configurable just for the start +#define RGBORDER "GRBW" // RGBOrder; is configurable just for the start +#define FX_OPTIONS 56 // ws2812fx Options 56 = SIZE_SMALL + FADE_MEDIUM + GAMMA is configurable just for the start; for WS2812FX setSegment OPTIONS, see: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md +//#define LED_TYPE_WS2811 // Uncomment, if LED type uses 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) #define LED_BUILTIN 2 // ESP-12F has the built in LED on GPIO2, see https://github.com/esp8266/Arduino/issues/2192 -#define RGBW // If defined, use RGBW Strips -const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname +char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just for the start #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 @@ -16,17 +17,21 @@ const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname #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_GY33 12 // If defined, enable button handling code for GY-33 color sensor to scan color. The value defines the input pin (12 / D6) for read color data with RGB sensor, connect this PIN to ground to trigger button. -//#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out +#define ENABLE_REMOTE 13 // If defined, enable Remote Control via TSOP31238. The value defines the input pin (13 / D7) for TSOP31238 Out -#define ENABLE_STATE_SAVE 1 // If defined, save state on reboot, if set to 0 in EEPROM, if set to 1 on SPIFFS +#define ENABLE_STATE_SAVE 1 // If defined, load saved state on reboot and save state. If set to 0 from EEPROM, if set to 1 from SPIFFS #define ENABLE_LEGACY_ANIMATIONS // Enable Legacy Animations +#define CUSTOM_WS2812FX_ANIMATIONS //uncomment and put animations in "custom_ws2812fx_animations.h" #define ENABLE_E131 // E1.31 implementation You have to uncomment #define USE_WS2812FX_DMA and set it to 0 #define ENABLE_TV // Enable TV Animation +#define USE_HTML_MIN_GZ //uncomment for using index.htm & edit.htm from PROGMEM instead of SPIFFs #if defined(ENABLE_E131) + #define MULTICAST false #define START_UNIVERSE 1 // First DMX Universe to listen for #define END_UNIVERSE 2 // Total number of Universes to listen for, starting at UNIVERSE + // MUST: END_UNIVERSE >= START_UNIVERSE #endif #if defined(ENABLE_REMOTE) @@ -47,7 +52,19 @@ const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname #endif #if defined(MQTT_HOME_ASSISTANT_SUPPORT) - #define MQTT_HOME_ASSISTANT_0_84_SUPPORT // Comment if using HA version < 0.84 + #define MQTT_HOME_ASSISTANT_0_87_SUPPORT // Comment if using HA version < 0.87 +#endif + +#if defined(USE_WS2812FX_DMA) and USE_WS2812FX_DMA < 0 and USE_WS2812FX_DMA > 2 +#error "Definition of USE_WS2812FX_DMA is wrong!" +#endif + +#if defined(ENABLE_MQTT) and ENABLE_MQTT < 0 and ENABLE_MQTT > 1 +#error "Definition of ENABLE_MQTT is wrong!" +#endif + +#if defined(ENABLE_MQTT) and ENABLE_MQTT < 0 and ENABLE_MQTT > 1 +#error "Definition of ENABLE_MQTT is wrong!" #endif #if defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT) @@ -59,19 +76,21 @@ const char HOSTNAME[] = "McLightingRGBW_01"; // Friedly hostname // parameters for automatically cycling favorite patterns uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mode, duration (seconds) - {0xff000000, 0x00ff0000, 0x00000000, 200, 1, 5}, // blink red/geen for 5 seconds - {0x00ff0000, 0x0000ff00, 0x00000000, 200, 3, 10}, // wipe green/blue for 10 seconds - {0x0000ff00, 0xff000000, 0x00000000, 60, 14, 10}, // dual scan blue on red for 10 seconds - {0x0000ff00, 0xff000000, 0x00000000, 40, 45, 15}, // fireworks blue/red for 15 seconds - {0xff000000, 0x00ff0000, 0x0000ff00, 40, 54, 15} // tricolor chase red/green/blue for 15 seconds + {0x00ff0000, 0x0000ff00, 0x00000000, 200, 1, 5000}, // blink red/geen for 5 seconds + {0x0000ff00, 0x000000ff, 0x00000000, 200, 3, 10000}, // wipe green/blue for 10 seconds + {0x000000ff, 0x00ff0000, 0x00000000, 60, 14, 10000}, // dual scan blue on red for 10 seconds + {0x000000ff, 0x00ff0000, 0x00000000, 40, 45, 15000}, // fireworks blue/red for 15 seconds + {0x00ff0000, 0x0000ff00, 0x000000ff, 40, 54, 15000} // tricolor chase red/green/blue for 15 seconds }; #if defined(ENABLE_MQTT) - char mqtt_buf[80]; - char mqtt_intopic[strlen(HOSTNAME) + 3 + 1]; // Topic in will be: /in - char mqtt_outtopic[strlen(HOSTNAME) + 4 + 1]; // Topic out will be: /out + char mqtt_buf[80]; + char mqtt_will_topic[sizeof(HOSTNAME) + 7]; // Topic 'will' will be:HOSTNAME "/status"; + char mqtt_will_payload[] = "ONLINE"; + char mqtt_intopic[sizeof(HOSTNAME) + 3]; // Topic 'in' will be: /in + char mqtt_outtopic[sizeof(HOSTNAME) + 4]; // Topic 'out' will be: /out #if ENABLE_MQTT == 0 - #define MQTT_MAX_PACKET_SIZE 2048 + #define MQTT_MAX_PACKET_SIZE 512 #define MQTT_MAX_RECONNECT_TRIES 4 int mqtt_reconnect_retries = 0; uint8_t qossub = 0; // PubSubClient can sub qos 0 or 1 @@ -83,24 +102,20 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod #endif #if defined(ENABLE_HOMEASSISTANT) - char mqtt_ha_state_in[5 + strlen(HOSTNAME) + 12 + 1]; // Topic in will be: home/_ha/state/in" - char mqtt_ha_state_out[5 + strlen(HOSTNAME) + 13 + 1]; // Topic in will be: home/_ha/state/out" + char mqtt_ha_config[20 + sizeof(HOSTNAME) + 7]; // Topic config will be: "homeassistant/light//config" + char mqtt_ha_state_in[5 + sizeof(HOSTNAME) + 12]; // Topic in will be: "home/_ha/state/in" + char mqtt_ha_state_out[5 + sizeof(HOSTNAME) + 13]; // Topic in will be: "home/_ha/state/out" const char* on_cmd = "ON"; const char* off_cmd = "OFF"; bool new_ha_mqtt_msg = false; uint16_t color_temp = 327; // min is 154 and max is 500 #endif - #if defined(ENABLE_MQTT_HOSTNAME_CHIPID) - char mqtt_clientid[64]; - #else - const char* mqtt_clientid = HOSTNAME; - #endif - - char mqtt_host[64] = ""; - char mqtt_port[6] = ""; - char mqtt_user[32] = ""; - char mqtt_pass[32] = ""; + char mqtt_clientid[sizeof(HOSTNAME) + 9]; + char mqtt_host[65] = ""; //is configurable just for the start + uint16_t mqtt_port = 1883; //is configurable just for the start + char mqtt_user[33] = ""; //is configurable just for the start + char mqtt_pass[33] = ""; //is configurable just for the start #endif @@ -110,14 +125,18 @@ uint32_t autoParams[][6] = { // main_color, back_color, xtra_color, speed, mod #define DBG_OUTPUT_PORT Serial // Set debug output port // List of all color modes -enum MODE {OFF, AUTO, TV, E131, CUSTOM, HOLD, SET_ALL, SET_MODE, SET_COLOR, SET_SPEED, SET_BRIGHTNESS}; -MODE mode = SET_MODE; // Standard mode that is active when software starts +#if defined(ENABLE_LEGACY_ANIMATIONS) + enum MODE {OFF, AUTO, TV, E131, CUSTOM, HOLD, SET_ALL, SET_MODE, SET_COLOR, SET_SPEED, SET_BRIGHTNESS, INIT_STRIP, WIPE, RAINBOW, RAINBOWCYCLE, THEATERCHASE, TWINKLERANDOM, THEATERCHASERAINBOW}; +#else + enum MODE {OFF, AUTO, TV, E131, CUSTOM, HOLD, SET_ALL, SET_MODE, SET_COLOR, SET_SPEED, SET_BRIGHTNESS, INIT_STRIP}; +#endif +MODE mode = SET_ALL; // Standard mode that is active when software starts MODE prevmode = mode; int ws2812fx_speed = 196; // Global variable for storing the delay between color changes --> smaller == faster int brightness = 196; // Global variable for storing the brightness (255 == 100%) -int ws2812fx_mode = 0; // Helper variable to set WS2812FX modes +int ws2812fx_mode = 0; // Global variable for storing the WS2812FX modes bool shouldSaveConfig = false; // For WiFiManger custom config @@ -162,3 +181,22 @@ bool updateState = false; byte KeyPressCount_gy33 = 0; byte prevKeyState_gy33 = HIGH; // button is active low #endif + +struct { + uint16_t stripSize = NUMLEDS; + char RGBOrder[5] = RGBORDER; + #if defined(USE_WS2812FX_DMA) + #if USE_WS2812FX_DMA == 0 + uint8_t pin = 3; + #endif + #if USE_WS2812FX_DMA == 1 + uint8_t pin = 2; + #endif + #if USE_WS2812FX_DMA == 2 + uint8_t pin = 1; + #endif + #else + uint8_t pin = LED_PIN; + #endif + uint8_t fxoptions = FX_OPTIONS; +} WS2812FXStripSettings; diff --git a/Arduino/McLighting/htm_edit_gz.h b/Arduino/McLighting/htm_edit_gz.h new file mode 100644 index 0000000..b1fa888 --- /dev/null +++ b/Arduino/McLighting/htm_edit_gz.h @@ -0,0 +1,463 @@ +#include + +#define edit_htm_gz_len 5489 +static const char edit_htm_gz[] PROGMEM ={ + 0x1f, 0x8b, 0x08, 0x08, 0x10, 0x9c, 0x83, 0x5c, 0x04, 0x00, 0x65, 0x64, + 0x69, 0x74, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xed, 0x1c, 0x67, 0x7b, 0xf2, + 0x36, 0xf0, 0x7b, 0x7f, 0x85, 0xeb, 0x8e, 0x40, 0x99, 0x21, 0x24, 0x6f, + 0x66, 0x5b, 0x76, 0x12, 0xa0, 0x84, 0x91, 0x84, 0xa4, 0xeb, 0x31, 0xb6, + 0x00, 0x27, 0xc6, 0x76, 0x6c, 0x13, 0x20, 0x69, 0xfa, 0xdb, 0x7b, 0x92, + 0xbc, 0x07, 0x38, 0xa3, 0xf3, 0x29, 0xef, 0x00, 0x4b, 0x77, 0xa7, 0xbb, + 0xd3, 0xe9, 0x74, 0x3a, 0x49, 0x3e, 0xfe, 0xbc, 0xda, 0xa9, 0x0c, 0x6e, + 0x2e, 0x6a, 0xcc, 0xd4, 0x98, 0x49, 0xdf, 0x7e, 0x76, 0x8c, 0xbf, 0x18, + 0x89, 0x93, 0x27, 0x27, 0x2c, 0x92, 0xd9, 0x6f, 0x3f, 0x63, 0x98, 0xe3, + 0x29, 0xe2, 0x04, 0xfc, 0x03, 0x7e, 0x1a, 0xa2, 0x21, 0xa1, 0x6f, 0xfb, + 0x17, 0x67, 0xf5, 0x7a, 0x9f, 0xa9, 0x09, 0xa2, 0xa1, 0x68, 0xc7, 0x39, + 0x52, 0x68, 0x02, 0xe8, 0xc6, 0x4a, 0x42, 0x8c, 0xb1, 0x52, 0xd1, 0x09, + 0x6b, 0xa0, 0xa5, 0x91, 0xe3, 0x75, 0x9d, 0x65, 0x66, 0x48, 0x10, 0xb9, + 0x13, 0x56, 0xe7, 0x35, 0x44, 0x89, 0x92, 0x4f, 0x96, 0x57, 0x64, 0x0c, + 0xd3, 0x46, 0xf2, 0x9c, 0x79, 0x86, 0x42, 0xfa, 0x79, 0xca, 0x88, 0xb2, + 0x80, 0x96, 0x87, 0xcc, 0x4e, 0x3e, 0x7f, 0x64, 0x97, 0xaa, 0x8a, 0x2e, + 0x1a, 0xa2, 0x22, 0x1f, 0x32, 0xdc, 0x48, 0x57, 0xa4, 0xb9, 0x81, 0x9c, + 0x3a, 0x09, 0x8d, 0x8d, 0x43, 0x66, 0x57, 0x5d, 0x3a, 0x45, 0x23, 0x45, + 0x13, 0x90, 0x76, 0xc8, 0x6c, 0xab, 0x4b, 0x06, 0xc0, 0x45, 0x81, 0xf9, + 0xa2, 0x58, 0x2c, 0xba, 0xea, 0x39, 0xfe, 0x7e, 0xa2, 0x29, 0x73, 0x59, + 0xc8, 0xf0, 0x8a, 0xa4, 0x00, 0xe4, 0x17, 0xf5, 0x5d, 0xfc, 0xc7, 0x01, + 0x11, 0x44, 0x5d, 0x95, 0xb8, 0xd5, 0x21, 0x23, 0x2b, 0x32, 0x72, 0x53, + 0x5e, 0x66, 0xf4, 0x29, 0x27, 0x28, 0x8b, 0x43, 0x26, 0x0f, 0x7f, 0xb6, + 0xf3, 0xd0, 0x84, 0x36, 0x19, 0x71, 0x09, 0x26, 0x9f, 0x36, 0xff, 0x66, + 0x8b, 0x4c, 0xd2, 0xc1, 0x18, 0x83, 0x98, 0x19, 0x5d, 0x7c, 0x42, 0xc0, + 0x4e, 0xc1, 0x64, 0xd2, 0xa9, 0x18, 0x73, 0x33, 0x51, 0x82, 0x56, 0x74, + 0x4e, 0xd6, 0x33, 0x3a, 0xd2, 0xc4, 0xb1, 0x0f, 0x60, 0x81, 0xc4, 0xc9, + 0xd4, 0x38, 0x1c, 0x29, 0x92, 0x60, 0xd5, 0xbc, 0x84, 0x69, 0x70, 0x2e, + 0xb9, 0x94, 0x28, 0x89, 0x3a, 0xb4, 0x89, 0x3b, 0xc3, 0xcf, 0xbf, 0xa1, + 0xa8, 0xc0, 0xb8, 0x57, 0x79, 0x9e, 0x82, 0x19, 0xa7, 0x4d, 0x44, 0xd9, + 0x53, 0xa4, 0x72, 0x82, 0x20, 0xca, 0x13, 0x28, 0x5b, 0xc7, 0x01, 0x34, + 0x0a, 0x1c, 0x04, 0x3b, 0x4c, 0x43, 0x12, 0x67, 0x88, 0x8f, 0xc8, 0xd5, + 0x84, 0x28, 0x67, 0x16, 0xa2, 0x60, 0x4c, 0x0f, 0x99, 0xbd, 0xbc, 0x5b, + 0x23, 0xfc, 0x5c, 0xd3, 0xa1, 0x33, 0x00, 0x59, 0x04, 0xb2, 0xda, 0xda, + 0xd6, 0x74, 0x95, 0x93, 0x5d, 0xed, 0xd1, 0x6e, 0xa4, 0xdd, 0x1c, 0xec, + 0x43, 0x51, 0x96, 0x44, 0x19, 0x65, 0x46, 0x92, 0xc2, 0xdf, 0x87, 0xc8, + 0xb5, 0xa7, 0x2e, 0x37, 0x48, 0x76, 0x38, 0x55, 0x1e, 0x91, 0xc6, 0x3c, + 0xbb, 0x2c, 0xc7, 0x6c, 0x6c, 0x3d, 0x86, 0xc9, 0xa6, 0xcd, 0x5e, 0xad, + 0x56, 0xb3, 0x30, 0x6c, 0x34, 0x5d, 0xcf, 0x18, 0x30, 0x32, 0x1e, 0x45, + 0xb4, 0x80, 0x5e, 0x4c, 0xfb, 0x4a, 0x1c, 0xad, 0x3a, 0x1c, 0x47, 0x74, + 0xd8, 0xc6, 0xee, 0x7f, 0xf9, 0x2c, 0xb4, 0x51, 0x51, 0x56, 0xe7, 0x06, + 0xf3, 0x1c, 0x6b, 0xb0, 0x29, 0x2a, 0xc7, 0x8b, 0xc6, 0x0a, 0x9a, 0xdb, + 0x40, 0xf4, 0xd9, 0x63, 0xc6, 0x98, 0x0f, 0x6d, 0xc6, 0x49, 0xcc, 0x36, + 0x1e, 0x92, 0x57, 0x48, 0x13, 0x38, 0x99, 0x4b, 0x33, 0x25, 0x4d, 0xe4, + 0x40, 0xe2, 0x7e, 0x88, 0xf1, 0x67, 0x66, 0xca, 0x53, 0x66, 0x0e, 0x85, + 0x50, 0x21, 0x21, 0xde, 0xf0, 0x1b, 0x32, 0x0c, 0x8c, 0xd1, 0xbd, 0x68, + 0xac, 0x03, 0x71, 0x55, 0xc5, 0xd2, 0x43, 0x84, 0x49, 0xe5, 0xf3, 0xe3, + 0x18, 0x26, 0x1a, 0x49, 0xd1, 0x34, 0x04, 0x87, 0x2e, 0x36, 0x92, 0x8c, + 0x80, 0x78, 0x45, 0xe3, 0xa8, 0x96, 0xc1, 0x98, 0x90, 0x26, 0x89, 0x1b, + 0xf9, 0xa3, 0xfd, 0x94, 0x02, 0xff, 0x3c, 0x42, 0x12, 0x7c, 0xe3, 0x21, + 0x1f, 0x34, 0x03, 0xf2, 0xa7, 0x00, 0x9e, 0x26, 0x16, 0xb5, 0xdf, 0x09, + 0x15, 0xff, 0x88, 0x89, 0xa5, 0x2e, 0xc2, 0x46, 0x3a, 0xac, 0xf0, 0xf0, + 0x70, 0x84, 0xc6, 0x8a, 0x86, 0x98, 0xe7, 0x37, 0xea, 0x8d, 0xf0, 0x76, + 0x08, 0xcc, 0x70, 0x23, 0x09, 0x09, 0xb6, 0xc8, 0x41, 0x72, 0x02, 0x1a, + 0x73, 0x73, 0xc9, 0x08, 0xb1, 0xcf, 0xec, 0x5e, 0xac, 0x36, 0xf8, 0x29, + 0xe2, 0xef, 0x91, 0x70, 0x28, 0x2b, 0x46, 0xc2, 0x6e, 0x30, 0x19, 0xa9, + 0x16, 0xe2, 0x41, 0x3e, 0x52, 0x2f, 0x6e, 0x7f, 0x32, 0xd7, 0xa4, 0x04, + 0x2b, 0x70, 0x06, 0x77, 0x28, 0xce, 0xb8, 0x09, 0xca, 0xa9, 0xf2, 0xe4, + 0x68, 0xc4, 0xe9, 0x68, 0xaf, 0x98, 0x16, 0xaf, 0xca, 0x9d, 0xde, 0x22, + 0xdf, 0x6c, 0x4c, 0x94, 0x12, 0x7c, 0x7e, 0xe8, 0x5f, 0x4e, 0x6b, 0x97, + 0x13, 0xf8, 0x55, 0xc6, 0x8f, 0x95, 0x49, 0xa5, 0x74, 0x83, 0x7f, 0xd4, + 0x3b, 0x68, 0x71, 0x89, 0x7f, 0x34, 0x86, 0xbd, 0xfa, 0xf5, 0x69, 0x6f, + 0x30, 0x2a, 0xdc, 0xe6, 0x85, 0x42, 0x7d, 0x75, 0xdb, 0x2d, 0x97, 0x6f, + 0x1b, 0x07, 0xe2, 0x6d, 0xbf, 0x7c, 0x3e, 0xba, 0xae, 0xcb, 0xb7, 0x57, + 0xe7, 0xd2, 0xcd, 0x75, 0x6f, 0x97, 0xe7, 0x25, 0xe9, 0x02, 0x23, 0xa8, + 0xcb, 0xf3, 0x5e, 0xad, 0x7e, 0x89, 0x7e, 0xd0, 0x74, 0xa9, 0xbd, 0x3d, + 0xcf, 0xe7, 0x4b, 0xdd, 0x49, 0x03, 0x5c, 0xf4, 0x8a, 0x93, 0xea, 0xf5, + 0x4e, 0x33, 0x55, 0x91, 0xce, 0xce, 0x9a, 0xdd, 0xe6, 0xea, 0xe1, 0xf2, + 0xaa, 0xfb, 0x38, 0xa8, 0xd5, 0x76, 0xaa, 0xb3, 0xd2, 0xb4, 0xb5, 0x28, + 0x4d, 0x2f, 0xf7, 0xbb, 0xb7, 0xca, 0x69, 0xb1, 0x54, 0xe8, 0x16, 0x26, + 0xed, 0x7e, 0x9d, 0xe3, 0x51, 0xb1, 0x5d, 0x31, 0xce, 0xf7, 0xfb, 0x17, + 0xe5, 0xfa, 0xa2, 0x74, 0xdf, 0x9b, 0x8b, 0xa7, 0x4d, 0xb5, 0xb4, 0xa7, + 0xf7, 0x7e, 0xc8, 0xb5, 0xe6, 0x9f, 0x9e, 0x1a, 0xbb, 0xe2, 0x76, 0xf1, + 0x9e, 0x37, 0xb8, 0xcb, 0x87, 0x5e, 0x63, 0xda, 0x18, 0xca, 0xf3, 0x83, + 0x4e, 0xee, 0xc2, 0xf8, 0xd4, 0x7e, 0xd2, 0xdb, 0xe2, 0xbd, 0xf4, 0x58, + 0x4f, 0x1d, 0x18, 0x85, 0xfb, 0xeb, 0x41, 0xf5, 0x71, 0x75, 0xa6, 0x95, + 0xf4, 0x52, 0x9e, 0x6b, 0xf6, 0x7a, 0xe2, 0xf6, 0x20, 0x5f, 0xc9, 0x4d, + 0xcf, 0x8b, 0xad, 0xcb, 0x91, 0xb1, 0x9b, 0xdb, 0xd7, 0x7e, 0x50, 0xaf, + 0xaf, 0x24, 0x75, 0xbf, 0xd7, 0xd7, 0x0e, 0xce, 0x8b, 0xf9, 0x51, 0x71, + 0x7f, 0xbc, 0xac, 0x73, 0x83, 0xee, 0x41, 0x6a, 0x6c, 0xec, 0xd7, 0x6e, + 0xf7, 0xda, 0xe7, 0x37, 0xa3, 0x7c, 0xe7, 0x3e, 0x25, 0xc8, 0x37, 0x0d, + 0x75, 0x76, 0x31, 0x19, 0x2e, 0x9a, 0x67, 0xa5, 0xc7, 0xd6, 0x72, 0xff, + 0xf1, 0x66, 0xc8, 0xef, 0x36, 0x84, 0x76, 0xa9, 0x7b, 0x3e, 0xe9, 0xd6, + 0xee, 0xd5, 0xbb, 0xde, 0x60, 0xba, 0xb3, 0x37, 0xe8, 0x17, 0x2e, 0x53, + 0xd5, 0xeb, 0xeb, 0x5c, 0x75, 0xfb, 0xd3, 0xf5, 0xfc, 0x66, 0x32, 0xdb, + 0x57, 0x17, 0xe7, 0xab, 0x9b, 0x6d, 0x59, 0xbd, 0xd5, 0x6f, 0x9b, 0x9d, + 0xe5, 0xd9, 0xac, 0x73, 0xb5, 0x7d, 0x96, 0x9b, 0x16, 0x53, 0x9d, 0xbd, + 0xc7, 0xda, 0x64, 0xb7, 0x51, 0xb9, 0x2d, 0xab, 0x93, 0x59, 0x69, 0x6f, + 0x3a, 0xdc, 0x5f, 0x9c, 0x36, 0x2f, 0x4f, 0xab, 0xbd, 0xf2, 0xb0, 0x7b, + 0x23, 0xf2, 0xdd, 0xa2, 0x26, 0xf1, 0x3b, 0x83, 0x71, 0xfe, 0xaa, 0xad, + 0xef, 0x57, 0x4f, 0xcb, 0xfd, 0xfd, 0xbd, 0x62, 0xbd, 0x70, 0x53, 0xd7, + 0xd5, 0xbb, 0xc9, 0xe5, 0xcd, 0x5d, 0x73, 0x98, 0x2b, 0x3d, 0xed, 0x4c, + 0x74, 0xa1, 0x2b, 0x14, 0x10, 0x2a, 0x9f, 0x2e, 0x66, 0x42, 0xe3, 0x7a, + 0x78, 0xca, 0x4f, 0xca, 0x8d, 0xfe, 0xfd, 0xed, 0xb0, 0x33, 0x54, 0xa6, + 0x7c, 0x6d, 0x88, 0x46, 0x3d, 0xa5, 0xcb, 0x97, 0x26, 0x77, 0x0f, 0x10, + 0x36, 0xfd, 0x70, 0x93, 0x2a, 0x5d, 0xad, 0xe6, 0x3b, 0xb7, 0x3b, 0x7a, + 0xa9, 0xf9, 0x30, 0x6e, 0x2a, 0x8d, 0xb6, 0x8e, 0x16, 0x65, 0x54, 0x3b, + 0xeb, 0x5c, 0x4c, 0xba, 0xcb, 0xe5, 0xc5, 0xf9, 0xd9, 0x1d, 0xdf, 0x38, + 0xdd, 0x7b, 0x30, 0x5a, 0xb9, 0x7c, 0x49, 0x28, 0x55, 0x9f, 0x9a, 0x0d, + 0x79, 0x3e, 0xaf, 0xa6, 0x0a, 0x46, 0xab, 0xf9, 0xa9, 0xbb, 0x5f, 0x9d, + 0x9e, 0x9e, 0x8e, 0x3a, 0xe5, 0xeb, 0x54, 0xb3, 0xf6, 0xc4, 0x9f, 0xb6, + 0xe6, 0x37, 0xfc, 0x7e, 0xa1, 0x7d, 0x5f, 0xbb, 0x44, 0xf7, 0x2d, 0x71, + 0x31, 0x7f, 0xbc, 0x3a, 0x4d, 0x4d, 0xe6, 0xdd, 0x72, 0xf7, 0xa9, 0xd3, + 0x28, 0x0e, 0x85, 0xd2, 0x68, 0xbf, 0xd6, 0xe1, 0x7b, 0xfc, 0x43, 0xf7, + 0xb1, 0x7a, 0x7f, 0x53, 0x10, 0x2b, 0xad, 0xf9, 0xb2, 0x56, 0x39, 0x2f, + 0xee, 0x9c, 0x2b, 0xa3, 0xf6, 0x50, 0x99, 0x1b, 0x0f, 0x8d, 0x49, 0x95, + 0x2b, 0x0c, 0x3e, 0x5d, 0x3e, 0xb4, 0x9a, 0x0b, 0xe3, 0xa0, 0xd9, 0x5b, + 0xcd, 0x97, 0xcd, 0xab, 0xf2, 0xea, 0xe1, 0x6a, 0x38, 0x7c, 0x38, 0x53, + 0x2a, 0x95, 0xcb, 0x4a, 0xe9, 0x61, 0x7a, 0xd9, 0x11, 0x95, 0xc1, 0x75, + 0xe5, 0x53, 0xa3, 0x38, 0xe8, 0xd6, 0x3a, 0xd5, 0x7c, 0xe9, 0x62, 0x55, + 0xc8, 0x7d, 0x6a, 0x14, 0x86, 0xea, 0x7c, 0xfb, 0xbc, 0x98, 0x92, 0x96, + 0xa8, 0x5b, 0x1c, 0x0c, 0xcb, 0xa3, 0xb3, 0x41, 0x55, 0x55, 0xae, 0x90, + 0x04, 0x96, 0x51, 0xbe, 0xaa, 0x8f, 0x16, 0xf3, 0x5d, 0xa5, 0xdd, 0x3e, + 0xbf, 0x2c, 0x4f, 0x95, 0xe1, 0x6a, 0xd7, 0x98, 0x09, 0x3d, 0xbe, 0xbd, + 0x58, 0xcd, 0x2e, 0x0a, 0x9d, 0x56, 0x97, 0x6b, 0xdd, 0x2d, 0x0f, 0x72, + 0x8f, 0x72, 0x59, 0xd9, 0xbb, 0xda, 0x69, 0xee, 0x89, 0x4f, 0xa5, 0xc1, + 0xac, 0x2f, 0xb7, 0xb9, 0x7c, 0xf5, 0xe1, 0xd3, 0x18, 0x69, 0x67, 0xca, + 0xf4, 0x7c, 0xaa, 0x6d, 0xab, 0xf9, 0xed, 0x27, 0x4d, 0x7a, 0x2a, 0x1e, + 0x68, 0xb7, 0xf5, 0x62, 0x07, 0xba, 0xe0, 0xfc, 0x7e, 0x58, 0xd8, 0x79, + 0xbc, 0xea, 0x3e, 0xdd, 0xa8, 0xa9, 0xc5, 0xe8, 0xa6, 0x71, 0x95, 0x6b, + 0xaa, 0xc3, 0xe6, 0xdd, 0x23, 0x0c, 0xe6, 0x7d, 0x43, 0x3f, 0x6b, 0x56, + 0xb4, 0xf6, 0x0f, 0xa5, 0x9b, 0xfa, 0xf2, 0xae, 0xd0, 0x68, 0xf6, 0x77, + 0x6f, 0xaf, 0x97, 0x93, 0x22, 0x5a, 0x34, 0xf5, 0xf3, 0x31, 0xd7, 0x68, + 0x9f, 0xdd, 0xec, 0x36, 0x87, 0x0f, 0x17, 0x4f, 0xfb, 0xad, 0x72, 0xf9, + 0x6e, 0x2f, 0xb5, 0xaa, 0x3e, 0x5e, 0x5d, 0x7c, 0x3a, 0x80, 0x6f, 0x35, + 0x77, 0x50, 0x3f, 0x50, 0xce, 0x96, 0x3b, 0x1d, 0x51, 0x3f, 0xbd, 0x5e, + 0xa0, 0x4f, 0x1d, 0x4e, 0xca, 0x9f, 0x2e, 0x2b, 0x30, 0x88, 0xba, 0x30, + 0x22, 0x6b, 0x67, 0x5d, 0x18, 0x90, 0xb5, 0x33, 0x18, 0x9a, 0xa4, 0x68, + 0x0a, 0xff, 0x9d, 0xe1, 0x0a, 0x5a, 0x54, 0x83, 0xc7, 0x29, 0x85, 0x5d, + 0x54, 0xf7, 0x6b, 0xb9, 0xf2, 0xed, 0xa4, 0x74, 0x91, 0x7f, 0x98, 0x36, + 0xef, 0x76, 0xb4, 0x61, 0xe7, 0x53, 0x09, 0x7f, 0x6a, 0x52, 0x7d, 0x70, + 0xdf, 0x9f, 0x77, 0x67, 0x95, 0x0a, 0x9b, 0x04, 0x4f, 0x9c, 0xd1, 0x90, + 0x8a, 0x38, 0xe3, 0x2d, 0x6e, 0x07, 0x4f, 0x40, 0x71, 0x5d, 0xd1, 0x86, + 0x68, 0x69, 0x4a, 0x03, 0x51, 0x66, 0x7b, 0xcf, 0x1d, 0xb2, 0x11, 0xc8, + 0xf0, 0x2a, 0x98, 0xf5, 0x0c, 0x91, 0xe7, 0xa4, 0x0c, 0x27, 0x89, 0x13, + 0x98, 0x99, 0x66, 0xa2, 0x20, 0x48, 0xb1, 0x26, 0x95, 0x50, 0xff, 0x98, + 0x71, 0xc2, 0x92, 0xed, 0x7d, 0x75, 0xb9, 0x31, 0x00, 0x89, 0x12, 0x93, + 0x84, 0x69, 0x38, 0x22, 0x61, 0x59, 0x87, 0x57, 0x12, 0x8e, 0x9a, 0x02, + 0xf8, 0xa7, 0x54, 0x73, 0x3a, 0xc5, 0xf3, 0x6a, 0x5c, 0xe1, 0xc2, 0xf8, + 0x26, 0x84, 0x32, 0x3b, 0x31, 0x27, 0x66, 0x6b, 0x62, 0x62, 0x52, 0x31, + 0xa6, 0x0e, 0x6f, 0x13, 0x20, 0x44, 0xb0, 0x89, 0xdc, 0x37, 0x0c, 0x0d, + 0x98, 0x18, 0x4e, 0xb8, 0xe3, 0x78, 0x50, 0x00, 0x03, 0x81, 0xd1, 0x0c, + 0x7f, 0xd3, 0x08, 0x49, 0xd1, 0x98, 0xd1, 0x7c, 0x32, 0x16, 0x97, 0xcc, + 0x37, 0x39, 0x13, 0xe7, 0x7b, 0xb2, 0x70, 0x63, 0xe8, 0xba, 0x8d, 0xe1, + 0x64, 0x81, 0x49, 0x58, 0x51, 0x17, 0x0e, 0xe1, 0x05, 0x60, 0x97, 0x47, + 0x19, 0x55, 0x5c, 0x22, 0x29, 0x43, 0x62, 0x99, 0xc3, 0x7c, 0x92, 0xa2, + 0x52, 0x2e, 0x83, 0xb2, 0x39, 0xc5, 0x4e, 0x00, 0xc7, 0xc9, 0x30, 0xdb, + 0x51, 0xe6, 0xcd, 0x12, 0x8b, 0xc3, 0x8c, 0xc9, 0x61, 0xc6, 0xe2, 0x30, + 0x63, 0x72, 0x28, 0xca, 0x63, 0x51, 0x16, 0x0d, 0xc4, 0x6c, 0xeb, 0x44, + 0x50, 0x47, 0x54, 0x93, 0x71, 0x8b, 0xf6, 0x3d, 0x5a, 0x8d, 0x35, 0x6e, + 0x86, 0xf4, 0xd8, 0xa4, 0x6d, 0x1a, 0x6e, 0x56, 0xc7, 0x9a, 0x32, 0x83, + 0x12, 0xa7, 0x32, 0x18, 0x8b, 0xdb, 0x5c, 0xb8, 0x81, 0x0c, 0x25, 0x2e, + 0x96, 0x23, 0x85, 0xbf, 0xe3, 0xbe, 0x98, 0xab, 0x92, 0xc2, 0x09, 0x64, + 0xf1, 0x11, 0x2b, 0x42, 0xf7, 0xaf, 0xf0, 0x34, 0x3a, 0x36, 0x83, 0x6b, + 0xbe, 0xc0, 0xd0, 0x2e, 0xec, 0x47, 0x8e, 0xec, 0x42, 0xd1, 0xae, 0x72, + 0x84, 0xc8, 0x10, 0x42, 0x64, 0x09, 0x1c, 0x6a, 0xf8, 0xa1, 0x6b, 0x32, + 0x5a, 0x88, 0x17, 0x42, 0xfe, 0x25, 0xd7, 0x17, 0xd8, 0x4a, 0x5e, 0x25, + 0xa5, 0x97, 0xe1, 0x91, 0x62, 0x18, 0xca, 0x2c, 0x5a, 0x52, 0x67, 0x9c, + 0x17, 0xf2, 0x84, 0xe5, 0x40, 0x9f, 0x38, 0xe4, 0x1c, 0xa6, 0x10, 0x49, + 0x73, 0xa4, 0x99, 0x2f, 0x54, 0x8d, 0x98, 0xf0, 0x3b, 0x18, 0xb4, 0x7a, + 0x22, 0x06, 0xcb, 0x0e, 0x87, 0x0e, 0x2f, 0x2e, 0x16, 0xd6, 0x68, 0x1b, + 0x6b, 0x36, 0x28, 0xda, 0xae, 0x9f, 0xda, 0x71, 0x0e, 0xd6, 0x87, 0x4e, + 0xde, 0x86, 0xd7, 0x44, 0xd5, 0xb0, 0x32, 0x33, 0xe3, 0xb9, 0xcc, 0x63, + 0xb1, 0x18, 0x18, 0xf8, 0x9c, 0x81, 0xea, 0xa2, 0x84, 0x2e, 0x4d, 0x23, + 0x4c, 0x98, 0xe3, 0x26, 0xcd, 0xe0, 0xce, 0x4a, 0x33, 0x54, 0x3b, 0x49, + 0x87, 0xa1, 0x47, 0x4e, 0x63, 0x96, 0x33, 0xe9, 0xd4, 0x30, 0xd4, 0x23, + 0x77, 0xa1, 0xb9, 0xdc, 0x38, 0x61, 0x04, 0x85, 0x9f, 0x63, 0x0a, 0x59, + 0x4a, 0xbc, 0x46, 0xe9, 0x25, 0x58, 0x52, 0xcf, 0x3a, 0x79, 0x13, 0x8a, + 0x90, 0xc5, 0xb9, 0x24, 0xc0, 0x62, 0xc7, 0xc0, 0x04, 0xeb, 0xaf, 0x9c, + 0x41, 0xe8, 0x2f, 0xaa, 0x12, 0x06, 0x18, 0x73, 0x92, 0x8e, 0xfc, 0xf5, + 0x32, 0x37, 0xc3, 0x75, 0x24, 0xa6, 0x76, 0x90, 0x1d, 0x16, 0x26, 0xc8, + 0x30, 0xdb, 0x2f, 0xaf, 0xce, 0x04, 0x4b, 0xb6, 0x64, 0x96, 0x53, 0x55, + 0x24, 0x0b, 0x95, 0xa9, 0x28, 0x09, 0x09, 0x42, 0x29, 0xe9, 0x95, 0x45, + 0xe5, 0x8c, 0xe9, 0x6b, 0x44, 0xc1, 0xf0, 0x59, 0x51, 0xc0, 0xac, 0xd0, + 0xd1, 0x9c, 0xc1, 0x25, 0xac, 0x17, 0xc0, 0x16, 0x15, 0xaf, 0x0f, 0x7d, + 0x75, 0xb6, 0x24, 0x61, 0x78, 0xe6, 0x1a, 0xe8, 0x8a, 0x93, 0xe6, 0x04, + 0x26, 0xf7, 0x56, 0x51, 0x31, 0x35, 0x9f, 0xa4, 0xa3, 0x39, 0x18, 0xa8, + 0xbc, 0x46, 0x56, 0x0a, 0xe0, 0x16, 0x96, 0x96, 0x64, 0x45, 0x59, 0x46, + 0xda, 0xe9, 0xa0, 0xdd, 0x02, 0xe4, 0x2d, 0x6a, 0x3e, 0x5b, 0x6f, 0xe4, + 0x8b, 0x52, 0xf4, 0x71, 0x36, 0xbb, 0x17, 0x44, 0xed, 0x55, 0x8c, 0x11, + 0x0c, 0x2f, 0x5f, 0xed, 0xfb, 0xaa, 0xa8, 0xbd, 0x95, 0x2d, 0x42, 0x2f, + 0xc0, 0x15, 0x36, 0xd4, 0x57, 0xb2, 0x85, 0x51, 0xfc, 0x7c, 0xe1, 0x41, + 0xf7, 0x76, 0xc6, 0x30, 0x45, 0xd2, 0x04, 0xfc, 0xf5, 0x8d, 0xe9, 0x29, + 0x8c, 0xcc, 0x0b, 0x45, 0x37, 0x2e, 0x34, 0x85, 0x47, 0xba, 0xde, 0x43, + 0x0f, 0x73, 0xa4, 0x1b, 0x09, 0x32, 0x84, 0xed, 0xd1, 0x33, 0x66, 0x12, + 0xe6, 0x20, 0xce, 0x02, 0xfb, 0xc2, 0xaa, 0x6f, 0x70, 0x06, 0x48, 0x75, + 0xc2, 0x14, 0x4d, 0x38, 0x07, 0xd2, 0x06, 0xd4, 0x01, 0x66, 0xae, 0x33, + 0x9f, 0x9f, 0x60, 0xe7, 0x95, 0x64, 0x38, 0x09, 0x69, 0x20, 0x6f, 0xad, + 0xd7, 0xeb, 0xf4, 0x7e, 0x64, 0x53, 0x5e, 0xa8, 0x14, 0xfb, 0x33, 0xc4, + 0x5f, 0x29, 0xa7, 0x0d, 0x5d, 0x55, 0x64, 0x1d, 0x0d, 0xd0, 0x92, 0x0e, + 0x35, 0xe7, 0x83, 0x24, 0xdd, 0x8c, 0x79, 0x9c, 0x0f, 0xf1, 0x3d, 0x80, + 0x34, 0x06, 0xbc, 0xe9, 0x05, 0x18, 0x6d, 0x82, 0x8c, 0x83, 0x47, 0x3c, + 0x00, 0x7c, 0xe8, 0x2f, 0xeb, 0x26, 0xd9, 0xa0, 0xab, 0xa3, 0xc4, 0x3c, + 0x32, 0x9a, 0x3c, 0x42, 0xaf, 0xc8, 0xe0, 0x79, 0x87, 0xed, 0x16, 0x7e, + 0xb2, 0xb5, 0x76, 0x14, 0x84, 0xcc, 0x2a, 0x32, 0xd1, 0x19, 0x96, 0x14, + 0xf1, 0x53, 0xc8, 0xa5, 0x83, 0xe6, 0x22, 0xd4, 0x4e, 0xd1, 0x1d, 0xf3, + 0x81, 0x08, 0x6f, 0x56, 0x05, 0x67, 0x65, 0xb6, 0x56, 0x37, 0x1f, 0x3d, + 0xed, 0xd8, 0x40, 0x66, 0x9f, 0x27, 0xa8, 0x53, 0x48, 0x33, 0x6a, 0x38, + 0x37, 0x00, 0x93, 0x60, 0x2f, 0x2e, 0x07, 0x00, 0xc1, 0xe6, 0xb0, 0xbf, + 0x66, 0x43, 0xe1, 0x74, 0x4c, 0xca, 0x22, 0x0d, 0x10, 0x41, 0x5d, 0xf9, + 0x2c, 0x16, 0xe4, 0xe4, 0x25, 0x91, 0xbf, 0x67, 0x4e, 0x6c, 0x2d, 0x26, + 0x90, 0xcf, 0x8c, 0x5c, 0x1d, 0x93, 0x25, 0x69, 0xfd, 0xce, 0x38, 0xc1, + 0x66, 0xd9, 0x24, 0x98, 0xd2, 0x09, 0x04, 0xaa, 0x49, 0x48, 0x0e, 0x1b, + 0x73, 0x4d, 0x76, 0xf1, 0x63, 0x76, 0xc4, 0x9a, 0x5e, 0x35, 0xe7, 0x9c, + 0x2c, 0xf6, 0x28, 0x97, 0x9a, 0x14, 0x0e, 0xf5, 0xe2, 0x1b, 0xf6, 0xaf, + 0x65, 0x56, 0x42, 0xf2, 0x04, 0x7c, 0xfc, 0x31, 0x53, 0xb0, 0x78, 0xf4, + 0x77, 0x15, 0xf5, 0x3e, 0x0e, 0x8a, 0x97, 0x14, 0xd4, 0x7a, 0x05, 0xfe, + 0x9c, 0x08, 0x4c, 0x5a, 0x0c, 0x00, 0x4a, 0x9c, 0x6e, 0x9c, 0x59, 0xc0, + 0x39, 0x53, 0x3b, 0xf9, 0xb0, 0x86, 0x19, 0xb3, 0x59, 0x8c, 0xa5, 0xcf, + 0x47, 0xba, 0xa1, 0xc1, 0xe4, 0x9e, 0x80, 0x2d, 0x87, 0x30, 0x32, 0x1e, + 0xa5, 0xbd, 0x84, 0xab, 0xd8, 0xeb, 0xc1, 0x5e, 0xfc, 0x5e, 0x3c, 0x96, + 0xda, 0xe8, 0x5c, 0x8b, 0x4d, 0x42, 0x37, 0xf5, 0x46, 0x05, 0xf0, 0x09, + 0x1b, 0x94, 0xe6, 0xe5, 0xdf, 0x35, 0xcc, 0x48, 0x14, 0x91, 0x66, 0x5c, + 0xe2, 0xfe, 0x98, 0xff, 0x39, 0xed, 0x32, 0x81, 0x75, 0xe3, 0xaf, 0xd3, + 0x7f, 0xff, 0x00, 0x24, 0x2d, 0x83, 0xdc, 0x54, 0xda, 0xb7, 0xf5, 0x49, + 0x84, 0x35, 0x63, 0x48, 0x1a, 0x63, 0xf8, 0xe4, 0x23, 0x91, 0x87, 0x1f, + 0x1a, 0xdc, 0x34, 0x00, 0xe6, 0x12, 0xdf, 0x1d, 0xfe, 0x94, 0x4d, 0xfc, + 0xf8, 0x4b, 0xf6, 0xe7, 0x54, 0x32, 0xf9, 0xdd, 0x97, 0xb9, 0x2c, 0x5a, + 0x22, 0x3e, 0x61, 0x91, 0x4a, 0xfe, 0xb8, 0xfd, 0xb3, 0x1f, 0x11, 0x97, + 0x13, 0xcc, 0xec, 0x37, 0xc9, 0x9f, 0xb2, 0x04, 0x33, 0x12, 0xcd, 0x11, + 0x06, 0x07, 0x46, 0xca, 0x98, 0x20, 0xe3, 0x71, 0x44, 0xf2, 0xe5, 0x63, + 0x58, 0x9d, 0x08, 0xc1, 0xe1, 0x84, 0x61, 0x2c, 0x81, 0xbf, 0x65, 0xf6, + 0x93, 0x66, 0x8b, 0xe4, 0xcb, 0x3b, 0x62, 0xf6, 0xbd, 0x33, 0x85, 0x5b, + 0x03, 0x7e, 0x91, 0x5f, 0xc2, 0xd8, 0xc1, 0x4a, 0xd8, 0xc4, 0x0d, 0x80, + 0x10, 0xb5, 0xb3, 0x78, 0x5b, 0x95, 0x4d, 0x12, 0x14, 0xfa, 0xc4, 0x06, + 0x67, 0x39, 0x0f, 0xc2, 0x9d, 0x8a, 0x26, 0x26, 0x02, 0x79, 0x9a, 0xb0, + 0x51, 0xdc, 0x3a, 0x3f, 0x53, 0x0c, 0x78, 0x1a, 0xf8, 0x1f, 0x90, 0xd6, + 0x70, 0xef, 0x98, 0x2b, 0x6d, 0x29, 0xc7, 0x32, 0xbf, 0xfd, 0xe6, 0x32, + 0xe2, 0x08, 0x6f, 0xe4, 0x13, 0xce, 0x45, 0x85, 0xd0, 0x48, 0x59, 0x5c, + 0x78, 0x5a, 0xa6, 0x72, 0x45, 0x63, 0x3a, 0x0f, 0xde, 0xce, 0x59, 0xc7, + 0x4e, 0x6a, 0x3b, 0x69, 0x37, 0x16, 0x73, 0x09, 0xed, 0x9b, 0xe4, 0x07, + 0x10, 0x3d, 0x58, 0x81, 0x53, 0xc4, 0x0a, 0xc6, 0x5a, 0x68, 0x9d, 0x44, + 0x06, 0x5e, 0xac, 0x09, 0xc2, 0x7a, 0x03, 0x40, 0x12, 0x9a, 0xf4, 0x14, + 0x65, 0xdd, 0x4a, 0x47, 0x10, 0x1f, 0x5d, 0x58, 0x16, 0x06, 0x80, 0x81, + 0xa8, 0xfa, 0x0f, 0x66, 0xa0, 0xef, 0xce, 0x9a, 0xbc, 0x35, 0x9e, 0xb7, + 0x28, 0x47, 0x44, 0x82, 0x78, 0x02, 0xad, 0x2a, 0x0b, 0x19, 0x7f, 0x13, + 0xb3, 0x20, 0x4a, 0xd8, 0xd4, 0xd2, 0x96, 0x60, 0xa2, 0x64, 0x48, 0x66, + 0x65, 0x2b, 0x99, 0xd5, 0x35, 0xde, 0xec, 0xca, 0x14, 0xfb, 0x9d, 0x55, + 0x7b, 0x62, 0x68, 0x73, 0xf7, 0x82, 0xed, 0x25, 0x92, 0x85, 0x0b, 0xaa, + 0xc8, 0xf8, 0x1c, 0xb0, 0xb4, 0xcb, 0x58, 0x68, 0x19, 0x2f, 0x61, 0xb3, + 0x66, 0xde, 0x12, 0x6b, 0x0d, 0xef, 0x5a, 0xb9, 0x47, 0x8a, 0xd5, 0x91, + 0x41, 0x48, 0x92, 0xdc, 0x0c, 0x03, 0xf5, 0x06, 0xe2, 0xc7, 0xe2, 0x6c, + 0xc2, 0x80, 0x80, 0x27, 0xec, 0x56, 0x8a, 0x48, 0xb8, 0xc5, 0x32, 0x84, + 0xd6, 0x09, 0x3b, 0xe3, 0x96, 0xe6, 0x2e, 0xf6, 0x76, 0x3e, 0xff, 0xd5, + 0x11, 0x03, 0xcf, 0x66, 0xba, 0x84, 0x16, 0x58, 0xe9, 0x43, 0x6e, 0x6e, + 0x28, 0x47, 0x76, 0x72, 0x95, 0x26, 0x55, 0x59, 0x26, 0xf7, 0xed, 0xd6, + 0x06, 0xe5, 0xe0, 0x81, 0x2d, 0xd5, 0x15, 0x09, 0x56, 0xdd, 0x78, 0x4b, + 0x39, 0x81, 0x93, 0xbb, 0x8e, 0x8e, 0x1c, 0x93, 0xc3, 0xbb, 0xbd, 0xeb, + 0xcc, 0x6d, 0x2e, 0x79, 0xe7, 0x1b, 0x24, 0x79, 0x8c, 0x04, 0x63, 0x27, + 0xfd, 0x7e, 0x9a, 0x23, 0x1c, 0xac, 0x21, 0x2a, 0x89, 0x5e, 0xa2, 0x98, + 0x8a, 0x87, 0x2c, 0xa5, 0x10, 0x20, 0x2c, 0xea, 0x15, 0x9a, 0xd7, 0x5c, + 0x33, 0xb4, 0x88, 0x90, 0x59, 0x33, 0xff, 0x19, 0x9c, 0x7a, 0x54, 0x59, + 0x78, 0x0f, 0x63, 0x84, 0x40, 0xd2, 0x37, 0xc3, 0x98, 0x6c, 0x05, 0x7c, + 0x38, 0x01, 0xf6, 0x58, 0x04, 0x7b, 0x8c, 0x53, 0xea, 0xdf, 0x56, 0x14, + 0x49, 0xe2, 0x54, 0x1d, 0x1d, 0xe7, 0xc8, 0x23, 0x7b, 0x14, 0x44, 0xdb, + 0x1c, 0x3b, 0xc1, 0x27, 0x9e, 0x12, 0x02, 0xf9, 0x0d, 0x87, 0x73, 0x1b, + 0x7f, 0xa4, 0x08, 0x2b, 0x17, 0x11, 0xbd, 0xbc, 0xaa, 0x58, 0xfe, 0x24, + 0xb1, 0xe5, 0x3a, 0x9a, 0xb0, 0x95, 0xb4, 0xe7, 0x47, 0x1c, 0x0e, 0x78, + 0xf1, 0x35, 0x34, 0x83, 0xcd, 0x6a, 0x53, 0x51, 0x92, 0x7f, 0x2d, 0x65, + 0x3d, 0x3a, 0xbd, 0x81, 0xd7, 0x60, 0xfa, 0xf4, 0x15, 0xdd, 0x11, 0xd2, + 0x21, 0x94, 0x86, 0x0f, 0x8a, 0x16, 0x86, 0x69, 0xbe, 0x47, 0x97, 0x7d, + 0x8e, 0xe2, 0x83, 0x68, 0xf1, 0x34, 0x4f, 0x86, 0x0e, 0xe2, 0xc6, 0x1b, + 0x2d, 0x51, 0xe5, 0x34, 0x28, 0xf8, 0x41, 0x11, 0xc2, 0xf4, 0x8f, 0x29, + 0x64, 0x79, 0x2c, 0x08, 0x00, 0xb8, 0x83, 0x2d, 0x66, 0x27, 0x49, 0xc8, + 0xbb, 0x75, 0xea, 0x87, 0xfe, 0xb1, 0xf0, 0x73, 0xd2, 0x47, 0x93, 0x44, + 0xb0, 0x0d, 0x64, 0x10, 0x50, 0x73, 0xc0, 0xff, 0x83, 0xba, 0xdd, 0x9c, + 0xd2, 0x63, 0x8e, 0x92, 0xda, 0x12, 0xfe, 0x17, 0xfe, 0xb2, 0x31, 0x82, + 0xa7, 0x9c, 0xa3, 0xff, 0x7b, 0xf9, 0x03, 0x7a, 0xd9, 0xe7, 0x74, 0x49, + 0xd2, 0xf2, 0x5d, 0x5e, 0x97, 0x52, 0xf0, 0xc0, 0x90, 0xa2, 0x50, 0xb3, + 0x21, 0xd9, 0x42, 0xdb, 0x6c, 0x02, 0x38, 0xb1, 0xac, 0xc6, 0x4a, 0xd3, + 0xd6, 0xa4, 0x35, 0x3d, 0xef, 0xce, 0xc6, 0xda, 0x02, 0x38, 0xea, 0xa7, + 0xf8, 0xa1, 0x8e, 0x03, 0xa2, 0xd5, 0x0b, 0x9a, 0x04, 0xa6, 0x40, 0x34, + 0x58, 0x0d, 0xe9, 0x42, 0x13, 0x30, 0x18, 0x55, 0x1f, 0x33, 0xdb, 0x49, + 0x0f, 0xb2, 0x15, 0x43, 0x99, 0x18, 0x3e, 0x5a, 0x64, 0xdc, 0x85, 0xc1, + 0x3b, 0x81, 0x73, 0x64, 0x5b, 0x49, 0x2f, 0x4d, 0xa7, 0x97, 0xff, 0x2e, + 0x73, 0x7b, 0x09, 0x24, 0x53, 0x90, 0x84, 0x13, 0x9e, 0xef, 0xb1, 0x30, + 0x93, 0x84, 0x07, 0xc8, 0x2c, 0x0b, 0xb3, 0xb1, 0x2a, 0x44, 0xcc, 0x86, + 0x3d, 0x7d, 0xfb, 0x91, 0x62, 0xa5, 0xb7, 0xe8, 0x28, 0xa6, 0x84, 0xcc, + 0xdc, 0xf9, 0x3f, 0x41, 0xa3, 0x91, 0xc1, 0x24, 0x11, 0xeb, 0xbf, 0x11, + 0x4a, 0x92, 0x90, 0x0d, 0x67, 0x8b, 0x41, 0x24, 0x53, 0xf7, 0xbe, 0xae, + 0xa1, 0x48, 0x61, 0x3d, 0x8f, 0xcf, 0x2d, 0xdb, 0xfd, 0x1e, 0xc0, 0x89, + 0x93, 0xf3, 0x0a, 0x49, 0x42, 0xfe, 0xe3, 0x3c, 0x38, 0xf1, 0x17, 0x54, + 0x4f, 0x67, 0xf8, 0x30, 0xd9, 0x1b, 0x14, 0x65, 0x2e, 0xcc, 0xde, 0xaf, + 0x2b, 0xd7, 0x2a, 0xef, 0x9f, 0xa7, 0x28, 0x9f, 0xb9, 0xe2, 0xf5, 0xeb, + 0x7b, 0x27, 0x3b, 0x8b, 0x86, 0x07, 0xca, 0x2a, 0x0c, 0x75, 0x46, 0x66, + 0x9d, 0xa5, 0x6a, 0x3f, 0x5e, 0xdc, 0x49, 0xcf, 0xbd, 0xa2, 0xff, 0x07, + 0x79, 0xa4, 0xff, 0x7d, 0xfc, 0x47, 0x6b, 0x34, 0xdc, 0xc7, 0xeb, 0x53, + 0x65, 0x51, 0x71, 0xda, 0x49, 0x20, 0xea, 0xe5, 0xd3, 0xb0, 0xea, 0x26, + 0x1b, 0x82, 0xcf, 0x81, 0x2d, 0x8c, 0x47, 0x0a, 0xfe, 0x8a, 0x6c, 0x15, + 0xc1, 0xc4, 0x47, 0x82, 0x60, 0x01, 0x3c, 0x50, 0x20, 0x5f, 0xef, 0xe3, + 0xdf, 0xa9, 0xf9, 0x2e, 0xb2, 0xe6, 0xd0, 0xa9, 0xb1, 0x7e, 0x98, 0xcd, + 0x39, 0x40, 0xe1, 0x2d, 0xb6, 0xe0, 0x70, 0x44, 0xb0, 0x49, 0xa7, 0xea, + 0xbb, 0xc8, 0xaa, 0xcd, 0x8d, 0x62, 0x28, 0x7f, 0xab, 0x12, 0x6d, 0x0f, + 0x65, 0xc1, 0x4c, 0x00, 0x72, 0x08, 0xd9, 0xd5, 0x48, 0x60, 0x7c, 0xe2, + 0xc3, 0x05, 0x7b, 0x43, 0x60, 0x83, 0xd2, 0x38, 0x5a, 0xf7, 0x66, 0xfc, + 0x3c, 0x16, 0x12, 0x0e, 0x1f, 0xc8, 0x62, 0x6d, 0x91, 0x6c, 0xd2, 0x7a, + 0x68, 0x53, 0x04, 0xfc, 0x05, 0x1c, 0x6d, 0xa9, 0xcb, 0xf5, 0xe0, 0x54, + 0x08, 0xf8, 0xdf, 0x06, 0xf6, 0x18, 0xbb, 0x69, 0x49, 0xde, 0x70, 0xc2, + 0x21, 0x12, 0x5c, 0xca, 0xd0, 0x79, 0xc8, 0x49, 0x65, 0x6d, 0x46, 0xf0, + 0xf4, 0xa0, 0x67, 0xf8, 0x3b, 0x68, 0x01, 0x83, 0x24, 0x89, 0x38, 0xe6, + 0xc4, 0x2d, 0x8f, 0x32, 0x1e, 0xeb, 0xc8, 0xb8, 0xc6, 0x15, 0x7e, 0x68, + 0x9a, 0xa6, 0x0b, 0x03, 0x3f, 0x25, 0x35, 0x11, 0x1a, 0x52, 0xe4, 0x99, + 0x02, 0x77, 0x0a, 0xe0, 0x20, 0x6c, 0xd0, 0x61, 0x78, 0xb4, 0xe4, 0xd8, + 0xcb, 0x31, 0x51, 0x3c, 0xce, 0xb0, 0x3b, 0x65, 0xdf, 0x32, 0x09, 0xda, + 0x1b, 0x94, 0xeb, 0xa4, 0xbb, 0xf6, 0x06, 0x30, 0x40, 0xf9, 0x9e, 0x22, + 0x8c, 0x40, 0x3a, 0xc4, 0xe4, 0x1b, 0x66, 0xf0, 0xbf, 0x72, 0xfe, 0xf4, + 0x69, 0xdd, 0xf9, 0xbc, 0xbc, 0xc6, 0x37, 0x39, 0xa9, 0xf7, 0x16, 0xe2, + 0xe8, 0xd2, 0x2a, 0x4d, 0x36, 0x5a, 0xd2, 0x0c, 0xbe, 0x1b, 0x15, 0x8c, + 0x44, 0x01, 0xea, 0x35, 0x53, 0x05, 0x80, 0xd3, 0x13, 0x36, 0x89, 0x04, + 0x21, 0xce, 0xd0, 0xbd, 0x8d, 0xe4, 0x77, 0x2c, 0x7b, 0x48, 0x4c, 0x2c, + 0x05, 0x4f, 0x29, 0xb2, 0xc1, 0x04, 0x36, 0xde, 0x52, 0x16, 0x48, 0xab, + 0xc0, 0xd1, 0xfa, 0x84, 0xdf, 0x92, 0xe8, 0x69, 0xcb, 0x35, 0x2d, 0xe3, + 0xc9, 0xc4, 0xd3, 0x36, 0xc5, 0xc8, 0x62, 0x05, 0x55, 0xe8, 0xd1, 0x52, + 0x73, 0x0b, 0xc9, 0xd3, 0x4e, 0x80, 0x5b, 0x8f, 0x65, 0x13, 0x12, 0x01, + 0x90, 0x38, 0xd3, 0x93, 0x37, 0x12, 0x36, 0xd5, 0x90, 0xdc, 0x10, 0xae, + 0x5a, 0x70, 0xa4, 0xc5, 0x0d, 0x41, 0xa3, 0x0d, 0xbb, 0x2e, 0xac, 0xb3, + 0x80, 0xe2, 0x59, 0x88, 0x2d, 0x9d, 0x69, 0x8e, 0xa0, 0xd8, 0xf9, 0x3a, + 0x19, 0x51, 0x16, 0xe7, 0xe6, 0x41, 0xb1, 0x55, 0x7a, 0xd2, 0xc9, 0x52, + 0xa6, 0x53, 0xaf, 0xc3, 0xf8, 0x80, 0x2d, 0x5f, 0x95, 0x9b, 0x90, 0x93, + 0xa4, 0x3e, 0x80, 0xb0, 0x89, 0xd1, 0x64, 0x38, 0x4d, 0x92, 0x46, 0xfe, + 0x69, 0xd6, 0xbf, 0x69, 0x4d, 0xa0, 0xe3, 0x5b, 0x78, 0x59, 0xe3, 0x60, + 0x8f, 0xd6, 0x63, 0xe3, 0xd6, 0xcd, 0x92, 0xf7, 0xda, 0x39, 0x46, 0x21, + 0x09, 0xaf, 0xd7, 0x1c, 0x3f, 0x63, 0x28, 0x8a, 0x7d, 0xc0, 0x8c, 0x3c, + 0xc1, 0x45, 0x46, 0x36, 0x00, 0xf2, 0xfe, 0x21, 0xe4, 0xec, 0x8f, 0xda, + 0xb7, 0x77, 0x3e, 0xc7, 0x74, 0xec, 0x5d, 0x52, 0x96, 0xf9, 0xfa, 0x6b, + 0x47, 0x1d, 0x66, 0xb3, 0xd6, 0x33, 0xe6, 0xce, 0xfa, 0xcd, 0xae, 0x1d, + 0x31, 0x04, 0xef, 0xd5, 0x83, 0x97, 0xd4, 0x87, 0x8d, 0x5e, 0xd8, 0x77, + 0x07, 0x34, 0x4b, 0x07, 0x7f, 0xfa, 0xe8, 0x26, 0x0d, 0xc5, 0xd8, 0xc9, + 0x27, 0xfa, 0xa4, 0xc0, 0xbc, 0xb5, 0x41, 0xf1, 0x97, 0x67, 0x27, 0x49, + 0xcb, 0xaf, 0x19, 0xdc, 0x58, 0xdc, 0x98, 0xbe, 0xeb, 0xf3, 0xf5, 0xc2, + 0xd9, 0xb5, 0x4e, 0x86, 0xf7, 0x6f, 0x48, 0xcf, 0x92, 0xf6, 0x23, 0xdd, + 0xe5, 0x1a, 0x9e, 0x9d, 0x9d, 0x9b, 0xb8, 0xaa, 0xfb, 0xdb, 0xfd, 0xa2, + 0x25, 0x6b, 0x9a, 0xf0, 0xed, 0xf3, 0x8c, 0x6f, 0x73, 0x8c, 0x70, 0x04, + 0xb9, 0x05, 0x2b, 0xb9, 0x04, 0xcd, 0xb0, 0xdb, 0x6b, 0x12, 0x03, 0xcd, + 0xf4, 0xf7, 0x26, 0xa0, 0x28, 0xc9, 0xcd, 0x49, 0x28, 0x09, 0x9c, 0x02, + 0x69, 0xd1, 0xb2, 0x0d, 0xdf, 0x41, 0x9f, 0x04, 0xd9, 0x9b, 0x04, 0x98, + 0xfc, 0x11, 0x7c, 0x1d, 0x03, 0x3c, 0x7c, 0xa7, 0x52, 0xc1, 0x9c, 0x32, + 0x21, 0x62, 0xd1, 0xfa, 0x51, 0xfc, 0xf9, 0x28, 0x14, 0xa0, 0x26, 0x05, + 0x56, 0x89, 0xb8, 0xd8, 0x74, 0xc0, 0x27, 0xd6, 0x71, 0x66, 0xbf, 0xb9, + 0x9b, 0xb8, 0x40, 0x3e, 0x34, 0x5a, 0x22, 0x24, 0xb0, 0xeb, 0x31, 0x7f, + 0xe2, 0xb8, 0x29, 0x9e, 0x49, 0x5a, 0x74, 0x03, 0x73, 0x94, 0x8f, 0x72, + 0x80, 0xdc, 0xfa, 0x9d, 0x3b, 0x4a, 0x36, 0xc4, 0x44, 0x36, 0x18, 0x84, + 0x3f, 0x75, 0xf7, 0xfc, 0x9a, 0xe3, 0x45, 0x18, 0x83, 0x9c, 0x11, 0x7a, + 0xd3, 0xa1, 0x1c, 0x7d, 0x21, 0x1a, 0x20, 0x36, 0x80, 0x05, 0x7d, 0x0d, + 0x38, 0x72, 0x38, 0x7c, 0x0d, 0x67, 0xaf, 0x0f, 0x43, 0x6a, 0xc8, 0xa9, + 0x9d, 0xe8, 0x1a, 0x29, 0xa2, 0xea, 0x4e, 0x8f, 0xac, 0x50, 0xe4, 0x88, + 0x2a, 0x3e, 0xaa, 0x99, 0x28, 0x78, 0x55, 0x8d, 0xaa, 0xd1, 0xa3, 0x9a, + 0x5f, 0x06, 0x38, 0x76, 0x06, 0x35, 0xf1, 0xb2, 0x71, 0x8e, 0xd1, 0x5a, + 0x08, 0xa6, 0x8b, 0xdb, 0xd8, 0xeb, 0x24, 0xa6, 0xfc, 0x67, 0x76, 0x3b, + 0x5c, 0xb5, 0x8d, 0xea, 0x28, 0x35, 0xaa, 0x66, 0x22, 0x8e, 0x23, 0x6a, + 0x44, 0x5e, 0xf9, 0x8b, 0xb4, 0x6b, 0x4c, 0x45, 0xdd, 0x7d, 0x12, 0xda, + 0x35, 0x5d, 0x58, 0x4a, 0xf6, 0x6e, 0x69, 0xf9, 0xf7, 0x87, 0xb6, 0x72, + 0x5b, 0x64, 0x2f, 0xca, 0x7f, 0xbe, 0x8b, 0xd2, 0x82, 0x5a, 0xda, 0xb0, + 0xff, 0xb0, 0x92, 0x67, 0x42, 0xb5, 0x0a, 0xdd, 0x93, 0x6a, 0x9e, 0x4c, + 0xaa, 0xc1, 0x29, 0xd5, 0x06, 0x4e, 0x93, 0xd8, 0x72, 0xe3, 0xde, 0x32, + 0x65, 0x84, 0x7c, 0x05, 0x8e, 0x88, 0x05, 0x25, 0x01, 0x7a, 0x1f, 0xba, + 0xf9, 0xfb, 0xf1, 0xb1, 0x45, 0xd4, 0xc6, 0x6f, 0xf0, 0x14, 0x5b, 0xe8, + 0xa1, 0x2d, 0x9c, 0xb9, 0xac, 0x8c, 0xcc, 0xae, 0x0d, 0x98, 0x8a, 0xd3, + 0xf7, 0xa4, 0xf2, 0x2d, 0x07, 0xfa, 0xa3, 0x8f, 0xf4, 0x07, 0x00, 0x99, + 0x8f, 0x3a, 0xe3, 0x1f, 0xe8, 0xfa, 0x37, 0x99, 0x6c, 0x94, 0xe1, 0x7e, + 0x8c, 0xf9, 0xc6, 0x35, 0xe2, 0x50, 0x79, 0x3e, 0xcc, 0xa0, 0x3f, 0xc8, + 0xac, 0xff, 0x2c, 0xe3, 0x8e, 0x65, 0xe2, 0x96, 0xa1, 0xfb, 0x9e, 0x63, + 0x78, 0xc4, 0xf0, 0x79, 0xc5, 0x49, 0xd0, 0xdb, 0x67, 0x88, 0xff, 0x8c, + 0x0b, 0x1c, 0x64, 0xe0, 0x39, 0x2d, 0x7c, 0xcc, 0x91, 0x72, 0xf3, 0xe6, + 0x86, 0x49, 0x75, 0xdd, 0x01, 0xf2, 0x6a, 0xad, 0x55, 0x1b, 0xd4, 0xde, + 0x71, 0x84, 0x3c, 0xa8, 0x38, 0x30, 0x99, 0xca, 0xc8, 0x8e, 0xca, 0xff, + 0x4c, 0x97, 0x92, 0xcb, 0xf1, 0x60, 0x0c, 0x1a, 0xc9, 0x18, 0x81, 0xb5, + 0x6f, 0x74, 0x38, 0x27, 0xd4, 0xe1, 0x44, 0xac, 0x1c, 0xce, 0xfb, 0x9d, + 0x1f, 0xb0, 0x69, 0xc3, 0xba, 0x3b, 0xd4, 0xb9, 0xc4, 0xbe, 0x02, 0x14, + 0x50, 0x89, 0x69, 0xba, 0xde, 0x06, 0xe3, 0x1b, 0x93, 0x1b, 0x2b, 0xbe, + 0x61, 0x91, 0x6e, 0x88, 0x81, 0x4b, 0xcc, 0xa0, 0x51, 0xa3, 0xd7, 0x08, + 0x70, 0x2c, 0xfe, 0x1d, 0x5c, 0xde, 0x38, 0x61, 0xc9, 0xb1, 0x54, 0x9a, + 0xc6, 0x8a, 0xb6, 0x09, 0x79, 0x2e, 0xd1, 0x38, 0xdd, 0xe9, 0x11, 0x60, + 0x42, 0x33, 0xac, 0x1e, 0xf1, 0xaa, 0x25, 0xae, 0xb7, 0xa3, 0x16, 0x42, + 0x62, 0x90, 0xa3, 0x0d, 0x67, 0xae, 0xc9, 0xcb, 0xc2, 0xec, 0xdb, 0xa3, + 0xd4, 0xe2, 0xd3, 0xe4, 0x45, 0x63, 0x69, 0xc0, 0x87, 0x42, 0xf8, 0x5a, + 0xa9, 0x74, 0xe0, 0x06, 0xcd, 0xb4, 0x05, 0x70, 0x75, 0xb8, 0x83, 0x5d, + 0xa7, 0xe3, 0xc4, 0x3f, 0xd0, 0x9d, 0x61, 0x48, 0x28, 0x92, 0x7b, 0x92, + 0x12, 0x27, 0xca, 0xec, 0x87, 0xdc, 0x5b, 0xf8, 0xc0, 0x28, 0x93, 0x2c, + 0x2e, 0xfc, 0x3c, 0x32, 0x23, 0xd0, 0xd0, 0xfd, 0x51, 0xd4, 0xca, 0xc2, + 0x46, 0xa0, 0xeb, 0x8c, 0xf5, 0xf0, 0x77, 0xba, 0x0b, 0xfc, 0x8e, 0x7b, + 0xe4, 0xe8, 0xc5, 0xde, 0xf5, 0x48, 0xbc, 0x0b, 0x87, 0xff, 0x15, 0x56, + 0x13, 0xeb, 0xc1, 0x01, 0xe0, 0x95, 0x08, 0x91, 0xab, 0x10, 0x3d, 0xba, + 0x4a, 0x9d, 0xaa, 0x6f, 0x59, 0x6d, 0x29, 0xf2, 0xab, 0x16, 0x3c, 0x54, + 0x0a, 0xdc, 0xb1, 0x71, 0x7c, 0x86, 0x65, 0xf1, 0x04, 0xcd, 0xe7, 0x5d, + 0x83, 0xd6, 0x42, 0x2f, 0x82, 0x7a, 0x73, 0x9f, 0x49, 0xb3, 0x14, 0x06, + 0x12, 0xb9, 0x1d, 0x96, 0xb5, 0xae, 0x82, 0x04, 0xf1, 0x49, 0x23, 0x01, + 0xfc, 0xe7, 0xcf, 0xfc, 0xcc, 0x47, 0x8e, 0x8f, 0xe4, 0x46, 0x0e, 0xc9, + 0xc0, 0x0b, 0x34, 0x41, 0x8a, 0xed, 0x8b, 0xc8, 0x33, 0x18, 0xbc, 0x51, + 0x1c, 0xe2, 0xaf, 0xb5, 0x1c, 0xba, 0x6f, 0x34, 0x43, 0xea, 0xd8, 0x56, + 0x9b, 0x43, 0xc9, 0x14, 0xd2, 0x36, 0xa4, 0xa4, 0x17, 0x87, 0x0e, 0x91, + 0x80, 0x20, 0xce, 0x88, 0x76, 0xfc, 0x31, 0x76, 0x71, 0x47, 0xee, 0x3a, + 0x73, 0xcf, 0x03, 0xaa, 0xe0, 0x8d, 0x0f, 0x59, 0xfc, 0x60, 0xdf, 0x92, + 0xf0, 0xc8, 0x93, 0xcb, 0xa9, 0x70, 0x61, 0xec, 0x5f, 0x7e, 0x51, 0xd6, + 0x35, 0xb1, 0x45, 0x4b, 0x62, 0xbb, 0xb8, 0x34, 0x83, 0xef, 0xb2, 0x11, + 0x97, 0xfb, 0xa7, 0xc4, 0x4a, 0x7f, 0xc1, 0x2d, 0x3c, 0x8c, 0x51, 0x96, + 0x94, 0x51, 0xe2, 0x47, 0x5c, 0x00, 0xd7, 0xf0, 0x9e, 0x89, 0x34, 0x87, + 0xd4, 0x7e, 0x5e, 0x92, 0xb1, 0x82, 0xaa, 0x0f, 0xb9, 0x95, 0x97, 0xcb, + 0xc1, 0x08, 0x8c, 0x0a, 0x25, 0x3e, 0xc8, 0x7a, 0x36, 0xdf, 0x42, 0x8a, + 0x71, 0x17, 0xe6, 0x4d, 0x37, 0x6a, 0xac, 0x7b, 0x32, 0xf1, 0x02, 0x36, + 0x4a, 0x07, 0x94, 0x46, 0xdf, 0x46, 0x90, 0xd8, 0x68, 0xb7, 0xf4, 0x7c, + 0x40, 0x00, 0x8f, 0xf5, 0x2d, 0xaa, 0x2c, 0x00, 0x12, 0x46, 0xf6, 0x61, + 0x18, 0xd3, 0x90, 0xf4, 0x75, 0x43, 0x80, 0x84, 0x32, 0x53, 0x74, 0xa9, + 0xd1, 0x23, 0xbd, 0x6f, 0xb1, 0xfa, 0x18, 0x76, 0x1f, 0xe8, 0x73, 0x8c, + 0xbf, 0x3e, 0x9c, 0xa3, 0x4c, 0xb9, 0x62, 0xb8, 0x78, 0x51, 0x1c, 0x71, + 0x86, 0x7e, 0x5f, 0xfa, 0xf9, 0x89, 0x1d, 0x59, 0x58, 0xdd, 0x81, 0x7b, + 0xbb, 0x0f, 0xfc, 0x10, 0x8d, 0x61, 0x1d, 0xb7, 0x15, 0x01, 0x54, 0x0c, + 0x5e, 0x31, 0x37, 0x83, 0x5f, 0xa6, 0x63, 0x76, 0x08, 0xbb, 0x7a, 0x63, + 0x00, 0x53, 0x81, 0x09, 0x8a, 0x67, 0x05, 0x0c, 0x4b, 0xbe, 0x83, 0xc0, + 0x5f, 0x12, 0x43, 0xe9, 0x93, 0x03, 0x2f, 0x22, 0x99, 0x97, 0xce, 0xe8, + 0x4b, 0x7a, 0x56, 0x36, 0x68, 0x14, 0x3b, 0x97, 0x3a, 0xea, 0x2b, 0x63, + 0x63, 0x00, 0xef, 0x50, 0x49, 0x10, 0x15, 0x6c, 0xc4, 0x00, 0xd0, 0x3e, + 0x24, 0xbf, 0x13, 0x85, 0x50, 0xa6, 0x4f, 0xe1, 0x90, 0x84, 0x04, 0xff, + 0x8c, 0x12, 0x8f, 0xdf, 0x3b, 0xda, 0x82, 0x79, 0xc9, 0xa2, 0x1b, 0x04, + 0xee, 0xc3, 0x16, 0xc8, 0x05, 0x2c, 0xc1, 0x8d, 0x36, 0xb9, 0xad, 0x95, + 0xb0, 0x76, 0x3d, 0xfc, 0x86, 0xa7, 0xcc, 0x66, 0x70, 0x95, 0x41, 0xcf, + 0xc2, 0x92, 0xa4, 0x42, 0x7f, 0x27, 0xbc, 0x46, 0x84, 0x5d, 0xcd, 0x21, + 0xb3, 0xa5, 0x73, 0x8f, 0xc8, 0x04, 0xd8, 0x4a, 0x7b, 0x00, 0x46, 0x30, + 0xe3, 0x37, 0x11, 0xbc, 0x5e, 0xeb, 0x79, 0x21, 0xca, 0x00, 0x59, 0x31, + 0x34, 0x29, 0xd3, 0xdf, 0x4a, 0xe3, 0xf7, 0x4c, 0xf1, 0xf0, 0x6c, 0x62, + 0x41, 0xd1, 0x8b, 0x17, 0x11, 0x47, 0xa7, 0x87, 0xce, 0x3a, 0xcc, 0xbc, + 0xb0, 0xe8, 0x4f, 0x2e, 0x78, 0xbd, 0x7c, 0xda, 0x56, 0x9d, 0x35, 0xa4, + 0x60, 0xf7, 0x96, 0x25, 0x1e, 0xdf, 0x6f, 0x62, 0xbe, 0xd6, 0xb0, 0x59, + 0x77, 0x64, 0xfc, 0x4a, 0x5a, 0xa2, 0x0a, 0xc7, 0xda, 0xde, 0xa1, 0x14, + 0x08, 0x0f, 0x94, 0x57, 0x28, 0xe5, 0x36, 0xa8, 0x94, 0xdb, 0x37, 0x2a, + 0x25, 0xc4, 0x80, 0xf0, 0xc3, 0x25, 0x30, 0xd4, 0xe6, 0x64, 0x48, 0x47, + 0x6b, 0x50, 0x80, 0xd9, 0x23, 0x1d, 0xff, 0x37, 0xa8, 0x46, 0x43, 0xaf, + 0x52, 0x4d, 0x7f, 0x2a, 0x8e, 0x8d, 0x10, 0x05, 0xd1, 0x8a, 0x3f, 0x57, + 0x4d, 0x1a, 0xfa, 0x38, 0x35, 0x99, 0x9e, 0xd2, 0x0a, 0x54, 0xc3, 0x8f, + 0xa9, 0xb8, 0x92, 0xd9, 0xa1, 0x2b, 0x3e, 0x2b, 0x98, 0xb6, 0xea, 0x8e, + 0xde, 0x14, 0x1c, 0xc7, 0x0e, 0x53, 0x3f, 0xc2, 0xb5, 0x46, 0x4a, 0xfe, + 0xe2, 0x5b, 0x55, 0x9b, 0x0d, 0x38, 0xeb, 0x6a, 0xdf, 0x84, 0xa6, 0xc8, + 0x65, 0x38, 0xa8, 0xd5, 0xc2, 0x07, 0x7d, 0xbd, 0x77, 0x97, 0xf1, 0x3f, + 0x1d, 0xa4, 0x79, 0x7e, 0xf1, 0xbf, 0xb3, 0x48, 0x33, 0x70, 0x39, 0x18, + 0x13, 0x1c, 0x29, 0x06, 0x15, 0xf3, 0x64, 0x4b, 0x38, 0x3b, 0xd5, 0x10, + 0xce, 0xf2, 0xa9, 0x12, 0x30, 0x9d, 0xc8, 0xfd, 0xf8, 0xdd, 0xd7, 0x3f, + 0xa7, 0x60, 0x69, 0x7c, 0x02, 0x5f, 0xc9, 0x13, 0xf8, 0xf1, 0xf5, 0xcf, + 0xdf, 0x24, 0x73, 0x13, 0x31, 0xed, 0xf4, 0xc4, 0x2c, 0x0d, 0x6f, 0x55, + 0x4b, 0xd3, 0x17, 0x1e, 0x30, 0xcf, 0xa4, 0xb9, 0x1f, 0xa1, 0xe4, 0x67, + 0xa0, 0x4d, 0x0a, 0x8f, 0xcc, 0x8e, 0x0e, 0x06, 0xe2, 0x9e, 0x5c, 0x80, + 0x1d, 0x74, 0xa4, 0x09, 0x09, 0xf2, 0xc2, 0x01, 0xf3, 0x27, 0xd6, 0x99, + 0xf9, 0x93, 0xce, 0x36, 0xc1, 0x2b, 0xd6, 0x9e, 0xbd, 0xcc, 0x04, 0x8b, + 0x8b, 0x58, 0xcb, 0xe7, 0x39, 0xe0, 0x61, 0x2f, 0xb0, 0x62, 0xe7, 0xe6, + 0x2f, 0x80, 0xc7, 0x68, 0x01, 0x2c, 0x53, 0x6f, 0xc7, 0x39, 0xba, 0x76, + 0xf6, 0xbc, 0x21, 0x8b, 0x5e, 0x05, 0xc6, 0x5d, 0xa8, 0x1f, 0x42, 0x52, + 0x4b, 0x90, 0xef, 0x74, 0x88, 0x49, 0x94, 0xb9, 0x30, 0x96, 0x20, 0x7f, + 0x83, 0x47, 0x7d, 0x8e, 0xbb, 0xe3, 0x96, 0x90, 0x9e, 0x19, 0xe9, 0x39, + 0x6c, 0x05, 0xdb, 0xd9, 0xed, 0xec, 0x01, 0xfe, 0x95, 0x85, 0xa5, 0xb9, + 0xfb, 0xc5, 0xe8, 0xae, 0xc5, 0x39, 0xec, 0xb9, 0xe3, 0x64, 0x96, 0x71, + 0xc2, 0xce, 0x8d, 0x71, 0x66, 0x9f, 0xfd, 0xd6, 0x69, 0x1a, 0xb3, 0x61, + 0xbd, 0x7f, 0xfd, 0x18, 0x9f, 0xcc, 0x63, 0x14, 0x7a, 0xbb, 0x9a, 0x75, + 0xf7, 0xff, 0x11, 0x6b, 0x32, 0x09, 0x47, 0xf5, 0x18, 0x11, 0x2a, 0x2d, + 0x11, 0x31, 0x29, 0x28, 0xf3, 0xd5, 0x62, 0xa9, 0x43, 0x6b, 0xcc, 0x1e, + 0x09, 0xad, 0xb3, 0x22, 0x4d, 0xfb, 0xfa, 0xb3, 0x75, 0xa1, 0x99, 0xbc, + 0x28, 0xd8, 0x8b, 0x22, 0x92, 0x9b, 0xe1, 0x18, 0xcb, 0x7b, 0x57, 0xdc, + 0x44, 0xdd, 0xf2, 0xa0, 0x6e, 0x01, 0x2a, 0x45, 0xa0, 0xe2, 0x62, 0x29, + 0xe1, 0x45, 0xf4, 0x39, 0xfa, 0x42, 0xfa, 0x3f, 0x00, 0x33, 0xfc, 0x14, + 0xf6, 0xa1, 0x5e, 0x00, 0x00 +}; diff --git a/Arduino/McLighting/htm_index_gz.h b/Arduino/McLighting/htm_index_gz.h new file mode 100644 index 0000000..c4a9306 --- /dev/null +++ b/Arduino/McLighting/htm_index_gz.h @@ -0,0 +1,1651 @@ +#include + +#define index_htm_gz_len 19752 +static const char index_htm_gz[] PROGMEM ={ + 0x1f, 0x8b, 0x08, 0x08, 0x27, 0x3d, 0x8e, 0x5c, 0x04, 0x00, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xdc, 0x5d, 0xdb, 0x7a, + 0xdb, 0xb8, 0x11, 0xbe, 0xef, 0xf7, 0xf5, 0x1d, 0x18, 0xa5, 0x4d, 0xa4, + 0xae, 0x24, 0xeb, 0x60, 0xbb, 0x8e, 0xbc, 0xf2, 0x36, 0xc9, 0x3a, 0x69, + 0xda, 0x1c, 0xb6, 0x71, 0xb6, 0x69, 0x9b, 0xe6, 0x73, 0x29, 0x09, 0x92, + 0x58, 0x53, 0xa4, 0x4a, 0x52, 0xb1, 0x1d, 0xd7, 0xcf, 0xd2, 0x9b, 0xde, + 0xf4, 0x05, 0x7a, 0xd5, 0xab, 0xf6, 0xc5, 0xfa, 0xcf, 0x00, 0x20, 0xc0, + 0x83, 0x64, 0xd9, 0xb1, 0xd5, 0x83, 0x77, 0x23, 0x89, 0xc0, 0x60, 0x66, + 0x30, 0x18, 0x0c, 0x06, 0xc0, 0x00, 0xfc, 0xfa, 0xde, 0xb7, 0x6f, 0x9e, + 0xbe, 0xfb, 0xed, 0x77, 0x87, 0xce, 0x34, 0x99, 0xf9, 0x07, 0x3f, 0xfc, + 0xc1, 0xd7, 0xea, 0xdb, 0xc1, 0xdf, 0xd7, 0x53, 0xe1, 0x8e, 0xd4, 0x6f, + 0x7e, 0x4e, 0xbc, 0xc4, 0x17, 0x07, 0xaf, 0x86, 0x2f, 0xbd, 0xc9, 0x34, + 0xf1, 0x82, 0xc9, 0xd7, 0x5b, 0x9c, 0x62, 0x83, 0xcc, 0x44, 0xe2, 0x3a, + 0xc3, 0xa9, 0x1b, 0xc5, 0x22, 0xe9, 0x57, 0xbe, 0x7f, 0xf7, 0xac, 0xb1, + 0x57, 0x29, 0xe4, 0x07, 0xee, 0x4c, 0xf4, 0x2b, 0x9f, 0x3c, 0x71, 0x3a, + 0x0f, 0xa3, 0xa4, 0xe2, 0x0c, 0xc3, 0x20, 0x11, 0x01, 0xe0, 0x4f, 0xbd, + 0x51, 0x32, 0xed, 0x8f, 0xc4, 0x27, 0x6f, 0x28, 0x1a, 0xfc, 0x50, 0x77, + 0xbc, 0xc0, 0x4b, 0x3c, 0xd7, 0x6f, 0xc4, 0x43, 0xd7, 0x17, 0xfd, 0x76, + 0xb3, 0xb5, 0x0c, 0xdf, 0x2c, 0x1c, 0x78, 0x3e, 0x8a, 0x89, 0x41, 0xc3, + 0x9d, 0xcf, 0x1b, 0x43, 0x77, 0xee, 0x0e, 0x7c, 0x61, 0x61, 0x3f, 0x17, + 0x71, 0xa6, 0xac, 0xef, 0x05, 0x27, 0x4e, 0x24, 0xfc, 0x7e, 0x25, 0x9e, + 0x82, 0x8f, 0xe1, 0x22, 0x71, 0x3c, 0x00, 0x57, 0x9c, 0x69, 0x24, 0xc6, + 0xfd, 0xca, 0x34, 0x49, 0xe6, 0x71, 0x6f, 0x6b, 0x6b, 0x38, 0x0a, 0x9a, + 0x91, 0x7b, 0x3a, 0xf1, 0x92, 0xe6, 0x30, 0x9c, 0x6d, 0x25, 0xe1, 0xc0, + 0x5f, 0xcc, 0xb6, 0x8c, 0x14, 0xbe, 0x7f, 0xb1, 0xd5, 0xee, 0x6e, 0xef, + 0x8a, 0x6e, 0x77, 0x7b, 0x6b, 0xe6, 0x26, 0x22, 0x02, 0xb7, 0x56, 0xf6, + 0xcb, 0x70, 0x12, 0x6e, 0x8d, 0xdd, 0x4f, 0x84, 0xba, 0x89, 0x8f, 0x8a, + 0x93, 0x9c, 0xcf, 0xc1, 0xae, 0x37, 0x73, 0x27, 0x62, 0xeb, 0xac, 0x21, + 0x49, 0x6e, 0x95, 0x33, 0x86, 0x8a, 0xa0, 0x4a, 0x49, 0xb8, 0x18, 0x4e, + 0x1b, 0x77, 0xc5, 0x5b, 0x9e, 0x46, 0x73, 0x1e, 0x4c, 0x96, 0xc9, 0x29, + 0x39, 0xf7, 0x45, 0x3c, 0x15, 0x22, 0xc9, 0x33, 0x32, 0x86, 0x90, 0xe3, + 0xe6, 0x24, 0x0c, 0x27, 0xbe, 0x70, 0xe7, 0x5e, 0xcc, 0xec, 0x0c, 0xe3, + 0xf8, 0x9b, 0xb1, 0x3b, 0xf3, 0xfc, 0xf3, 0xfe, 0x2b, 0x45, 0xfc, 0xab, + 0x17, 0xa0, 0x90, 0x6d, 0x06, 0x46, 0x8a, 0x84, 0x9f, 0x38, 0x17, 0x94, + 0x3a, 0x70, 0x87, 0x27, 0x93, 0x28, 0x5c, 0x04, 0xa3, 0x46, 0x24, 0xe6, + 0xc2, 0x4d, 0x7a, 0x4e, 0x10, 0xaa, 0x9f, 0xfb, 0x04, 0x30, 0x77, 0x47, + 0x23, 0xf0, 0xde, 0x73, 0x5a, 0xfc, 0x38, 0x73, 0xa3, 0x89, 0x17, 0xc8, + 0xa7, 0x4b, 0x60, 0xa9, 0x3b, 0x3d, 0x77, 0x0c, 0x62, 0xf8, 0x1e, 0x88, + 0x71, 0x18, 0x09, 0x46, 0x8b, 0x3f, 0xd2, 0x8c, 0x13, 0x2f, 0x69, 0x0c, + 0xc2, 0xb3, 0x46, 0xec, 0x7d, 0x66, 0x14, 0x5e, 0x30, 0x05, 0x5b, 0x8c, + 0x17, 0x7f, 0x25, 0x39, 0x12, 0x29, 0x75, 0x0a, 0x8d, 0x86, 0x6a, 0x4a, + 0x50, 0xa2, 0xb7, 0xdb, 0x69, 0xee, 0xfc, 0x98, 0xf3, 0x07, 0xe1, 0xe8, + 0xbc, 0x98, 0xdf, 0x6e, 0xee, 0x88, 0x99, 0x42, 0x0d, 0x19, 0x8a, 0xc6, + 0x54, 0x90, 0xdc, 0x91, 0xbe, 0xbb, 0x6f, 0xc1, 0x9e, 0xca, 0xd4, 0xed, + 0x56, 0xcb, 0x4e, 0x95, 0x72, 0xeb, 0x55, 0xde, 0x42, 0xeb, 0x4f, 0xdd, + 0xf3, 0x4a, 0xbd, 0xf2, 0x73, 0xe1, 0x7f, 0x12, 0x89, 0x37, 0x74, 0x5f, + 0x8b, 0x85, 0xb0, 0x9f, 0x1d, 0x99, 0x90, 0x3e, 0xd7, 0x1f, 0x93, 0xa4, + 0xeb, 0xb1, 0x1b, 0xc4, 0x8d, 0x18, 0x95, 0x18, 0x2b, 0xbc, 0xc3, 0xd0, + 0x0f, 0xa3, 0xde, 0xfd, 0x4e, 0xa7, 0x23, 0x99, 0x5e, 0x24, 0x49, 0x18, + 0xd4, 0x9d, 0x0f, 0x52, 0x1f, 0xe5, 0x63, 0xe5, 0x63, 0x9a, 0x10, 0x09, + 0xf4, 0x61, 0xeb, 0x39, 0x5e, 0x0c, 0x66, 0x9e, 0x4c, 0x88, 0x42, 0xdf, + 0x2a, 0x21, 0x6b, 0x3e, 0x5c, 0x44, 0x31, 0xd0, 0x3b, 0xf3, 0xd0, 0x0b, + 0x20, 0xfe, 0xfd, 0x0c, 0x0d, 0x2f, 0x98, 0x2f, 0x92, 0xba, 0x13, 0xce, + 0x13, 0x6a, 0xda, 0x79, 0xdd, 0x89, 0x85, 0x2f, 0x86, 0x48, 0x49, 0xc4, + 0x59, 0xe2, 0x46, 0xc2, 0x25, 0x1c, 0xb2, 0xe6, 0x46, 0xf4, 0xce, 0xd6, + 0x4f, 0x9c, 0xa3, 0xb9, 0x18, 0x7a, 0xe3, 0x73, 0xce, 0xd1, 0x19, 0x6e, + 0x30, 0x14, 0x4e, 0x38, 0x46, 0x5a, 0x34, 0x73, 0x80, 0x67, 0x26, 0xa0, + 0x7b, 0xce, 0x4f, 0xb6, 0x2c, 0x8a, 0x12, 0x5d, 0xf8, 0x49, 0x44, 0x63, + 0x3f, 0x3c, 0xed, 0x39, 0x9f, 0xbc, 0xd8, 0x83, 0x31, 0x60, 0x94, 0x8f, + 0x47, 0x23, 0x54, 0x2d, 0x76, 0xfe, 0xa0, 0xb3, 0xff, 0xe0, 0xa0, 0xa2, + 0x4e, 0x12, 0x3a, 0x7f, 0x98, 0x7a, 0xa3, 0x91, 0x08, 0xfe, 0x00, 0x42, + 0xce, 0x8b, 0x43, 0x67, 0x6f, 0xeb, 0xd1, 0x56, 0xbb, 0xb5, 0xd5, 0x6e, + 0x67, 0x71, 0xf7, 0x7a, 0x8d, 0x59, 0xf8, 0xb9, 0x31, 0x0e, 0x87, 0x8b, + 0xb8, 0xe1, 0x05, 0x81, 0x88, 0x0a, 0x32, 0x2c, 0x82, 0xe4, 0xa5, 0x5a, + 0x84, 0x28, 0xc8, 0xb9, 0x08, 0xe2, 0x5c, 0x14, 0xf4, 0xdf, 0x70, 0x65, + 0x80, 0x23, 0xe4, 0x6e, 0x96, 0xa5, 0x70, 0x91, 0x90, 0x82, 0x4b, 0x96, + 0xa8, 0x1f, 0x45, 0x23, 0x11, 0xe5, 0x18, 0xac, 0xf3, 0x10, 0x73, 0x6d, + 0x6d, 0x23, 0x02, 0xa6, 0xef, 0xba, 0x73, 0x98, 0x81, 0x08, 0x0a, 0x00, + 0x5a, 0x12, 0x05, 0x37, 0xe9, 0xd3, 0x30, 0x8a, 0xc4, 0x10, 0x6d, 0x38, + 0x15, 0x68, 0x3b, 0x17, 0xe3, 0x80, 0x97, 0x9c, 0x53, 0x8b, 0xb2, 0x6d, + 0x71, 0x86, 0xbe, 0x37, 0x3c, 0xa1, 0xc1, 0x80, 0x4d, 0x6f, 0x4c, 0xcd, + 0xeb, 0xbd, 0x39, 0xca, 0xb6, 0xaa, 0x56, 0x49, 0xa6, 0xc7, 0x6a, 0xd9, + 0x48, 0x40, 0x28, 0x26, 0x25, 0x23, 0x0b, 0x14, 0x48, 0xe5, 0x79, 0xe6, + 0x45, 0x30, 0x2a, 0x67, 0xce, 0x76, 0xeb, 0xab, 0xba, 0xf3, 0x82, 0x14, + 0x3d, 0x80, 0xee, 0x1c, 0x9e, 0xcd, 0xd1, 0xb5, 0x20, 0x8d, 0x76, 0xbb, + 0x01, 0xb4, 0x45, 0xd5, 0x2f, 0x2a, 0x7c, 0xc1, 0xd8, 0xc9, 0xde, 0xe9, + 0x30, 0xd1, 0x39, 0x20, 0x82, 0xc4, 0x92, 0x65, 0x83, 0x2b, 0x22, 0xf9, + 0xe0, 0x64, 0x86, 0xce, 0x59, 0xa9, 0xde, 0xc8, 0x8b, 0xa9, 0x96, 0xa3, + 0xfa, 0x0f, 0x7f, 0xf0, 0x41, 0xff, 0xfe, 0x28, 0x1b, 0x68, 0xee, 0x0e, + 0x21, 0x12, 0x34, 0x49, 0x73, 0x5b, 0x02, 0x37, 0x07, 0x49, 0x70, 0x7c, + 0x2c, 0xc7, 0x46, 0x55, 0x69, 0xd7, 0xf7, 0x26, 0x41, 0xc3, 0x4b, 0xc4, + 0x2c, 0xee, 0x39, 0x43, 0x41, 0x95, 0xb3, 0x59, 0x88, 0xdc, 0x91, 0xb7, + 0x88, 0x53, 0x9a, 0x86, 0x8d, 0x6c, 0x12, 0x08, 0xcf, 0x7d, 0x17, 0xa4, + 0xc6, 0xbe, 0x38, 0xa3, 0x14, 0xfe, 0xd1, 0x73, 0xda, 0x4e, 0xcb, 0x71, + 0x17, 0x49, 0xc8, 0x49, 0x7f, 0x5c, 0xc4, 0x09, 0xba, 0x75, 0x43, 0xd1, + 0x37, 0xe4, 0x8c, 0x41, 0xb7, 0xc1, 0xe7, 0x61, 0x0c, 0x27, 0x00, 0x4a, + 0x4e, 0xc3, 0x90, 0x9b, 0x78, 0x9f, 0x58, 0x08, 0x2c, 0x2b, 0x99, 0x41, + 0x15, 0xeb, 0xc6, 0xb0, 0x41, 0x03, 0x6f, 0xd8, 0x18, 0x88, 0xcf, 0x9e, + 0x88, 0xaa, 0xad, 0x66, 0x67, 0xa7, 0x8e, 0xf4, 0x3d, 0xfa, 0xc0, 0xaf, + 0x76, 0x8d, 0x0b, 0x9d, 0x4e, 0x51, 0xc3, 0x46, 0x0c, 0x81, 0xb0, 0x3c, + 0x4f, 0x23, 0x77, 0xce, 0xe9, 0xec, 0x6e, 0xa4, 0x55, 0x31, 0x42, 0xba, + 0x96, 0x6c, 0x76, 0xe7, 0x67, 0xb6, 0x10, 0x08, 0x1d, 0x5b, 0x7e, 0x29, + 0x0b, 0x43, 0xa5, 0xd3, 0x6e, 0x29, 0x48, 0x35, 0x26, 0x38, 0x5d, 0x2a, + 0x6a, 0xa4, 0xd5, 0x32, 0xd5, 0xb7, 0x87, 0x14, 0xa7, 0xbd, 0xcd, 0x60, + 0xd9, 0xa1, 0xc3, 0xd9, 0x69, 0xb5, 0xd6, 0x16, 0x2b, 0xe8, 0x38, 0x7b, + 0x0a, 0x89, 0x31, 0x25, 0x4e, 0x5b, 0xd3, 0x9f, 0x79, 0x41, 0x43, 0x71, + 0xb9, 0x47, 0x70, 0xb9, 0xfe, 0x9d, 0xf6, 0x8e, 0x91, 0x18, 0x86, 0x91, + 0x4b, 0xc2, 0x67, 0xb5, 0xbc, 0x59, 0x8b, 0xd4, 0xa5, 0x06, 0x39, 0xed, + 0x59, 0xbc, 0xaa, 0xa1, 0x61, 0xa8, 0x69, 0x60, 0xf3, 0x1b, 0xd4, 0x0c, + 0xc8, 0x9c, 0xc1, 0x4e, 0xc3, 0x9a, 0xdb, 0x96, 0x61, 0x11, 0xa3, 0x19, + 0x64, 0x27, 0x33, 0xfc, 0xd0, 0x1f, 0x59, 0xac, 0xf2, 0x5c, 0x95, 0x1d, + 0x97, 0xe7, 0xa6, 0x7f, 0x85, 0x5c, 0xa3, 0x1b, 0x8d, 0xc6, 0xc0, 0x0f, + 0x87, 0x27, 0x52, 0x45, 0x4c, 0xab, 0xdb, 0xae, 0xc6, 0x7e, 0x36, 0x8b, + 0xe9, 0x51, 0x13, 0xeb, 0xac, 0x7c, 0x87, 0x29, 0xfa, 0x2a, 0xaa, 0xfb, + 0xc8, 0x9c, 0xb4, 0xbc, 0x49, 0xb1, 0x9f, 0xd2, 0x66, 0x36, 0xca, 0x93, + 0xea, 0xdc, 0x5e, 0xeb, 0xc7, 0x19, 0x47, 0xc0, 0xb9, 0xff, 0xec, 0xd9, + 0x33, 0x4e, 0x49, 0xd5, 0x58, 0x67, 0x6c, 0x0f, 0xdd, 0xf1, 0x4e, 0xeb, + 0x9e, 0x37, 0x23, 0xff, 0xdc, 0x0d, 0xac, 0xde, 0xd0, 0x5c, 0xc0, 0x02, + 0x47, 0x43, 0x37, 0x66, 0xb7, 0xca, 0xe8, 0xf3, 0xae, 0xd4, 0xe7, 0xa2, + 0xe5, 0xd4, 0xf0, 0x59, 0xa9, 0x85, 0xb0, 0x8d, 0x33, 0x2d, 0x36, 0xf9, + 0x64, 0xba, 0x00, 0xfe, 0x22, 0xd6, 0x6b, 0xa3, 0x94, 0xb6, 0x66, 0xb8, + 0x83, 0x38, 0xf4, 0x17, 0x89, 0xc8, 0x54, 0x58, 0xab, 0xa6, 0xa5, 0xbf, + 0x26, 0x69, 0xaa, 0xbb, 0x89, 0x41, 0x27, 0x21, 0x4c, 0x4a, 0xc1, 0xad, + 0x2c, 0x74, 0xed, 0x9d, 0x54, 0x7c, 0x9f, 0x31, 0xf4, 0x8d, 0x48, 0xe6, + 0xdb, 0x39, 0x79, 0x8e, 0xc7, 0xda, 0xd5, 0x2a, 0xda, 0xf5, 0xfb, 0xe2, + 0x51, 0x5b, 0xec, 0x76, 0x8d, 0x4c, 0x33, 0x54, 0x96, 0x42, 0xa5, 0xec, + 0xfa, 0x7e, 0x03, 0xd3, 0xaa, 0x60, 0x22, 0x7a, 0xd2, 0x4d, 0x9d, 0xba, + 0xa3, 0xf0, 0x54, 0xe5, 0x9a, 0x04, 0xea, 0xc9, 0x5d, 0x74, 0xf0, 0x1d, + 0xfc, 0x6b, 0xb4, 0xf1, 0x11, 0x4d, 0x06, 0x6e, 0xb5, 0x55, 0xa7, 0xff, + 0x9a, 0x9d, 0x1a, 0xfa, 0x1d, 0xf7, 0x7f, 0xb2, 0x3e, 0xf8, 0x69, 0x67, + 0xb6, 0xb7, 0x39, 0xb7, 0x4d, 0xb9, 0x7b, 0xc5, 0xdc, 0x4e, 0x4d, 0xb6, + 0x1f, 0xcd, 0x60, 0x96, 0x9b, 0xc4, 0x55, 0xb6, 0xcf, 0x28, 0xb5, 0xf4, + 0x6f, 0xe1, 0xce, 0x2f, 0x22, 0x81, 0x8e, 0x95, 0xd0, 0x4c, 0x04, 0x28, + 0x1e, 0x02, 0x9f, 0xfb, 0x30, 0xd3, 0xf5, 0xae, 0x86, 0xb4, 0x4c, 0x63, + 0x07, 0xa6, 0xf1, 0x4a, 0x2b, 0x68, 0xfb, 0xe1, 0x4e, 0xfb, 0x46, 0x36, + 0xab, 0xcc, 0x22, 0xb1, 0xda, 0x2b, 0xb5, 0xb6, 0x04, 0xc5, 0x1f, 0x8d, + 0x06, 0x4d, 0xa0, 0x56, 0x38, 0xc9, 0x4d, 0x3d, 0x33, 0xe3, 0xe9, 0x57, + 0xdc, 0x9c, 0x8d, 0x50, 0x02, 0x0c, 0x52, 0x11, 0xad, 0x5c, 0xb2, 0x35, + 0x3a, 0x3b, 0xe0, 0x40, 0x7d, 0x30, 0x2f, 0x4b, 0x11, 0x8c, 0xdc, 0xe8, + 0xa4, 0x58, 0xbe, 0x55, 0x77, 0xe8, 0x7f, 0xae, 0x8f, 0x2a, 0x0b, 0x9f, + 0xe6, 0x1d, 0xbc, 0xa6, 0x57, 0xe1, 0xc8, 0xf5, 0x9d, 0xaa, 0xd1, 0xdb, + 0x1a, 0xfb, 0x31, 0xf7, 0x67, 0x9c, 0x7e, 0x91, 0xb5, 0xcd, 0x63, 0xef, + 0x4c, 0x8c, 0x50, 0xdc, 0xea, 0x0a, 0x6d, 0x7b, 0x3c, 0xc1, 0x64, 0x72, + 0x8e, 0xa4, 0x1d, 0x68, 0x19, 0x3b, 0x4d, 0x2f, 0xc3, 0x21, 0x0f, 0x14, + 0x70, 0xda, 0xc9, 0x45, 0x23, 0x7d, 0x05, 0x76, 0x6e, 0x0e, 0x31, 0x4e, + 0x74, 0x8f, 0xe3, 0x42, 0x2d, 0x7b, 0x94, 0x6c, 0xb7, 0x54, 0x9f, 0x93, + 0x0d, 0x96, 0x26, 0x18, 0xcf, 0x3e, 0xb5, 0x73, 0x99, 0x2e, 0x67, 0xaa, + 0x2c, 0xf5, 0xb7, 0x26, 0x5d, 0x37, 0xd7, 0xf7, 0x09, 0x48, 0x4a, 0x44, + 0x32, 0x50, 0x2c, 0x65, 0xab, 0x3d, 0x9c, 0x25, 0x59, 0xf4, 0x89, 0x4f, + 0xe5, 0x4e, 0xb7, 0xb4, 0x1f, 0xa5, 0x7d, 0xbc, 0x26, 0x8b, 0x47, 0x2b, + 0x9a, 0x71, 0x1d, 0x95, 0x56, 0x18, 0xc5, 0x2b, 0xb5, 0x08, 0x63, 0x41, + 0xff, 0x21, 0xb7, 0x68, 0xb5, 0x8d, 0x35, 0x22, 0x21, 0xe6, 0x35, 0x7d, + 0xbb, 0xd4, 0x09, 0xd8, 0x6d, 0x65, 0xbc, 0x6f, 0xee, 0xca, 0xb0, 0x94, + 0xde, 0xc8, 0xb9, 0xbf, 0xb7, 0xb7, 0xc7, 0x59, 0x66, 0x24, 0x90, 0x8d, + 0x8f, 0x1a, 0x10, 0xef, 0xae, 0xa7, 0x3c, 0x79, 0xe3, 0xab, 0xb5, 0x59, + 0xd6, 0x2b, 0x79, 0x53, 0x3d, 0x4e, 0x0a, 0x02, 0x1d, 0x3e, 0x5c, 0x40, + 0x02, 0xab, 0x3d, 0xc0, 0x36, 0x23, 0x49, 0x93, 0x1a, 0xe4, 0x7c, 0x59, + 0x4e, 0x58, 0xc1, 0x78, 0x1b, 0xcc, 0xcd, 0x28, 0x3c, 0x35, 0x1c, 0x36, + 0x46, 0x1e, 0xfc, 0x7d, 0xa9, 0x8c, 0xc8, 0x28, 0x40, 0x36, 0x23, 0x01, + 0x05, 0x89, 0xc5, 0xd2, 0x12, 0x0d, 0x05, 0x90, 0x2d, 0x89, 0x86, 0x59, + 0xcc, 0x82, 0xf2, 0x42, 0x32, 0xaf, 0x0c, 0x5e, 0x13, 0x5b, 0x55, 0x6e, + 0x25, 0xbd, 0x03, 0xa7, 0x49, 0xa5, 0x64, 0xf9, 0x99, 0x7b, 0xd6, 0xb0, + 0xd4, 0x3f, 0x5b, 0x80, 0xe4, 0x04, 0xb0, 0xac, 0xf8, 0xe8, 0x53, 0x81, + 0xc1, 0x49, 0xf9, 0xc4, 0x3d, 0xad, 0xd1, 0x25, 0xb0, 0xdc, 0xc8, 0x00, + 0x7d, 0xe8, 0xaa, 0x7f, 0x8d, 0x4e, 0x76, 0x6c, 0x68, 0xc9, 0xc1, 0x41, + 0xe5, 0x6e, 0xe3, 0x5f, 0x2b, 0x0f, 0xd0, 0xde, 0x96, 0x10, 0xac, 0x57, + 0x7b, 0xa5, 0x10, 0x9d, 0x9a, 0x63, 0x46, 0xae, 0x65, 0xba, 0xb8, 0xbb, + 0xbb, 0x5b, 0xe0, 0x76, 0xb7, 0x9c, 0x5b, 0x33, 0x92, 0x2d, 0xe1, 0x56, + 0x0d, 0x66, 0x57, 0xb2, 0xdb, 0x5e, 0x8f, 0xdf, 0x2c, 0x53, 0x8f, 0xca, + 0x99, 0xda, 0x51, 0x64, 0x1b, 0xdd, 0x3c, 0xbe, 0x9f, 0x2a, 0x8a, 0x8f, + 0x88, 0x22, 0x09, 0xb8, 0xc0, 0xf6, 0x8e, 0x25, 0xe4, 0x36, 0x21, 0x29, + 0x34, 0x43, 0x77, 0xa9, 0x08, 0xbb, 0xab, 0x45, 0xd8, 0xee, 0x94, 0xb3, + 0xfb, 0x53, 0xd5, 0x5a, 0x8d, 0xed, 0x52, 0x19, 0xa6, 0xac, 0x12, 0x5c, + 0x67, 0xa9, 0x10, 0x77, 0x28, 0x97, 0xb2, 0xb7, 0xaf, 0x29, 0xc4, 0xf6, + 0x4e, 0x39, 0x5b, 0x7b, 0x4a, 0x4e, 0x8d, 0x9d, 0xa5, 0x6c, 0x49, 0x9a, + 0x2b, 0xd9, 0x62, 0x11, 0x12, 0xaa, 0x9d, 0xb5, 0xd8, 0xa2, 0x4e, 0x53, + 0x27, 0x9b, 0x37, 0xf5, 0xfc, 0x11, 0xfb, 0x25, 0xe8, 0x7b, 0xb4, 0xec, + 0x58, 0x34, 0x51, 0x4b, 0xbb, 0xe2, 0xfd, 0x24, 0x0c, 0x31, 0x8c, 0x48, + 0x73, 0x69, 0x7c, 0x07, 0x33, 0x09, 0x2a, 0xd6, 0x95, 0xe5, 0xb6, 0x5c, + 0x8d, 0x55, 0xee, 0xce, 0xd5, 0x5a, 0xdc, 0x5a, 0xa2, 0xc5, 0xab, 0xa6, + 0x4e, 0xd9, 0x0a, 0x64, 0x3d, 0xc9, 0x74, 0xbc, 0xa6, 0x61, 0xb8, 0x9e, + 0x3e, 0x91, 0xf3, 0xad, 0x45, 0xa6, 0x6a, 0xbb, 0xe6, 0x4a, 0x41, 0xd1, + 0xf2, 0x1b, 0xaf, 0x9a, 0x47, 0x8b, 0x3c, 0x56, 0xde, 0x3f, 0x00, 0xce, + 0x9c, 0x27, 0xd7, 0x5a, 0x35, 0xc9, 0xf5, 0x45, 0x02, 0x7a, 0x3c, 0x83, + 0x97, 0x98, 0x9b, 0xad, 0x8e, 0x98, 0xad, 0x9c, 0xdb, 0x1b, 0x77, 0x41, + 0xae, 0xf0, 0x99, 0x99, 0x8a, 0xc9, 0x11, 0xbe, 0xef, 0xcd, 0x63, 0x2f, + 0x2e, 0x65, 0xb1, 0x17, 0x84, 0x49, 0xb5, 0x37, 0xf6, 0xa2, 0x38, 0x69, + 0xb0, 0xf6, 0xd4, 0x9c, 0x0b, 0x33, 0x36, 0xb2, 0xfc, 0x24, 0xdb, 0x4a, + 0x49, 0xc6, 0x61, 0x08, 0x1e, 0x4b, 0x56, 0x9e, 0x8b, 0x9e, 0x81, 0x99, + 0xd3, 0x95, 0x65, 0x96, 0xcb, 0xfa, 0xb6, 0xa7, 0x9b, 0xa9, 0xee, 0x64, + 0x54, 0xc7, 0xb4, 0x1e, 0x1b, 0x2b, 0xd3, 0x9d, 0x96, 0x4e, 0x52, 0xad, + 0x29, 0xa3, 0xa9, 0x9a, 0xce, 0x53, 0x5d, 0xab, 0x00, 0xb2, 0x34, 0xdb, + 0xcc, 0xe7, 0x0a, 0x8b, 0x24, 0x86, 0xb8, 0xdd, 0x03, 0x9b, 0x9d, 0x9c, + 0xf3, 0xde, 0xdc, 0xe6, 0x79, 0x4f, 0xbd, 0x5d, 0x53, 0xa5, 0xd6, 0x87, + 0x66, 0xef, 0xe8, 0x67, 0x33, 0x31, 0xf2, 0x5c, 0x27, 0x0c, 0xfc, 0x73, + 0x27, 0x1e, 0x46, 0x42, 0x04, 0x8e, 0x1b, 0x8c, 0x9c, 0xaa, 0xe5, 0xa6, + 0x3c, 0xa2, 0x99, 0xaf, 0xd2, 0x86, 0xbc, 0x33, 0x95, 0x31, 0x21, 0x8f, + 0x5a, 0x5a, 0xab, 0x2f, 0x81, 0x7d, 0x2d, 0xdc, 0xed, 0xce, 0xee, 0xf6, + 0x7a, 0xc8, 0xdb, 0xed, 0xbd, 0x9d, 0x6b, 0x63, 0x7f, 0xd4, 0x5a, 0x17, + 0xfb, 0x4f, 0xd7, 0xc5, 0x6e, 0x55, 0x77, 0xe7, 0x51, 0x39, 0xf2, 0xa2, + 0x62, 0x15, 0x11, 0xc3, 0x53, 0x2f, 0xb0, 0xdb, 0xd2, 0xc8, 0x48, 0x5f, + 0x9a, 0x67, 0x71, 0x5b, 0x3e, 0x2a, 0x57, 0x68, 0xe0, 0xa2, 0xeb, 0xc2, + 0xb3, 0x6d, 0x76, 0x33, 0x7f, 0x9d, 0x1f, 0xef, 0x5b, 0x40, 0x93, 0x88, + 0x4d, 0xf2, 0x7e, 0xae, 0x82, 0x4b, 0x8b, 0x5d, 0xda, 0xf4, 0x3a, 0x45, + 0x7a, 0xc4, 0x7e, 0x73, 0x37, 0xf3, 0xb7, 0xbd, 0x1e, 0xc1, 0x62, 0xb9, + 0x12, 0x8a, 0xdd, 0x32, 0x8a, 0x9d, 0x9d, 0xf5, 0x28, 0x00, 0xae, 0x88, + 0x71, 0xbb, 0x0c, 0x63, 0xb7, 0x9b, 0xab, 0xfd, 0x7a, 0x04, 0x8a, 0xc5, + 0x8a, 0xf4, 0x76, 0xca, 0xe8, 0x6d, 0xb7, 0xb3, 0x75, 0xff, 0xe9, 0x7a, + 0xf4, 0x8a, 0xc5, 0x8a, 0xf4, 0x76, 0xcb, 0xe8, 0xed, 0xb4, 0xd6, 0x23, + 0x00, 0xb8, 0x22, 0xc6, 0x9f, 0x96, 0x62, 0xcc, 0xeb, 0xcb, 0xee, 0x9a, + 0x14, 0x8a, 0xe5, 0x8a, 0x14, 0xf7, 0xca, 0x28, 0xee, 0xe6, 0xf4, 0x65, + 0x4d, 0x82, 0xc5, 0x62, 0x45, 0x7a, 0x8f, 0xca, 0xe8, 0xfd, 0x74, 0x4d, + 0x2d, 0xfb, 0x69, 0x99, 0x96, 0xb5, 0x5b, 0xa5, 0x5d, 0x33, 0xa7, 0x2f, + 0x6b, 0xf6, 0x94, 0x42, 0xb1, 0x32, 0x82, 0xa5, 0xb6, 0xe0, 0x51, 0xfb, + 0x46, 0x32, 0x7b, 0xd4, 0xbe, 0x5a, 0x66, 0xed, 0x72, 0x63, 0xd0, 0x5a, + 0x53, 0xd3, 0x08, 0x70, 0x3d, 0xa3, 0xb7, 0x4b, 0x83, 0x46, 0xc6, 0xf0, + 0xc5, 0xb3, 0xcd, 0x1a, 0xbe, 0x78, 0xb6, 0x69, 0xc3, 0x17, 0xcf, 0x6e, + 0xdb, 0xf0, 0xc5, 0xb3, 0xcd, 0x1a, 0xbe, 0x78, 0xb6, 0x59, 0xc3, 0x17, + 0xcf, 0x6e, 0xdb, 0xf0, 0xc5, 0xb3, 0x4d, 0x1b, 0xbe, 0x78, 0xb6, 0x59, + 0xc3, 0x17, 0xcf, 0x6e, 0xdb, 0xf0, 0xc5, 0xb3, 0x0d, 0x1b, 0xbe, 0x78, + 0xb6, 0x61, 0xc3, 0x17, 0xcf, 0x36, 0x66, 0xf8, 0xb4, 0x5b, 0x6d, 0x88, + 0xcf, 0x46, 0x9b, 0x35, 0x7c, 0xb3, 0xd1, 0xa6, 0x0d, 0xdf, 0x6c, 0x74, + 0xdb, 0x86, 0x6f, 0x36, 0xda, 0xac, 0xe1, 0x9b, 0x8d, 0x36, 0x6b, 0xf8, + 0x66, 0xa3, 0xdb, 0x36, 0x7c, 0xb3, 0xd1, 0xa6, 0x0d, 0xdf, 0x6c, 0xb4, + 0x59, 0xc3, 0x37, 0x1b, 0xdd, 0xb6, 0xe1, 0x9b, 0x8d, 0x36, 0x6c, 0xf8, + 0x66, 0xa3, 0x0d, 0x1b, 0xbe, 0xd9, 0x68, 0x63, 0x86, 0x2f, 0x9d, 0xf3, + 0x1b, 0xea, 0xfe, 0x64, 0xb3, 0x96, 0xcf, 0x9f, 0x6c, 0xda, 0xf2, 0xf9, + 0x93, 0xdb, 0xb6, 0x7c, 0xfe, 0x64, 0xb3, 0x96, 0xcf, 0x9f, 0x6c, 0xd6, + 0xf2, 0xf9, 0x93, 0xdb, 0xb6, 0x7c, 0xfe, 0x64, 0xd3, 0x96, 0xcf, 0x9f, + 0x6c, 0xd6, 0xf2, 0xf9, 0x93, 0xdb, 0xb6, 0x7c, 0xfe, 0x64, 0xc3, 0x96, + 0xcf, 0x9f, 0x6c, 0xd8, 0xf2, 0xf9, 0x93, 0xcd, 0x59, 0xbe, 0x74, 0x3d, + 0xd2, 0xcc, 0xb4, 0xfd, 0xcd, 0x5a, 0xbe, 0x33, 0x7f, 0xd3, 0x96, 0xef, + 0xcc, 0xbf, 0x6d, 0xcb, 0x77, 0xe6, 0x6f, 0xd6, 0xf2, 0x9d, 0xf9, 0x9b, + 0xb5, 0x7c, 0x67, 0xfe, 0x6d, 0x5b, 0xbe, 0x33, 0x7f, 0xd3, 0x96, 0xef, + 0xcc, 0xdf, 0xac, 0xe5, 0x3b, 0xf3, 0x6f, 0xdb, 0xf2, 0x9d, 0xf9, 0x1b, + 0xb6, 0x7c, 0x67, 0xfe, 0x86, 0x2d, 0xdf, 0x99, 0x7f, 0x27, 0x96, 0x6f, + 0xd5, 0x9e, 0xc9, 0xce, 0x23, 0x6b, 0xcf, 0x44, 0xee, 0x54, 0x36, 0xce, + 0xe2, 0x06, 0x15, 0xc9, 0x85, 0x98, 0xca, 0xdd, 0x66, 0x7b, 0x87, 0xdb, + 0x10, 0x6a, 0xd2, 0xfe, 0xa7, 0xdc, 0x6a, 0xc9, 0xb0, 0xd8, 0x2e, 0x6c, + 0x88, 0x2b, 0x1a, 0xa5, 0xb8, 0x25, 0x04, 0x07, 0x6f, 0xb9, 0xb4, 0x55, + 0x83, 0x93, 0x18, 0x32, 0xe0, 0xff, 0x27, 0x5b, 0xb4, 0x83, 0xee, 0x45, + 0x43, 0x1c, 0x1a, 0xa2, 0x83, 0x5e, 0xc9, 0xf1, 0xb1, 0x7c, 0x52, 0x5b, + 0xc3, 0x81, 0x37, 0x53, 0x51, 0xc1, 0x36, 0x50, 0x63, 0xec, 0xc1, 0xe4, + 0x63, 0xc7, 0x4d, 0x06, 0xc2, 0xc8, 0x60, 0x7a, 0x3a, 0x58, 0xe1, 0x50, + 0x21, 0x2b, 0x5e, 0x34, 0x0a, 0x13, 0x04, 0xb3, 0x55, 0x1b, 0x8f, 0x5a, + 0x23, 0x31, 0x91, 0xd1, 0x57, 0x9d, 0xba, 0xd3, 0x05, 0x64, 0x06, 0xb0, + 0x11, 0x62, 0x97, 0xda, 0x4b, 0xf7, 0x4a, 0x19, 0x6e, 0x5b, 0x86, 0x65, + 0x15, 0xd8, 0xf3, 0x82, 0x71, 0xb8, 0x8a, 0x39, 0x7d, 0xac, 0x80, 0xd8, + 0x03, 0xee, 0x53, 0x37, 0x1a, 0xc5, 0xfb, 0xd9, 0xa8, 0xf9, 0xfd, 0x2c, + 0x97, 0xf2, 0xa7, 0x0f, 0x46, 0x7f, 0x5b, 0x45, 0xcc, 0x86, 0x98, 0xa9, + 0x1d, 0xc3, 0x9f, 0x9d, 0x88, 0xf3, 0x71, 0x84, 0xd3, 0x68, 0x71, 0xb1, + 0xf2, 0x2a, 0x60, 0x00, 0x9c, 0xe0, 0x54, 0x42, 0x14, 0x9e, 0x08, 0xc4, + 0xe8, 0xc5, 0xc8, 0x8d, 0x5c, 0x22, 0x40, 0xda, 0xb2, 0xef, 0x5c, 0x16, + 0xb0, 0x14, 0xb9, 0xd4, 0x78, 0xe4, 0x77, 0xca, 0xa4, 0x0e, 0xc1, 0x5b, + 0xca, 0x66, 0xcd, 0x52, 0x11, 0x3a, 0x58, 0x13, 0x20, 0x20, 0x8d, 0xe2, + 0x18, 0xb6, 0x9c, 0x77, 0xa1, 0x1b, 0x27, 0x32, 0xdc, 0x2f, 0xe6, 0x54, + 0x45, 0x84, 0x4f, 0xcd, 0xc8, 0xb3, 0x14, 0x99, 0x8d, 0x73, 0x6b, 0xcc, + 0xee, 0x70, 0x78, 0x5a, 0x61, 0x27, 0x1c, 0xd1, 0x28, 0xd8, 0x30, 0x5c, + 0x16, 0xf7, 0x86, 0xfe, 0x8d, 0xac, 0x62, 0xd8, 0xac, 0x89, 0x9c, 0x5b, + 0x15, 0x62, 0xdf, 0x61, 0xc4, 0xf9, 0x2d, 0xc4, 0x35, 0x03, 0x14, 0x89, + 0x3d, 0x1e, 0x03, 0x4c, 0xc4, 0x61, 0xb7, 0x24, 0xc0, 0xae, 0xfd, 0x53, + 0xb5, 0x93, 0x6f, 0x24, 0xd2, 0xc4, 0x19, 0xc1, 0xd3, 0x6e, 0xab, 0xd5, + 0x2a, 0x88, 0x46, 0xfe, 0xce, 0x85, 0xa3, 0x5b, 0x9a, 0x36, 0x76, 0x47, + 0xc2, 0x0b, 0x28, 0x7a, 0x34, 0xae, 0xf3, 0x03, 0x22, 0xb9, 0xf8, 0xc9, + 0xe9, 0xe0, 0x83, 0x4b, 0x5d, 0x07, 0xba, 0xc0, 0xd4, 0xce, 0xed, 0x32, + 0xb5, 0x7d, 0x2d, 0xa6, 0xb6, 0x97, 0x30, 0xd5, 0xbe, 0x65, 0xae, 0xda, + 0xd7, 0x63, 0x8b, 0xc1, 0x55, 0x9f, 0xd4, 0x74, 0xd2, 0x5e, 0xa5, 0xca, + 0x29, 0x03, 0x19, 0x51, 0x20, 0xba, 0x8a, 0x3d, 0xb5, 0x7b, 0xfc, 0xa5, + 0xee, 0x66, 0x46, 0x4b, 0xec, 0xbe, 0xa6, 0xba, 0xea, 0x9d, 0x20, 0x2d, + 0x70, 0xac, 0x2b, 0x67, 0xb0, 0x2f, 0xc1, 0x60, 0x08, 0x14, 0x89, 0x6b, + 0xec, 0x77, 0x82, 0x15, 0x16, 0xe5, 0x2d, 0x75, 0x72, 0x31, 0x72, 0xe2, + 0x53, 0x2f, 0x19, 0x4e, 0x9d, 0x06, 0xe2, 0xbf, 0xe3, 0x04, 0x27, 0x88, + 0x29, 0xea, 0x77, 0x38, 0x15, 0xc3, 0x13, 0x1d, 0xf6, 0xdb, 0x54, 0x10, + 0x17, 0xcb, 0xc2, 0x96, 0x8a, 0x41, 0xe4, 0xf2, 0x9c, 0x45, 0xb6, 0xdf, + 0x67, 0x2d, 0x8f, 0x79, 0xd6, 0x5e, 0x51, 0xe1, 0x84, 0x8d, 0x8a, 0x3f, + 0x4a, 0x19, 0x90, 0x47, 0xb3, 0x9c, 0xdc, 0x01, 0x29, 0x1b, 0x47, 0x2b, + 0x83, 0xa0, 0xa5, 0x4b, 0x23, 0x08, 0x4f, 0x8e, 0xaf, 0xcb, 0x8e, 0x25, + 0x14, 0xe3, 0xbc, 0x4d, 0x7c, 0x73, 0x3e, 0xec, 0x39, 0x32, 0xc8, 0xcd, + 0x51, 0x88, 0xd6, 0x32, 0xdb, 0x39, 0x18, 0x0c, 0x90, 0xb5, 0x24, 0xfc, + 0x65, 0x5b, 0xf6, 0x90, 0x62, 0x9a, 0xe1, 0x5a, 0x9d, 0x89, 0x5d, 0xc9, + 0x7c, 0x1a, 0x37, 0x5f, 0xa9, 0x64, 0xea, 0xdf, 0xd9, 0xb5, 0x25, 0xac, + 0x9e, 0x4d, 0x75, 0xa4, 0x78, 0x4d, 0x1d, 0xb6, 0x97, 0x8d, 0x00, 0x32, + 0x4c, 0xeb, 0x66, 0xd5, 0xd8, 0xfa, 0x89, 0x6c, 0xb5, 0x1e, 0x6b, 0x14, + 0xb4, 0xed, 0x2b, 0x27, 0x6d, 0x8f, 0x25, 0x22, 0xeb, 0xb4, 0x1f, 0xed, + 0x3e, 0xeb, 0xca, 0xe2, 0xb2, 0x2c, 0x9f, 0x5f, 0x34, 0x25, 0x4b, 0x22, + 0x14, 0xe5, 0x49, 0x08, 0xbb, 0x2c, 0x29, 0x6e, 0x91, 0x72, 0x51, 0xa6, + 0xa6, 0x46, 0xc5, 0x51, 0xf8, 0x37, 0x55, 0x12, 0x59, 0x4d, 0xd6, 0x7c, + 0x16, 0x5f, 0x09, 0xb3, 0x3a, 0xdf, 0x34, 0x6a, 0x93, 0x2b, 0x0c, 0xfa, + 0xf9, 0xd1, 0x52, 0x29, 0x7d, 0x11, 0x36, 0xc3, 0x72, 0xf1, 0xa0, 0x8b, + 0x2a, 0x01, 0x29, 0xa1, 0x25, 0xd5, 0xd9, 0xa7, 0x15, 0xdd, 0x35, 0x7b, + 0x64, 0xd9, 0xe1, 0xe3, 0xc7, 0x99, 0xd8, 0xd5, 0x8e, 0x89, 0x5d, 0x75, + 0x5d, 0x77, 0xd5, 0xc1, 0x39, 0x13, 0xf7, 0x8e, 0x04, 0xd3, 0x64, 0xea, + 0x50, 0x28, 0x37, 0xa9, 0x3e, 0x13, 0xba, 0x12, 0xfd, 0x52, 0x02, 0xa9, + 0xa7, 0x92, 0x2a, 0x6d, 0xaa, 0x58, 0x8c, 0x5d, 0x5b, 0x1e, 0xe9, 0x0f, + 0x71, 0x52, 0x43, 0x25, 0x65, 0x4f, 0xdf, 0x6e, 0xb3, 0x7d, 0x29, 0x2a, + 0x0e, 0x85, 0xb6, 0x32, 0x1f, 0x4b, 0x6a, 0xda, 0x56, 0x51, 0x82, 0x79, + 0xec, 0x3d, 0xd5, 0x26, 0x17, 0x99, 0x2e, 0xf8, 0xf0, 0x15, 0x22, 0x14, + 0x1d, 0xd9, 0x74, 0x31, 0x99, 0x60, 0x19, 0xba, 0xe9, 0x3c, 0x65, 0x5e, + 0xf1, 0x3f, 0xfb, 0x49, 0x4e, 0xb0, 0x98, 0x0d, 0x08, 0x60, 0x20, 0x92, + 0x53, 0x9a, 0x59, 0xb4, 0x00, 0x4a, 0x67, 0x44, 0xd0, 0x59, 0xe8, 0xc4, + 0x85, 0xca, 0x87, 0x5f, 0x24, 0xfc, 0x51, 0xfc, 0x30, 0xef, 0x7d, 0xd9, + 0x0e, 0x58, 0xa6, 0x2a, 0xdb, 0x54, 0x95, 0x2e, 0xff, 0xa5, 0x52, 0xf2, + 0xdd, 0x81, 0xf0, 0xe5, 0x71, 0x6b, 0xfe, 0x99, 0x95, 0xca, 0x5e, 0xd6, + 0x44, 0xa4, 0xee, 0x61, 0xd1, 0xb7, 0xcb, 0x30, 0xf1, 0xf8, 0xf1, 0x63, + 0xcb, 0x96, 0x73, 0x8b, 0x96, 0x6a, 0x49, 0x51, 0xe4, 0x34, 0xca, 0x88, + 0x84, 0xb9, 0xed, 0x18, 0x6e, 0x0b, 0xaa, 0x23, 0x05, 0x80, 0xe3, 0xc5, + 0x92, 0xe7, 0xa5, 0x43, 0x8c, 0xae, 0xa6, 0x96, 0x18, 0xa3, 0x90, 0xa3, + 0x96, 0x6e, 0x84, 0x22, 0xd6, 0x8b, 0x35, 0x6a, 0xd8, 0x6e, 0xb7, 0x8b, + 0xa3, 0x93, 0x91, 0x1c, 0xd7, 0x2d, 0x3d, 0x9d, 0x55, 0xb0, 0x9c, 0x85, + 0x73, 0xc1, 0x66, 0xd4, 0xe3, 0xb0, 0x53, 0x6a, 0xab, 0xec, 0x59, 0x4d, + 0x39, 0x8b, 0x5b, 0xd1, 0x0b, 0x97, 0x77, 0xc4, 0xbc, 0xf5, 0x55, 0x20, + 0x4e, 0x8b, 0x22, 0x26, 0x85, 0x1b, 0x17, 0xa2, 0x9c, 0x8d, 0xf4, 0x5b, + 0xfc, 0x47, 0x42, 0x5c, 0x29, 0x30, 0x69, 0x81, 0x2f, 0x96, 0x30, 0xb7, + 0xd3, 0xda, 0x1b, 0x8e, 0x87, 0xb9, 0x6e, 0x19, 0xb1, 0xda, 0x2b, 0x94, + 0x4b, 0x1b, 0x84, 0xa1, 0x3e, 0x5e, 0x98, 0x51, 0x2b, 0xd5, 0xc8, 0x62, + 0x37, 0x5c, 0x2a, 0x2f, 0x6b, 0xfe, 0xbe, 0xbc, 0xa6, 0xdb, 0xfc, 0x57, + 0x97, 0xea, 0x97, 0x4f, 0x26, 0xde, 0x57, 0x31, 0x58, 0x2f, 0x26, 0xf5, + 0x7a, 0x7a, 0xe4, 0x90, 0xa5, 0x1a, 0xc9, 0x14, 0xb2, 0xe2, 0x9a, 0xa4, + 0x87, 0xde, 0x6d, 0x26, 0x35, 0x74, 0x49, 0xe6, 0xa5, 0xc3, 0x72, 0x53, + 0x83, 0x1b, 0xe3, 0xc9, 0x08, 0xec, 0x5a, 0xc4, 0xd3, 0xc1, 0xbf, 0x95, + 0x1b, 0xfc, 0xb7, 0xcb, 0xe4, 0x4a, 0x70, 0x3f, 0x2e, 0xf3, 0x80, 0x0a, + 0xfa, 0x7c, 0x7f, 0xc8, 0x7f, 0xcb, 0x14, 0x54, 0xf0, 0x5f, 0xa9, 0xf8, + 0xb7, 0xd7, 0x14, 0xff, 0xfd, 0x01, 0xbb, 0x56, 0xaa, 0xcb, 0x7f, 0x80, + 0x6d, 0xed, 0xcb, 0x14, 0x33, 0x7e, 0x14, 0x9d, 0x85, 0x54, 0x7b, 0xef, + 0xc7, 0x73, 0x81, 0x41, 0xde, 0x2e, 0xcd, 0x29, 0x6b, 0x15, 0xde, 0xfa, + 0x89, 0x32, 0xd0, 0xef, 0x71, 0x57, 0x8a, 0x6f, 0x0d, 0x25, 0xc7, 0xa7, + 0x94, 0x70, 0x3c, 0x74, 0x83, 0x4f, 0x6e, 0xac, 0x31, 0x95, 0x1f, 0x3f, + 0x2e, 0xe8, 0xa1, 0x49, 0xd9, 0x4e, 0x43, 0x89, 0x2d, 0x2b, 0x66, 0x3c, + 0xe4, 0xab, 0x0f, 0x45, 0xa7, 0x4e, 0x8a, 0x3b, 0x6f, 0x4c, 0x21, 0x12, + 0x3e, 0x6e, 0xd8, 0x28, 0x3f, 0x29, 0x48, 0xae, 0xc6, 0xf2, 0x73, 0xd4, + 0x4a, 0xd3, 0xed, 0xca, 0xf9, 0x62, 0x22, 0xb4, 0x37, 0x62, 0xd4, 0xa5, + 0xfb, 0xe3, 0xdc, 0x61, 0xdc, 0x6d, 0x6d, 0x69, 0x8a, 0xa3, 0xc0, 0x2a, + 0xf7, 0x7f, 0x49, 0x30, 0x7f, 0x41, 0xe1, 0x32, 0x83, 0xbd, 0x3a, 0x90, + 0xd8, 0xdc, 0x89, 0xc4, 0xac, 0xcc, 0x0b, 0x68, 0x99, 0x1c, 0x7b, 0x82, + 0xd1, 0xdc, 0x33, 0xa9, 0x45, 0xf3, 0xbe, 0xca, 0xcf, 0xb8, 0xb4, 0xee, + 0xb7, 0xd9, 0xd2, 0x17, 0xdc, 0xc8, 0x27, 0xeb, 0x52, 0xa5, 0xaf, 0xe9, + 0xde, 0x98, 0x03, 0x0b, 0x74, 0xe4, 0x7d, 0x72, 0xbc, 0x11, 0x6e, 0xc7, + 0xc0, 0x82, 0x1d, 0x24, 0x7d, 0x8c, 0xa5, 0xa8, 0x00, 0xac, 0x54, 0xe4, + 0x3d, 0x16, 0xfd, 0x8a, 0x16, 0x0b, 0x49, 0xbe, 0xa2, 0x0a, 0xa6, 0x85, + 0xa7, 0xed, 0x03, 0x05, 0x0f, 0x22, 0xed, 0x7c, 0xee, 0xfc, 0xe0, 0x95, + 0x37, 0x8c, 0xc2, 0x38, 0x1c, 0x27, 0x2f, 0x0e, 0xbf, 0xde, 0x9a, 0xdb, + 0x64, 0xb7, 0x40, 0xb7, 0x8c, 0x0d, 0x3e, 0xdd, 0xa8, 0xe9, 0x64, 0x72, + 0x87, 0xbe, 0x1b, 0xc7, 0x0c, 0x60, 0x8e, 0x3f, 0x6a, 0xc0, 0x0c, 0x70, + 0xfc, 0x69, 0xe2, 0xd0, 0x45, 0x4f, 0xe8, 0xc4, 0xfd, 0x0a, 0xba, 0x29, + 0x6d, 0x28, 0xec, 0x75, 0x5b, 0x8f, 0xf6, 0xf6, 0x76, 0x3b, 0xf6, 0xef, + 0x8a, 0x54, 0x94, 0x7e, 0xa5, 0xd3, 0x6a, 0x55, 0x94, 0x8e, 0xa8, 0x87, + 0xb3, 0x99, 0x1f, 0xc4, 0xf2, 0xa6, 0x21, 0x5c, 0x34, 0x74, 0x7a, 0x7a, + 0xda, 0x3c, 0xed, 0x36, 0xc3, 0x68, 0xb2, 0x85, 0xdc, 0xd6, 0x16, 0x08, + 0x68, 0xc2, 0x05, 0xe2, 0x72, 0xf5, 0x4c, 0x2d, 0xb7, 0xf5, 0x2b, 0xf7, + 0xc5, 0x98, 0xfe, 0xab, 0xe8, 0xf5, 0x37, 0x45, 0x11, 0xb4, 0x69, 0x7d, + 0xae, 0x5f, 0x61, 0xa9, 0x3a, 0x43, 0x30, 0x8a, 0x8d, 0x9b, 0x47, 0xed, + 0x9d, 0xed, 0x47, 0xdb, 0xdd, 0x36, 0x12, 0xce, 0x73, 0x09, 0x11, 0x9e, + 0x77, 0xac, 0xe7, 0xad, 0xd5, 0xf4, 0x59, 0x94, 0x74, 0x08, 0x1e, 0x32, + 0x72, 0x27, 0x58, 0xf6, 0x23, 0x32, 0x5a, 0x82, 0x65, 0x0b, 0xa9, 0x15, + 0xc3, 0x71, 0xab, 0xe5, 0x0e, 0x87, 0xed, 0x22, 0xc7, 0xf9, 0x25, 0x44, + 0x62, 0xb1, 0x55, 0x87, 0xa5, 0x48, 0x73, 0xa8, 0xdb, 0xe0, 0x0a, 0xac, + 0x7e, 0x85, 0x4d, 0xd4, 0x9d, 0x55, 0x71, 0xa2, 0x2b, 0x52, 0x5c, 0x72, + 0xd5, 0xcd, 0x52, 0x5a, 0x8e, 0xba, 0x53, 0x56, 0x30, 0xe0, 0x2b, 0xcf, + 0xd6, 0x39, 0x73, 0xb1, 0x53, 0x91, 0x67, 0x60, 0x66, 0x00, 0xa3, 0x45, + 0x78, 0x41, 0x55, 0x03, 0x41, 0x3c, 0x46, 0x50, 0x4f, 0xd5, 0x33, 0x83, + 0xe1, 0x34, 0x04, 0xd7, 0xf2, 0x66, 0x88, 0x4a, 0xba, 0x98, 0x07, 0x40, + 0x5c, 0x40, 0xd6, 0x6e, 0xfd, 0xf8, 0xeb, 0x2d, 0x82, 0x5b, 0x8b, 0xa5, + 0x8c, 0x56, 0x97, 0x72, 0xd5, 0x69, 0x7d, 0x31, 0x57, 0x9d, 0xca, 0xc1, + 0x4a, 0x96, 0xbe, 0xde, 0x9a, 0x94, 0xf5, 0x27, 0xd2, 0x77, 0x93, 0x6e, + 0xba, 0xef, 0x3a, 0xdd, 0x59, 0x2f, 0xd0, 0x81, 0xf2, 0x32, 0x90, 0xf4, + 0xa0, 0xc6, 0x7a, 0x26, 0x27, 0x70, 0x65, 0x31, 0x79, 0x58, 0xca, 0x14, + 0xb2, 0xad, 0x2e, 0x0d, 0x55, 0xd9, 0xa3, 0x65, 0xd9, 0x34, 0x32, 0xc1, + 0x2a, 0x69, 0xd9, 0xd2, 0x35, 0xcd, 0x77, 0x35, 0xed, 0x65, 0xa6, 0x28, + 0x7f, 0x50, 0x2d, 0xe5, 0x45, 0x8d, 0x37, 0x14, 0x55, 0xa3, 0x71, 0xac, + 0x85, 0x87, 0xce, 0x7d, 0xa1, 0xc6, 0x74, 0xb7, 0x1c, 0x8b, 0x6b, 0x8d, + 0xb2, 0xbc, 0xf1, 0x92, 0x8a, 0xb7, 0x2c, 0x67, 0x25, 0x26, 0x00, 0x05, + 0xba, 0x15, 0xd0, 0x79, 0x13, 0x31, 0x4a, 0xcd, 0x84, 0x1c, 0xe9, 0x50, + 0xde, 0x73, 0x5c, 0xcc, 0xae, 0x1b, 0xf2, 0x19, 0xdc, 0x46, 0x0b, 0x63, + 0x4b, 0xb2, 0xb7, 0x00, 0x54, 0x0e, 0x4e, 0xbd, 0xb1, 0xf7, 0xf5, 0x96, + 0x77, 0xf0, 0x20, 0x18, 0xc4, 0xf3, 0x7d, 0xf9, 0xc9, 0x44, 0x74, 0x81, + 0xec, 0x16, 0x53, 0xe5, 0x80, 0xaa, 0x8c, 0xca, 0x12, 0xc8, 0x81, 0x64, + 0xe7, 0x20, 0x65, 0x45, 0x25, 0xcb, 0xaf, 0x2b, 0x6b, 0x00, 0xad, 0x49, + 0x4b, 0x5e, 0x93, 0xeb, 0x18, 0x9d, 0xca, 0xf5, 0x8f, 0x89, 0xf9, 0xe3, + 0x70, 0x3c, 0xfe, 0xd2, 0x0a, 0x80, 0x93, 0x1b, 0xd6, 0x01, 0xea, 0xc9, + 0xf3, 0x1f, 0x69, 0x0b, 0xf2, 0x4d, 0xb1, 0x2e, 0x16, 0x49, 0x9c, 0xf0, + 0x60, 0x7d, 0xc4, 0xf3, 0xcb, 0xda, 0x54, 0x5d, 0x59, 0x16, 0x06, 0x4f, + 0xe9, 0x9e, 0x2a, 0xdc, 0x82, 0x18, 0x1f, 0x47, 0x42, 0x95, 0xab, 0xd6, + 0x48, 0x7c, 0xcb, 0x64, 0x45, 0x07, 0xe6, 0x30, 0x23, 0x14, 0xa7, 0x46, + 0x4a, 0xb2, 0xd6, 0x69, 0xf9, 0xb4, 0xca, 0x4c, 0x64, 0x45, 0xdd, 0xb5, + 0x66, 0x66, 0xd3, 0xd0, 0xc1, 0x57, 0x0c, 0xff, 0xea, 0xd0, 0x3f, 0x9c, + 0x15, 0x3e, 0x84, 0x7e, 0x55, 0x17, 0xe5, 0x03, 0xb7, 0x7c, 0x78, 0x02, + 0x01, 0xf2, 0x69, 0xff, 0xb4, 0x37, 0xff, 0x79, 0xb9, 0x60, 0x9d, 0x5e, + 0x5a, 0xb4, 0x53, 0x25, 0xfe, 0xd9, 0xca, 0x01, 0x48, 0xba, 0xe0, 0xdc, + 0x44, 0x45, 0xcf, 0xbc, 0x82, 0xc6, 0x18, 0xca, 0xc6, 0x08, 0x83, 0x23, + 0x76, 0x77, 0xd9, 0x9f, 0xaf, 0x8a, 0x4f, 0x40, 0x5d, 0xa3, 0x6c, 0xbe, + 0x2f, 0x71, 0x06, 0x5f, 0x74, 0x09, 0x08, 0x24, 0x2d, 0x71, 0x29, 0x26, + 0x96, 0xd5, 0xc8, 0x70, 0x00, 0x24, 0xed, 0x54, 0x39, 0x4a, 0x1c, 0x6a, + 0xeb, 0x64, 0x3a, 0x31, 0xf0, 0xb4, 0xc0, 0xdf, 0xeb, 0xc5, 0xac, 0xda, + 0xae, 0xad, 0xa8, 0xb5, 0x51, 0xcd, 0x03, 0xc6, 0xaf, 0x7b, 0x4a, 0xbb, + 0x27, 0x53, 0x0d, 0x2f, 0x3f, 0x17, 0x67, 0xed, 0x12, 0x15, 0x5f, 0x47, + 0x69, 0x56, 0x56, 0xb0, 0xb3, 0x5e, 0x05, 0xbb, 0xcb, 0x2b, 0xd8, 0xb9, + 0x49, 0x05, 0x3b, 0x65, 0x15, 0xec, 0xdc, 0x45, 0x05, 0xbb, 0x5f, 0x5c, + 0xc1, 0xee, 0x4d, 0x2a, 0xd8, 0x2d, 0xab, 0x60, 0xf7, 0x0b, 0x2b, 0xc8, + 0x79, 0x6b, 0x9a, 0x8a, 0x55, 0x7d, 0xfd, 0xa7, 0xeb, 0xf4, 0x68, 0xbd, + 0x36, 0x91, 0xf6, 0xec, 0xb4, 0xd0, 0x95, 0xa6, 0x00, 0xb5, 0xe5, 0xab, + 0x30, 0xd6, 0xf2, 0x59, 0x56, 0xb5, 0xa0, 0x59, 0x8c, 0xad, 0x1c, 0x5c, + 0xd9, 0xf2, 0x5b, 0x57, 0x6b, 0xc6, 0x55, 0xa4, 0x79, 0x69, 0x81, 0x42, + 0x0e, 0xe0, 0xa5, 0xd3, 0x38, 0x19, 0xd1, 0x10, 0xc5, 0x89, 0x57, 0x95, + 0x94, 0xcb, 0x92, 0x72, 0x51, 0x5c, 0xae, 0xa9, 0x55, 0x50, 0x09, 0x46, + 0x03, 0x1d, 0xba, 0xb2, 0xce, 0xb2, 0xf8, 0x27, 0xd7, 0x5f, 0xa0, 0x3c, + 0x96, 0x89, 0xf5, 0x9d, 0xb4, 0xbc, 0x1a, 0x54, 0xa1, 0x0d, 0x7e, 0x4c, + 0xd6, 0xf0, 0xed, 0x9e, 0x71, 0x76, 0x8a, 0xbb, 0xb2, 0x39, 0x81, 0x4c, + 0x22, 0x41, 0x83, 0x23, 0x7f, 0x7d, 0xa1, 0x50, 0x18, 0xc7, 0x9d, 0x89, + 0x85, 0xb1, 0x6f, 0x50, 0x30, 0x03, 0x70, 0x57, 0x39, 0xa0, 0xcf, 0x2f, + 0x14, 0x0b, 0xa1, 0xb8, 0x33, 0xa9, 0x10, 0xf2, 0x0d, 0x0a, 0x85, 0x76, + 0x14, 0x41, 0x8f, 0xbe, 0xbe, 0x54, 0x2c, 0x84, 0xe3, 0xee, 0xe4, 0x42, + 0xd8, 0x37, 0x29, 0x18, 0xb9, 0xe2, 0x99, 0x5a, 0x46, 0xbd, 0xb6, 0xb5, + 0xa7, 0x6e, 0x86, 0xe9, 0xca, 0xef, 0xfd, 0x6b, 0xf9, 0xe8, 0x8e, 0xbe, + 0xa0, 0x0c, 0x02, 0x1f, 0x60, 0xaa, 0x0f, 0x3f, 0x67, 0x24, 0x62, 0x72, + 0xba, 0xc8, 0x0d, 0xfd, 0x42, 0xf1, 0x4b, 0x86, 0xef, 0x4c, 0xfe, 0x12, + 0xfd, 0x06, 0x1b, 0x80, 0x17, 0x8d, 0x6f, 0x57, 0xfe, 0x34, 0xcf, 0x99, + 0x89, 0xe8, 0x16, 0x84, 0x0d, 0xe6, 0xee, 0x70, 0xc0, 0x00, 0xf6, 0x2f, + 0x1f, 0x32, 0xf2, 0x63, 0xba, 0x7d, 0xa9, 0xa0, 0xbd, 0xba, 0xdb, 0xa6, + 0x2d, 0xc3, 0x2b, 0xeb, 0xc1, 0xd2, 0xd2, 0x52, 0x95, 0x51, 0x20, 0xba, + 0xcc, 0x1a, 0xf5, 0x97, 0x75, 0xd6, 0xb1, 0x2c, 0xb2, 0x92, 0x34, 0x05, + 0x23, 0xc6, 0xac, 0x29, 0x43, 0x12, 0x4e, 0x70, 0x0b, 0xfa, 0x63, 0x95, + 0x51, 0x4d, 0xa6, 0xb8, 0x0e, 0x5d, 0x05, 0x0d, 0xd4, 0xae, 0x64, 0x31, + 0x75, 0xf0, 0x32, 0xd8, 0x07, 0x13, 0xb9, 0xf5, 0x9d, 0xf5, 0x96, 0x1c, + 0x5e, 0xdb, 0x5b, 0xc3, 0xcb, 0xa3, 0x3f, 0xad, 0x2a, 0x24, 0xd4, 0x0c, + 0xee, 0x97, 0x03, 0x3f, 0xb7, 0x70, 0xd3, 0xa3, 0x2c, 0xde, 0x38, 0xb3, + 0x2e, 0x33, 0xdf, 0x63, 0xf9, 0xea, 0x42, 0x57, 0x36, 0xdd, 0x2d, 0xf9, + 0x95, 0x65, 0x69, 0x3f, 0xfc, 0xc1, 0x17, 0x4e, 0x0b, 0xed, 0x05, 0x6e, + 0xbc, 0x13, 0x60, 0xe9, 0x74, 0x56, 0x12, 0x5f, 0x93, 0x05, 0xc2, 0xa7, + 0xaf, 0xa8, 0xac, 0x14, 0x18, 0x52, 0x7b, 0x15, 0xd7, 0x9d, 0xae, 0x5e, + 0x73, 0xb6, 0xbd, 0xca, 0x0b, 0xdf, 0x46, 0x7d, 0xe6, 0x07, 0x72, 0xef, + 0xe6, 0x25, 0xba, 0xed, 0x02, 0x4b, 0xae, 0x66, 0x1f, 0xa0, 0x14, 0x93, + 0x04, 0xe6, 0x9a, 0xf9, 0xaa, 0x44, 0x5a, 0xb3, 0x4c, 0x6c, 0x08, 0x89, + 0x4a, 0xfe, 0xba, 0x66, 0x93, 0xaf, 0xc1, 0x30, 0x82, 0x09, 0x75, 0x57, + 0x02, 0xbb, 0x5f, 0x60, 0x2d, 0x2a, 0x07, 0x1b, 0x37, 0x0e, 0xd0, 0x87, + 0x86, 0xee, 0x31, 0x6b, 0xa1, 0xa2, 0x7e, 0xac, 0x4b, 0xde, 0x41, 0xdf, + 0xbf, 0xdd, 0xfe, 0xba, 0x46, 0xe3, 0xb1, 0x4e, 0x7c, 0xe7, 0xc1, 0xf4, + 0x45, 0x77, 0xdc, 0x78, 0x28, 0xbf, 0xb6, 0x11, 0xe3, 0x49, 0xb9, 0xac, + 0xd5, 0x1d, 0x34, 0xfa, 0x9c, 0xab, 0x4b, 0xbc, 0x5c, 0x39, 0xf9, 0x34, + 0x6d, 0x6e, 0x0a, 0xde, 0x62, 0x73, 0xb3, 0x50, 0xd6, 0x96, 0x8a, 0xdc, + 0xc1, 0xb9, 0x0b, 0xc3, 0xbe, 0x54, 0x51, 0x4a, 0xcd, 0x21, 0xed, 0x07, + 0xec, 0x5b, 0xea, 0xf3, 0xf3, 0x30, 0x4e, 0x68, 0x15, 0x5e, 0x2a, 0xd0, + 0x5a, 0x0d, 0x42, 0xe8, 0x64, 0x63, 0x4c, 0x55, 0xe1, 0x94, 0xd2, 0xf2, + 0x60, 0x98, 0xb2, 0x9d, 0x5c, 0xb5, 0x7d, 0xcd, 0x5b, 0xf0, 0xd8, 0x05, + 0xbb, 0xad, 0x7a, 0x3b, 0x74, 0x57, 0xc4, 0x5a, 0x95, 0x7f, 0xf5, 0xab, + 0x77, 0xef, 0x48, 0x00, 0x37, 0xaa, 0xfc, 0xec, 0x4f, 0x49, 0x72, 0x4c, + 0x12, 0xf8, 0xaf, 0xab, 0xfd, 0x7a, 0x2d, 0x4f, 0x95, 0xff, 0x2e, 0x8c, + 0xae, 0x53, 0x79, 0xe9, 0xdd, 0xe6, 0x3c, 0xd2, 0xdd, 0x9d, 0x9d, 0xee, + 0x8e, 0x25, 0x12, 0x1c, 0x82, 0xf9, 0xef, 0x13, 0xc9, 0xee, 0xda, 0x22, + 0xf9, 0x3e, 0xbe, 0xd2, 0x9a, 0xae, 0xd0, 0x07, 0x0a, 0xe1, 0xf8, 0x1f, + 0xae, 0xfc, 0x77, 0x28, 0x7b, 0x8d, 0xca, 0xcf, 0x01, 0x7e, 0x8a, 0x9a, + 0x58, 0x02, 0xa0, 0xa4, 0xff, 0x88, 0x00, 0xd6, 0x59, 0x37, 0xbd, 0x45, + 0x27, 0xef, 0x29, 0x46, 0x8c, 0xdb, 0xec, 0x3a, 0x12, 0xeb, 0x10, 0x58, + 0xff, 0xfb, 0x3a, 0x8f, 0x5d, 0xef, 0xb7, 0xcf, 0x9f, 0xbc, 0x59, 0xdf, + 0xb1, 0x95, 0x3f, 0x11, 0xf3, 0x14, 0x6e, 0xde, 0xb5, 0x55, 0xde, 0x51, + 0xf0, 0xa5, 0x8d, 0xd4, 0xde, 0xb5, 0x5b, 0x08, 0xe7, 0xf4, 0xfe, 0x23, + 0xed, 0xb3, 0x01, 0xf5, 0xee, 0x5a, 0x72, 0x7b, 0xf3, 0xdd, 0xbb, 0xb7, + 0x87, 0xbf, 0xbe, 0x6e, 0x43, 0xe3, 0x0d, 0x54, 0x38, 0x81, 0xb8, 0xc1, + 0xa6, 0xce, 0xb1, 0xfc, 0xec, 0xf1, 0xb7, 0x87, 0x37, 0xe0, 0x19, 0x27, + 0x75, 0x36, 0x39, 0xf5, 0xca, 0x31, 0xfd, 0xfc, 0xf1, 0xab, 0x57, 0x8f, + 0x6f, 0xc0, 0xf5, 0xc4, 0x9d, 0xcd, 0xdc, 0xff, 0x1c, 0xdb, 0x47, 0x2f, + 0x7e, 0x77, 0x13, 0x59, 0xc3, 0x27, 0xbe, 0x6d, 0x59, 0xdf, 0x75, 0xd7, + 0x58, 0x3e, 0x7a, 0xea, 0x38, 0x71, 0x19, 0x24, 0xae, 0x06, 0x53, 0xb3, + 0x5b, 0x7d, 0xd5, 0x50, 0x1a, 0x84, 0x83, 0x48, 0xee, 0x34, 0xbe, 0xc2, + 0x32, 0x46, 0xc6, 0x12, 0xa9, 0x59, 0x8a, 0xd9, 0x3a, 0x9b, 0x01, 0xa2, + 0xa2, 0xd7, 0x08, 0xd5, 0xb1, 0x82, 0x8a, 0x8e, 0x4a, 0xd8, 0x22, 0x4c, + 0xeb, 0x51, 0x7a, 0x86, 0x89, 0xc9, 0x6a, 0x4a, 0x34, 0x75, 0xb9, 0x0d, + 0x4a, 0x4f, 0x10, 0x0f, 0xb5, 0x9a, 0x12, 0x05, 0xf9, 0xde, 0x0a, 0xa5, + 0x24, 0xb8, 0x82, 0x50, 0x72, 0x2b, 0xb2, 0x03, 0x1d, 0x6c, 0x26, 0x5f, + 0x49, 0x0a, 0x1a, 0x50, 0xa4, 0x26, 0xe9, 0x5c, 0x53, 0xb3, 0x6f, 0x4b, + 0x25, 0x7d, 0xf7, 0x93, 0x78, 0x4d, 0xab, 0x71, 0xd7, 0x18, 0x0b, 0x8d, + 0x63, 0xcb, 0xc5, 0x03, 0x14, 0xbf, 0x0d, 0xc7, 0x4e, 0xaf, 0x2a, 0xeb, + 0x73, 0x6c, 0xb4, 0xb2, 0x7c, 0x47, 0xc3, 0x61, 0x2a, 0xad, 0x34, 0x0a, + 0x28, 0xb3, 0x8c, 0xd8, 0x88, 0x51, 0x2d, 0xbd, 0xd4, 0x2e, 0xf3, 0x53, + 0xc3, 0x64, 0xbf, 0x3c, 0x81, 0xde, 0x52, 0x66, 0xbd, 0x8d, 0xca, 0x7e, + 0xb3, 0xdb, 0x15, 0x1b, 0x0b, 0xfc, 0x36, 0x9f, 0xfc, 0xee, 0x02, 0x51, + 0xc5, 0xe6, 0x02, 0x7f, 0x1f, 0x29, 0x56, 0xd2, 0x00, 0xa2, 0x1b, 0x2e, + 0xd2, 0xca, 0x0b, 0xd1, 0xb9, 0x76, 0xf2, 0x67, 0xda, 0x50, 0xe9, 0xf1, + 0xcc, 0x65, 0x0b, 0xf8, 0x5f, 0xf3, 0x3a, 0x8d, 0x9b, 0x7b, 0xe1, 0xe8, + 0xc4, 0xc3, 0x19, 0x85, 0x41, 0xf9, 0x5b, 0x4f, 0xb7, 0x2a, 0x16, 0x21, + 0x7e, 0xfb, 0x0e, 0x84, 0x88, 0x46, 0xa5, 0x57, 0xd2, 0x1e, 0x0f, 0x7c, + 0x17, 0xcf, 0x07, 0xdf, 0x45, 0xe1, 0x1f, 0xc9, 0xf4, 0x4f, 0x43, 0x5a, + 0x59, 0x70, 0x0f, 0x70, 0x5e, 0xf5, 0x9f, 0x7f, 0xc3, 0xe9, 0x85, 0xf6, + 0x9e, 0xac, 0x8d, 0x73, 0x9d, 0xf0, 0xbd, 0xd2, 0xc6, 0x0b, 0xe7, 0x22, + 0x58, 0xd2, 0x78, 0xba, 0xc1, 0x94, 0x8e, 0x7d, 0x79, 0x8b, 0xa5, 0xad, + 0xe4, 0xa5, 0xa1, 0x5e, 0x85, 0x36, 0x92, 0xe2, 0x58, 0x15, 0x28, 0x8a, + 0x6b, 0x29, 0xbc, 0xb9, 0x3d, 0xb6, 0x79, 0x63, 0xa7, 0x8a, 0x10, 0x30, + 0xbc, 0x6d, 0x09, 0x71, 0x66, 0x4d, 0x9a, 0x39, 0x3e, 0x9e, 0x80, 0xc5, + 0x26, 0x9f, 0xa9, 0x7f, 0x33, 0xae, 0x3e, 0x7c, 0x75, 0xf4, 0xe2, 0xf0, + 0x61, 0xed, 0x5e, 0xbf, 0xdf, 0x68, 0x3b, 0x7f, 0xfe, 0xb3, 0x63, 0x60, + 0x71, 0x2c, 0xe5, 0xd7, 0x58, 0x04, 0x83, 0x7e, 0x1a, 0xe0, 0x77, 0x91, + 0x37, 0x42, 0xe9, 0xad, 0x87, 0x35, 0xe7, 0x20, 0xbd, 0xce, 0xdb, 0xfc, + 0x51, 0x55, 0xf0, 0x5e, 0xd1, 0xa6, 0x1f, 0x4e, 0xaa, 0x15, 0xbc, 0x7e, + 0x73, 0x24, 0x12, 0x19, 0x3f, 0x58, 0xdb, 0xcf, 0x02, 0x8e, 0x70, 0x78, + 0x68, 0x46, 0x6c, 0xa0, 0x41, 0x0f, 0xe5, 0xeb, 0x3f, 0x9f, 0x9c, 0xbf, + 0x18, 0x55, 0x0b, 0x61, 0xf3, 0xb5, 0x26, 0xeb, 0x58, 0x53, 0x1f, 0xe9, + 0xeb, 0x3b, 0x0f, 0xb9, 0x87, 0x3c, 0x5c, 0x17, 0x61, 0xba, 0x7c, 0x5f, + 0x86, 0x6a, 0x8a, 0xda, 0xd8, 0x98, 0x32, 0x31, 0xff, 0x4a, 0x94, 0x45, + 0xe1, 0xf2, 0xe1, 0x10, 0xbd, 0xfe, 0x8e, 0x3a, 0x8e, 0xf9, 0xfd, 0xc6, + 0xa8, 0x3a, 0x40, 0x7f, 0x82, 0xab, 0x18, 0x1c, 0xec, 0x10, 0x3a, 0xf0, + 0x04, 0x70, 0xb8, 0xef, 0x34, 0x50, 0x51, 0xb0, 0xf2, 0xb8, 0x3b, 0x03, + 0x3c, 0x0d, 0xe7, 0xe7, 0x74, 0x6f, 0x48, 0x9a, 0x23, 0xf8, 0x7c, 0x5f, + 0x85, 0x54, 0xad, 0x7a, 0x18, 0x4c, 0x7c, 0x2f, 0x9e, 0xd6, 0x9c, 0x4f, + 0x52, 0xf4, 0xf5, 0x1c, 0x24, 0xde, 0x12, 0xcc, 0x48, 0x5e, 0x8c, 0x1d, + 0xd7, 0x46, 0xed, 0x78, 0x31, 0x26, 0x14, 0x71, 0x4c, 0xd7, 0x7c, 0xd0, + 0x64, 0x39, 0xae, 0x13, 0xd2, 0x73, 0x7e, 0x57, 0x04, 0xb1, 0xe8, 0x2e, + 0x7c, 0x7e, 0x3f, 0xaa, 0xc2, 0x0f, 0x24, 0x7c, 0xa4, 0xe5, 0x13, 0xee, + 0x89, 0xf0, 0x75, 0x4d, 0xfa, 0xba, 0x39, 0x45, 0xd0, 0xb3, 0x5a, 0x96, + 0x01, 0x8e, 0x69, 0x05, 0x0e, 0xc7, 0x89, 0x55, 0xf9, 0x4a, 0xdd, 0x64, + 0x53, 0xc4, 0x26, 0x65, 0x99, 0xce, 0x6b, 0xe7, 0xa2, 0x9c, 0xcc, 0x74, + 0x74, 0xae, 0xf3, 0xfd, 0x0b, 0xa7, 0x8a, 0x19, 0xde, 0xfb, 0x9a, 0x0d, + 0x97, 0x46, 0x78, 0x02, 0x38, 0xfd, 0x6d, 0x03, 0xa0, 0xd9, 0x6c, 0x18, + 0xf9, 0x58, 0x04, 0x4b, 0xc3, 0x26, 0x01, 0xf3, 0x56, 0xff, 0x2e, 0x21, + 0x74, 0x18, 0x45, 0x61, 0xd4, 0x06, 0x10, 0xe6, 0xd8, 0xfe, 0x08, 0x07, + 0x61, 0x12, 0x95, 0xc3, 0x62, 0x32, 0x75, 0x69, 0x3a, 0xd0, 0x79, 0x9c, + 0x22, 0x5a, 0x86, 0xa2, 0x03, 0x14, 0x0e, 0x6d, 0xe6, 0xc6, 0x4d, 0xe7, + 0x3b, 0x9f, 0x8e, 0xd6, 0xe1, 0x30, 0x90, 0x6c, 0xd1, 0xb7, 0x87, 0x4f, + 0xdf, 0xbc, 0x7e, 0x7d, 0xf8, 0xf4, 0x9d, 0x7a, 0xcf, 0x29, 0x21, 0x4e, + 0x22, 0xb4, 0xfd, 0x04, 0x0a, 0xd9, 0xb4, 0x11, 0xfa, 0xb8, 0xa0, 0xe5, + 0x15, 0x8d, 0x7d, 0x40, 0xa6, 0x2f, 0x6b, 0x99, 0xd1, 0xb3, 0xd3, 0x6c, + 0x02, 0xd0, 0xd9, 0xc2, 0x0d, 0x1f, 0xd8, 0x82, 0x4c, 0x9b, 0xaa, 0x81, + 0x13, 0x02, 0x04, 0x83, 0x24, 0x30, 0x6e, 0xd4, 0x03, 0x77, 0xd1, 0x28, + 0x3b, 0xc2, 0x19, 0x8c, 0x17, 0x89, 0xe7, 0x22, 0xa9, 0x65, 0x89, 0xa9, + 0x31, 0xc1, 0xa6, 0xa7, 0x0a, 0xde, 0x19, 0xc9, 0xf7, 0x62, 0x10, 0xa3, + 0xe3, 0x92, 0xc4, 0xa5, 0xf8, 0x58, 0x55, 0x65, 0xa2, 0x48, 0x14, 0xd9, + 0x6c, 0x91, 0xb7, 0x38, 0x67, 0x73, 0x8e, 0x02, 0xfc, 0x5d, 0x06, 0xc0, + 0x2d, 0x00, 0x00, 0xfe, 0xe6, 0x14, 0x20, 0x35, 0xd7, 0x4b, 0x48, 0x19, + 0xe2, 0xad, 0x28, 0xdc, 0x2e, 0x46, 0xf6, 0x77, 0x50, 0x43, 0x61, 0x73, + 0x62, 0xb3, 0xa9, 0x0c, 0x19, 0xb2, 0xde, 0xcb, 0x5f, 0x76, 0xe6, 0xcc, + 0x9c, 0xe7, 0x01, 0xc0, 0x8b, 0x31, 0x59, 0x0d, 0x34, 0x04, 0x58, 0x25, + 0xc6, 0xa0, 0x53, 0x31, 0xf8, 0xc2, 0x8b, 0x67, 0x31, 0xc0, 0x21, 0x85, + 0xe5, 0x15, 0x24, 0x98, 0x5b, 0x84, 0xc1, 0x24, 0xd5, 0xb6, 0x13, 0x21, + 0xe6, 0x74, 0x46, 0x78, 0x06, 0x23, 0x8d, 0x72, 0x6e, 0xe2, 0xd8, 0xef, + 0x0e, 0x87, 0x61, 0x14, 0x71, 0xf0, 0x30, 0x21, 0xa3, 0x70, 0x02, 0xb0, + 0xe2, 0x0b, 0x6f, 0x33, 0x6a, 0x8b, 0x6d, 0x8c, 0xc5, 0x3c, 0xc1, 0x6e, + 0x7c, 0x63, 0x44, 0xd6, 0x46, 0x59, 0x63, 0xbc, 0x72, 0xef, 0x04, 0xe7, + 0x95, 0xa7, 0x11, 0xf8, 0xa8, 0xa7, 0xef, 0xcf, 0x85, 0xc4, 0x0f, 0x47, + 0x13, 0x91, 0x69, 0x14, 0x76, 0x4f, 0xa9, 0x89, 0xe9, 0x3b, 0xdb, 0x2d, + 0x47, 0xd4, 0x90, 0xd9, 0xbe, 0xca, 0x71, 0x57, 0x48, 0x7e, 0x4e, 0xdf, + 0x76, 0x06, 0x85, 0x1e, 0x21, 0xfd, 0x09, 0xbe, 0x4c, 0xb2, 0x7a, 0x37, + 0x0c, 0x49, 0x12, 0xdf, 0x76, 0x06, 0x35, 0xcb, 0x31, 0x90, 0x81, 0x65, + 0x22, 0x8e, 0x60, 0x16, 0x24, 0xe4, 0x8e, 0x55, 0xab, 0x6c, 0x92, 0x50, + 0x40, 0xc7, 0xaa, 0xf3, 0xc5, 0x7d, 0x08, 0x7b, 0x59, 0x59, 0xca, 0x93, + 0x05, 0x5b, 0x76, 0x31, 0xbd, 0xbb, 0x87, 0x62, 0x8f, 0xd5, 0x4f, 0x3b, + 0x3b, 0xbb, 0x4f, 0x0b, 0xa0, 0x23, 0x39, 0x53, 0x4d, 0x53, 0x72, 0xc0, + 0x66, 0x9f, 0x84, 0x80, 0xd5, 0xcf, 0x22, 0x94, 0xd9, 0x50, 0x00, 0x14, + 0xfd, 0x74, 0x8e, 0x44, 0x84, 0xd1, 0x22, 0x07, 0x67, 0xd6, 0xde, 0x09, + 0x8e, 0x06, 0x11, 0xfe, 0x99, 0x87, 0x32, 0xcb, 0xd1, 0x1a, 0x1b, 0xfd, + 0x2e, 0x10, 0xce, 0x2e, 0xde, 0x6a, 0xd0, 0xef, 0xd4, 0xca, 0x6c, 0x16, + 0xd4, 0xac, 0x5c, 0x52, 0x9d, 0xd1, 0xa7, 0xe6, 0xce, 0xcb, 0xc3, 0x6f, + 0x1d, 0x4e, 0xc9, 0x40, 0x9a, 0xb5, 0x3e, 0x00, 0xe2, 0xcb, 0x79, 0x43, + 0x4e, 0x7d, 0x06, 0x24, 0x5d, 0x5f, 0x4b, 0x51, 0x3d, 0xff, 0xee, 0xc5, + 0x1b, 0x87, 0x12, 0x8a, 0x60, 0x6f, 0xe6, 0x3c, 0x0a, 0xa7, 0xa0, 0xea, + 0x39, 0x07, 0x69, 0x16, 0x9e, 0x88, 0xaa, 0xbc, 0xca, 0x2a, 0x0f, 0x62, + 0x16, 0x7a, 0x00, 0xf3, 0x0c, 0xdd, 0x9d, 0x5e, 0x62, 0x2e, 0x8a, 0xf5, + 0x34, 0x4b, 0x2b, 0xa4, 0xc5, 0xb4, 0x54, 0x82, 0x1e, 0x10, 0xa9, 0x17, + 0xc7, 0xe5, 0xa1, 0xcd, 0x8a, 0x06, 0xeb, 0xc2, 0x64, 0x46, 0x7d, 0xf9, + 0xc8, 0xfb, 0x9c, 0xa7, 0x6e, 0x66, 0xf6, 0x46, 0x67, 0xf8, 0x3c, 0xe4, + 0x18, 0x1e, 0xac, 0xec, 0x61, 0xd9, 0x3a, 0xa5, 0x93, 0x7b, 0xc0, 0xe3, + 0x45, 0x90, 0xb9, 0xa6, 0x4b, 0x27, 0xe4, 0x94, 0x2b, 0xce, 0xb2, 0x4d, + 0x90, 0xce, 0xa1, 0xa9, 0xb7, 0x99, 0xa3, 0xbd, 0x45, 0x90, 0x24, 0x20, + 0x08, 0x1e, 0xc6, 0x72, 0xc4, 0xcd, 0x9c, 0x55, 0xb3, 0x4b, 0x26, 0x53, + 0x82, 0x66, 0x20, 0xed, 0x9d, 0xe4, 0x14, 0x54, 0x1d, 0x0d, 0x97, 0xfb, + 0xa6, 0x19, 0x70, 0xb9, 0x97, 0x49, 0xb6, 0x84, 0x7e, 0xe4, 0xec, 0x80, + 0x60, 0x6a, 0xef, 0xe9, 0xdb, 0xce, 0xb0, 0x23, 0x0d, 0x88, 0x04, 0x1e, + 0x9d, 0xf4, 0xd9, 0x06, 0x54, 0xaf, 0xd6, 0x26, 0x2f, 0x84, 0x7a, 0x07, + 0xda, 0xeb, 0x13, 0xd9, 0x3b, 0x7a, 0xb6, 0xc1, 0xcc, 0x9c, 0x96, 0xfa, + 0x78, 0x7a, 0x98, 0xc4, 0xb2, 0xb0, 0xce, 0x11, 0x81, 0x38, 0x0c, 0xe3, + 0x54, 0x7f, 0x5f, 0xd9, 0xff, 0x7d, 0x05, 0x15, 0xc5, 0x89, 0x38, 0x1a, + 0x38, 0x32, 0x0e, 0x8e, 0x3d, 0x15, 0x23, 0x9f, 0xe1, 0x88, 0xca, 0xe9, + 0x84, 0x1c, 0x20, 0x1b, 0x4b, 0x9d, 0x27, 0x13, 0xf2, 0x10, 0xd9, 0xb1, + 0x8f, 0x92, 0xac, 0x41, 0x7c, 0xd9, 0x98, 0x67, 0x50, 0xcc, 0xe5, 0xdc, + 0xe9, 0xe7, 0x21, 0x1b, 0x1b, 0x7b, 0x26, 0x55, 0x91, 0x40, 0x97, 0x0a, + 0x38, 0xf0, 0x97, 0xfa, 0x82, 0xaf, 0x05, 0xba, 0x2b, 0x12, 0x46, 0xf1, + 0xdd, 0xba, 0x83, 0xe8, 0xa2, 0x83, 0x30, 0xc0, 0xbc, 0x63, 0x85, 0x3b, + 0x18, 0x78, 0x18, 0xd2, 0x52, 0xc0, 0x65, 0x0e, 0xe1, 0xaf, 0x01, 0x40, + 0xc3, 0x64, 0x38, 0x07, 0xfc, 0xe2, 0x74, 0x95, 0x5b, 0xf8, 0x4b, 0xb8, + 0x0f, 0x29, 0x52, 0x8f, 0x90, 0x62, 0x3c, 0xb6, 0xc7, 0xd6, 0xe6, 0x6a, + 0x97, 0xf0, 0x44, 0x60, 0x00, 0x99, 0x08, 0xc8, 0x79, 0x80, 0x5f, 0xa3, + 0xa6, 0xf3, 0x5c, 0x0c, 0xa2, 0x85, 0x77, 0xe2, 0xc0, 0x98, 0xe4, 0xd8, + 0x70, 0x4e, 0x82, 0x70, 0xee, 0x84, 0xb3, 0xf4, 0x19, 0x9a, 0xc8, 0xe5, + 0x22, 0xb1, 0xdc, 0x4d, 0xe4, 0x6f, 0x34, 0xc7, 0x48, 0xdc, 0x85, 0x3b, + 0x93, 0xf3, 0x11, 0x5f, 0xd0, 0x35, 0x50, 0xbe, 0x8f, 0x27, 0x11, 0xdc, + 0x29, 0x4d, 0xe3, 0x24, 0xbe, 0x4f, 0x3d, 0x43, 0xd3, 0x02, 0x2b, 0x5c, + 0xc4, 0x5f, 0xfa, 0xae, 0x1b, 0xad, 0xf0, 0x10, 0x9f, 0xd1, 0xc2, 0xec, + 0xc0, 0xfb, 0xa3, 0xe4, 0x1e, 0x0b, 0x67, 0x81, 0x76, 0x13, 0x85, 0xf6, + 0x12, 0x55, 0x53, 0xe9, 0x56, 0xb8, 0x83, 0x1a, 0x0a, 0x8b, 0x99, 0x25, + 0x3e, 0x22, 0x6a, 0x11, 0x0f, 0xa7, 0x8b, 0xd3, 0x95, 0x8e, 0xe2, 0x63, + 0x5c, 0xde, 0xb2, 0x40, 0x0f, 0x40, 0x8d, 0xb0, 0x86, 0x30, 0x9c, 0x82, + 0x9c, 0x10, 0x31, 0xae, 0x49, 0x98, 0x10, 0x6b, 0xa8, 0x02, 0xf4, 0x96, + 0xa7, 0x83, 0xcd, 0xac, 0x2f, 0x78, 0x2a, 0xa2, 0x93, 0x84, 0xb5, 0xba, + 0xd4, 0x13, 0x34, 0x3a, 0x4a, 0xf7, 0xcf, 0x8c, 0xdd, 0x24, 0x0e, 0x05, + 0xe2, 0x77, 0xfe, 0x78, 0x62, 0x1c, 0xc1, 0xcf, 0xa1, 0x0b, 0xda, 0xd2, + 0x13, 0xc4, 0xa5, 0x60, 0xda, 0x17, 0x2c, 0xfa, 0x80, 0xdc, 0x24, 0x62, + 0x51, 0xe6, 0x03, 0x86, 0xe1, 0x12, 0x27, 0x30, 0x5c, 0xe2, 0x04, 0xba, + 0x8b, 0xd3, 0x52, 0x2f, 0xd0, 0x4b, 0x96, 0xfb, 0x80, 0xcf, 0x81, 0x94, + 0xfc, 0xb7, 0x19, 0xf9, 0x6f, 0xd3, 0x70, 0x02, 0xde, 0x47, 0xcb, 0x1d, + 0xbf, 0x7c, 0x01, 0xdf, 0xe5, 0x02, 0xb7, 0xe3, 0xf0, 0x91, 0x4e, 0xbd, + 0x73, 0x5d, 0x7f, 0x93, 0xfe, 0x9e, 0x08, 0xd6, 0x75, 0xf7, 0x26, 0xb2, + 0xc9, 0x51, 0xeb, 0xc0, 0x75, 0x67, 0x6b, 0x38, 0x7d, 0xa7, 0x2e, 0x14, + 0xee, 0x34, 0x5c, 0xed, 0xf6, 0xc1, 0xe1, 0x63, 0x61, 0x7e, 0x89, 0x3b, + 0xb7, 0x86, 0x63, 0x98, 0xf7, 0xf8, 0x42, 0x3c, 0x8b, 0xff, 0x07, 0x87, + 0x8f, 0x74, 0x66, 0xee, 0xa2, 0x3b, 0xbb, 0xce, 0x09, 0x75, 0x23, 0x11, + 0x2c, 0xf5, 0xf8, 0x1e, 0xfb, 0x13, 0x31, 0x83, 0xf2, 0xae, 0x70, 0xfa, + 0x4e, 0xe2, 0xe5, 0x5e, 0xdf, 0x63, 0xb4, 0xa6, 0x88, 0xe0, 0xf7, 0x2d, + 0x77, 0xfb, 0x7e, 0x89, 0xe1, 0x09, 0x0b, 0xa1, 0x2b, 0xdc, 0xbe, 0xe7, + 0xe2, 0x04, 0x53, 0x44, 0x0c, 0x5b, 0x04, 0x7a, 0xb5, 0xd3, 0x47, 0xb5, + 0x63, 0xeb, 0xe0, 0x9c, 0x78, 0xe2, 0xf3, 0x0a, 0xbf, 0xef, 0x44, 0xf8, + 0xa5, 0x7e, 0x9f, 0xb7, 0xd2, 0xed, 0xd3, 0x3f, 0x1d, 0x78, 0xa0, 0x22, + 0x58, 0xe1, 0xf7, 0xd1, 0x97, 0xc3, 0xce, 0x1f, 0x0d, 0xb5, 0x57, 0x3a, + 0x7e, 0xe0, 0xdd, 0xb2, 0xa7, 0x34, 0x6c, 0x2c, 0x7c, 0xe3, 0xf5, 0x4d, + 0x04, 0x0c, 0xb7, 0xa0, 0xe5, 0xd1, 0x95, 0x6e, 0x5f, 0x66, 0x28, 0x0d, + 0xe7, 0x20, 0xe4, 0x06, 0x65, 0xde, 0x5f, 0x0e, 0x0e, 0xd8, 0xc9, 0x28, + 0x15, 0x40, 0x8b, 0x03, 0xdc, 0x54, 0x24, 0x1a, 0x6f, 0x61, 0x4c, 0x5b, + 0xcb, 0x09, 0x94, 0x7a, 0x97, 0x73, 0x03, 0x47, 0x62, 0xa9, 0x1b, 0xf8, + 0xad, 0x58, 0x24, 0xf1, 0xf0, 0x8e, 0x97, 0x04, 0xc9, 0x07, 0x58, 0x5c, + 0xe1, 0x03, 0x62, 0xe9, 0x17, 0xcd, 0x18, 0x24, 0xcb, 0xbc, 0xbf, 0xf7, + 0x1e, 0x39, 0xac, 0xc6, 0x9d, 0xb8, 0xc2, 0xfd, 0x0b, 0xa0, 0xcf, 0x01, + 0x8f, 0xae, 0x33, 0xcf, 0x76, 0xfc, 0x2c, 0x7f, 0xc4, 0xf9, 0x39, 0x82, + 0x34, 0x1d, 0x11, 0xaf, 0x76, 0x05, 0x67, 0xae, 0xcf, 0xcb, 0xb9, 0x0b, + 0xe0, 0x6a, 0x3a, 0x4f, 0x44, 0xb0, 0x48, 0x3e, 0x0b, 0xe7, 0xfd, 0x8b, + 0xc3, 0x6f, 0x0f, 0xdf, 0x3a, 0xbf, 0x3e, 0x7c, 0xfb, 0xe4, 0xc5, 0xeb, + 0x6f, 0x0f, 0x5f, 0xd7, 0x9d, 0xc5, 0x8c, 0x50, 0x05, 0xe1, 0x70, 0x4a, + 0x25, 0x3e, 0x2f, 0xb8, 0xf5, 0xbc, 0x95, 0x5e, 0xe0, 0x4b, 0x32, 0x55, + 0x78, 0xf0, 0xee, 0x6a, 0xd5, 0x4e, 0xa9, 0x6e, 0x4a, 0xeb, 0xd0, 0x93, + 0x7a, 0xb9, 0x20, 0xbd, 0xbc, 0x2b, 0xa2, 0xca, 0xf7, 0x33, 0x0e, 0x3b, + 0xa4, 0xb5, 0xd6, 0x42, 0xe1, 0x33, 0x11, 0x25, 0xde, 0x64, 0xe9, 0x4a, + 0x21, 0x43, 0x4c, 0x7d, 0xe8, 0xc0, 0x40, 0x78, 0x33, 0xe7, 0x25, 0xbb, + 0x82, 0xa4, 0x12, 0x8f, 0xf5, 0x8a, 0x61, 0xdc, 0x20, 0x61, 0xd6, 0xd1, + 0x91, 0xf0, 0x82, 0x62, 0xd9, 0x14, 0xa6, 0xf1, 0xee, 0xc4, 0xeb, 0x15, + 0x36, 0x63, 0x2b, 0x56, 0x0e, 0x17, 0xab, 0x1c, 0xc2, 0xf7, 0x50, 0x7b, + 0x8c, 0x2c, 0xd8, 0x8c, 0xc0, 0xf0, 0x07, 0x85, 0xc0, 0x15, 0x81, 0x0b, + 0x9e, 0x0d, 0x82, 0xe7, 0x3a, 0xf8, 0xc2, 0x82, 0x56, 0x72, 0x8a, 0xa3, + 0xf2, 0xe8, 0xa6, 0x9e, 0x18, 0xc3, 0x54, 0xc1, 0xa7, 0x1a, 0x93, 0xfe, + 0x3e, 0xe1, 0x7a, 0x42, 0x0c, 0x27, 0x42, 0x21, 0xa0, 0x8b, 0xc8, 0xea, + 0xf8, 0x8a, 0xe3, 0x8c, 0xef, 0xa8, 0x7a, 0x82, 0x37, 0x2b, 0xba, 0x8d, + 0xce, 0x78, 0x11, 0x9c, 0x90, 0xf0, 0x3c, 0x48, 0x5f, 0xa3, 0x0c, 0xc4, + 0x74, 0xa6, 0x50, 0xe2, 0x4a, 0x5d, 0xfc, 0x72, 0x4f, 0x92, 0x05, 0xf4, + 0x06, 0xbf, 0x9e, 0x28, 0x5f, 0xf2, 0x14, 0x79, 0x9f, 0x9b, 0x4f, 0x9a, + 0xc5, 0x85, 0xc5, 0x91, 0x58, 0xb1, 0xb4, 0xf8, 0xcc, 0x8d, 0x06, 0xa2, + 0xcc, 0xad, 0x4c, 0xca, 0xbd, 0xca, 0x7f, 0xfd, 0x63, 0x99, 0x57, 0x59, + 0xea, 0x54, 0x0a, 0xef, 0x5f, 0x7f, 0x59, 0xee, 0x56, 0x3e, 0x3e, 0xf9, + 0x2c, 0xc8, 0xc7, 0x88, 0xb0, 0xee, 0x4a, 0xf5, 0x72, 0x5e, 0xb3, 0x93, + 0x13, 0x80, 0xde, 0xbf, 0xfe, 0xfe, 0xaf, 0xbf, 0x88, 0x68, 0x99, 0x87, + 0xb9, 0xaa, 0xec, 0x89, 0x4f, 0x8f, 0xd1, 0x17, 0xfa, 0x9a, 0xf3, 0xc8, + 0x85, 0x8a, 0xa2, 0x5c, 0x7c, 0xfa, 0xaf, 0xbf, 0x4e, 0x21, 0xe8, 0x4d, + 0xfa, 0x9b, 0x8b, 0xff, 0xfc, 0xfa, 0xe2, 0xe3, 0xe0, 0xb3, 0x3b, 0xf5, + 0x57, 0xfb, 0x91, 0x6f, 0x85, 0x87, 0x1e, 0x31, 0x0e, 0xe1, 0x32, 0xdd, + 0xdc, 0x2f, 0x2d, 0x5f, 0x66, 0x14, 0x81, 0x25, 0xfa, 0x5b, 0xf1, 0x40, + 0x9f, 0x93, 0x43, 0x71, 0xda, 0x5c, 0xc7, 0x07, 0xfd, 0x25, 0x7c, 0xd0, + 0xe6, 0x5a, 0xee, 0xe7, 0x73, 0xd6, 0xd3, 0x95, 0x1e, 0xe8, 0x8b, 0x74, + 0xad, 0x91, 0xba, 0x5a, 0xa6, 0x5e, 0x2b, 0x97, 0x1d, 0xdd, 0x9b, 0x2d, + 0x3b, 0xfe, 0x9c, 0xd7, 0x36, 0x27, 0x2b, 0x96, 0x1d, 0xdf, 0xe1, 0x6e, + 0xfb, 0x2b, 0xdc, 0x4f, 0xe6, 0x0f, 0x66, 0x87, 0x41, 0x57, 0x39, 0xa0, + 0x54, 0xa5, 0x53, 0x17, 0xb0, 0xe7, 0xf3, 0x5c, 0xbd, 0x8a, 0x0e, 0xe8, + 0x2f, 0x23, 0xe1, 0xc5, 0x65, 0xfe, 0xe7, 0x5b, 0x77, 0xb4, 0x8e, 0xfb, + 0xe9, 0x06, 0x9f, 0x11, 0x18, 0xb1, 0x86, 0x07, 0x0a, 0xeb, 0xf9, 0xc9, + 0x5b, 0xe9, 0x82, 0xe2, 0x05, 0xfa, 0x09, 0x00, 0xae, 0x58, 0x78, 0xd4, + 0x0e, 0xd0, 0x2a, 0x07, 0x34, 0x37, 0x82, 0xe3, 0x80, 0xa7, 0x07, 0xb3, + 0x11, 0x95, 0xfa, 0xa0, 0x19, 0x50, 0x60, 0xd7, 0xc0, 0xc9, 0xbd, 0x3c, + 0x74, 0xe9, 0xf8, 0x7a, 0xa4, 0xc0, 0x79, 0x8c, 0xcd, 0xd2, 0x5d, 0x36, + 0xc2, 0xae, 0xb1, 0x4c, 0x89, 0x15, 0x8c, 0x9f, 0xeb, 0x65, 0x4a, 0xf9, + 0x32, 0x04, 0x6c, 0xe0, 0xcb, 0x9d, 0x6c, 0x13, 0x08, 0x6c, 0xf6, 0xb2, + 0x9f, 0xbf, 0x7d, 0x82, 0x92, 0xf8, 0xd4, 0x68, 0x9f, 0x3f, 0x79, 0x8b, + 0x04, 0x7c, 0xea, 0x04, 0xb4, 0x81, 0x6c, 0x89, 0x34, 0xe1, 0xc9, 0x73, + 0x24, 0xe0, 0x53, 0x27, 0x3c, 0x79, 0x4b, 0x09, 0xf8, 0x4c, 0x13, 0x9e, + 0x13, 0x0e, 0x7c, 0xea, 0x84, 0xf7, 0x92, 0x0c, 0x7d, 0xa5, 0x49, 0x92, + 0x10, 0x7d, 0xa5, 0x49, 0x92, 0x14, 0x7d, 0xa5, 0x49, 0x92, 0x18, 0x7d, + 0xa5, 0x49, 0x92, 0x1c, 0xbe, 0x4c, 0x92, 0x24, 0x48, 0x5f, 0x69, 0x35, + 0xde, 0x33, 0x45, 0xfa, 0x32, 0x49, 0xb2, 0x6a, 0xef, 0xad, 0xba, 0xbd, + 0x67, 0x8a, 0xf4, 0x95, 0xf2, 0xfe, 0x9e, 0xd1, 0xd3, 0x97, 0x49, 0x92, + 0xf5, 0x79, 0x6f, 0xa1, 0x7f, 0xfb, 0x9e, 0x0a, 0xd2, 0x97, 0x11, 0xdc, + 0x7b, 0x82, 0xa2, 0x2f, 0x23, 0x3a, 0x86, 0xa2, 0x2f, 0x23, 0xbc, 0xf7, + 0x52, 0x7a, 0xef, 0x2d, 0xf1, 0x71, 0x12, 0x7d, 0x19, 0x01, 0x32, 0x2e, + 0xfa, 0x32, 0x14, 0xb9, 0x47, 0xd0, 0x57, 0x81, 0x62, 0x39, 0x94, 0x69, + 0x2e, 0x4a, 0xa2, 0x2f, 0x43, 0x91, 0x93, 0xf0, 0x55, 0x9a, 0x94, 0xd5, + 0x19, 0x13, 0x53, 0x6c, 0xb4, 0xa6, 0xd5, 0xc3, 0x47, 0xe5, 0xf5, 0x9b, + 0xb7, 0xaf, 0x1e, 0xbf, 0xd4, 0x18, 0xda, 0x9d, 0x3d, 0x22, 0x73, 0x08, + 0x8f, 0xfd, 0xe8, 0x30, 0x8f, 0xc3, 0xc4, 0xf8, 0x1a, 0x24, 0xed, 0x5d, + 0xc0, 0x93, 0x45, 0x3f, 0xfe, 0xcd, 0xb3, 0xc7, 0x47, 0xef, 0x34, 0x9e, + 0x6e, 0x47, 0x27, 0xdb, 0xa9, 0xdb, 0x7b, 0x3a, 0xf5, 0xd5, 0xe1, 0xb7, + 0x2f, 0xbe, 0x7f, 0xa5, 0xd3, 0x77, 0xb7, 0x75, 0xfa, 0xd1, 0xcb, 0x37, + 0x69, 0x6d, 0xf6, 0x5a, 0x29, 0x6a, 0x3b, 0xf9, 0x91, 0xa1, 0x68, 0xa7, + 0xb7, 0xdb, 0x29, 0xc9, 0xe7, 0x2f, 0x1f, 0x3f, 0x7d, 0xf1, 0xf8, 0x65, + 0xca, 0xbe, 0xa9, 0x80, 0x09, 0xf7, 0xb5, 0xc5, 0x40, 0x42, 0x70, 0x78, + 0xb0, 0x49, 0x49, 0x23, 0x8d, 0x13, 0xf2, 0x22, 0x30, 0xa1, 0xb7, 0x59, + 0x04, 0x18, 0x81, 0xc0, 0x3c, 0x04, 0x99, 0x4a, 0xb2, 0x23, 0x53, 0xf3, + 0x55, 0xdd, 0xd6, 0xc9, 0x2f, 0x1f, 0xbf, 0x7d, 0x7e, 0x98, 0x0a, 0x40, + 0xa7, 0xfe, 0x46, 0x26, 0x1b, 0xce, 0x29, 0x0e, 0xe7, 0x1e, 0x05, 0xb2, + 0x98, 0x59, 0x1e, 0x5d, 0x46, 0x97, 0xc6, 0x14, 0x54, 0x1b, 0x9e, 0x37, + 0x16, 0xcd, 0x19, 0x36, 0x3f, 0xfe, 0x18, 0xd7, 0x18, 0xb0, 0x24, 0xf4, + 0x0c, 0xa6, 0x7a, 0x44, 0xb1, 0x5a, 0x5b, 0xe5, 0x48, 0xac, 0x40, 0x99, + 0xb7, 0x16, 0x00, 0xe6, 0x23, 0x47, 0x9c, 0xdf, 0x87, 0xf7, 0xcb, 0xab, + 0x3f, 0xd5, 0xda, 0x45, 0x85, 0xb6, 0xd0, 0x69, 0x32, 0x80, 0x88, 0x93, + 0x7d, 0x2a, 0x21, 0x4c, 0x6e, 0x52, 0x0f, 0x6a, 0x17, 0x91, 0x48, 0x16, + 0x51, 0x50, 0x15, 0xfd, 0x37, 0x03, 0x32, 0x6b, 0x4d, 0x4c, 0x0f, 0x60, + 0xd3, 0x92, 0x90, 0x22, 0xcc, 0xde, 0x8c, 0xff, 0xfc, 0xe7, 0x8b, 0xe3, + 0xe3, 0x39, 0x3d, 0x1f, 0x1f, 0xf7, 0x3e, 0x7c, 0xbc, 0x24, 0x83, 0x49, + 0xb7, 0x02, 0x63, 0x9d, 0xf5, 0x31, 0x5d, 0x10, 0xf9, 0xe0, 0x41, 0x8a, + 0x4d, 0xd4, 0x93, 0xda, 0x85, 0x68, 0xa6, 0xe0, 0xfd, 0xe4, 0xf2, 0xcf, + 0x7f, 0xce, 0xe6, 0x8e, 0x71, 0x91, 0x15, 0xf1, 0x10, 0xf0, 0x05, 0xe2, + 0xb5, 0xa4, 0x39, 0x75, 0xe3, 0x37, 0xa7, 0x01, 0xe8, 0xcd, 0x61, 0xc1, + 0xcf, 0xab, 0x41, 0xed, 0xc1, 0x83, 0xaa, 0xf8, 0x10, 0x7c, 0xec, 0x27, + 0xf8, 0xa8, 0x5d, 0xd6, 0x98, 0xc5, 0xcb, 0x7d, 0x85, 0x05, 0x65, 0x24, + 0xcf, 0xe9, 0x73, 0x88, 0x1a, 0xca, 0x83, 0xf0, 0x61, 0x80, 0x4a, 0x2e, + 0xd0, 0xdc, 0x11, 0xe8, 0x0a, 0x06, 0xab, 0x27, 0x4d, 0x66, 0x45, 0x5d, + 0x11, 0x8d, 0x8b, 0x2a, 0xfb, 0xfd, 0xe0, 0x1b, 0x55, 0xcd, 0x21, 0xfb, + 0xcf, 0xa0, 0xd8, 0xab, 0x86, 0x36, 0x98, 0xf9, 0x5d, 0xc7, 0x05, 0x68, + 0x4e, 0x58, 0xbb, 0x64, 0x86, 0x8d, 0xd0, 0xb4, 0xc4, 0x1c, 0xbb, 0x6a, + 0x8a, 0x0b, 0x15, 0x0d, 0x98, 0xd4, 0xf9, 0x89, 0x11, 0x8a, 0xcb, 0xcb, + 0x6a, 0xad, 0x1e, 0xf6, 0x0d, 0xb4, 0xc5, 0xbe, 0x6a, 0x02, 0xa2, 0x10, + 0xf6, 0x45, 0x73, 0x88, 0xf7, 0xd7, 0xf1, 0xb9, 0xfe, 0x7a, 0x85, 0xa7, + 0x60, 0x15, 0x64, 0xfe, 0xf9, 0xcf, 0x94, 0xb0, 0xaf, 0x68, 0x86, 0x4d, + 0x15, 0x80, 0xd1, 0x4f, 0xf4, 0xaf, 0x7a, 0xd8, 0x64, 0x60, 0x50, 0x0d, + 0x2f, 0x15, 0x58, 0x52, 0x0d, 0xea, 0xa2, 0x56, 0x0f, 0x2e, 0x51, 0xbf, + 0x7a, 0xb4, 0x82, 0x76, 0x3d, 0x04, 0xf5, 0x10, 0x51, 0xac, 0x2d, 0xc8, + 0x26, 0x81, 0xf0, 0x93, 0x7e, 0x5b, 0x74, 0x6b, 0xf5, 0x34, 0x2d, 0x40, + 0x1a, 0x62, 0x05, 0x2b, 0x35, 0xd6, 0x9d, 0x28, 0xcb, 0xe4, 0xd0, 0x0f, + 0x63, 0x4c, 0x7b, 0xc2, 0x1c, 0x93, 0x51, 0x13, 0xf3, 0xba, 0xa7, 0xd8, + 0xeb, 0x0b, 0xfa, 0xf7, 0x5a, 0xf5, 0x08, 0x6d, 0x33, 0x02, 0xbf, 0xf8, + 0x01, 0x91, 0xc7, 0x61, 0xd0, 0x0f, 0xea, 0x51, 0x29, 0xa3, 0x9e, 0x2d, + 0x64, 0x6f, 0x5c, 0x85, 0x07, 0xcf, 0x81, 0x6c, 0xd8, 0x68, 0xbc, 0xd7, + 0x87, 0x30, 0x49, 0xe9, 0x52, 0x1d, 0xaf, 0x49, 0x0c, 0x26, 0xe1, 0xb2, + 0x1e, 0xf7, 0x2f, 0x70, 0x6e, 0x45, 0xf5, 0x08, 0xc6, 0xf3, 0xad, 0x20, + 0xf7, 0xa7, 0x2d, 0xb6, 0xeb, 0xe8, 0x70, 0x65, 0x19, 0xdd, 0xaf, 0xb6, + 0x45, 0xf7, 0x27, 0xaf, 0xdc, 0x64, 0xda, 0xc4, 0x1c, 0x73, 0x14, 0xce, + 0xaa, 0x35, 0x02, 0xfd, 0x7e, 0x4e, 0xd1, 0x53, 0xbd, 0x1d, 0xd1, 0xad, + 0x47, 0xf9, 0x52, 0xcf, 0x31, 0x55, 0x7c, 0xe6, 0x92, 0xa2, 0xf5, 0xda, + 0xcd, 0x6e, 0xdd, 0xe4, 0xbe, 0x43, 0x11, 0x2c, 0x78, 0xf5, 0xb6, 0x51, + 0x8a, 0xf9, 0x48, 0x22, 0x5a, 0xf8, 0x6d, 0x6f, 0xb5, 0xea, 0x23, 0x31, + 0x58, 0x4c, 0x7a, 0xf7, 0xda, 0x97, 0xfb, 0x79, 0xdd, 0xb1, 0x1a, 0x44, + 0x40, 0x91, 0x58, 0x1d, 0x72, 0xc2, 0xbf, 0xb8, 0x94, 0xc2, 0x0f, 0xfb, + 0x2c, 0x64, 0x56, 0xad, 0x63, 0xdf, 0x23, 0xff, 0x53, 0x44, 0xa8, 0x33, + 0xb7, 0x3e, 0xfa, 0x66, 0x5d, 0x29, 0x04, 0xfd, 0xa4, 0x20, 0x51, 0xfa, + 0xe6, 0x16, 0xa2, 0x7e, 0x5b, 0x97, 0xc5, 0x40, 0x3e, 0x3a, 0xe7, 0x79, + 0x0a, 0x42, 0x2b, 0x55, 0x5a, 0x3c, 0xa5, 0x68, 0xb3, 0x54, 0x3a, 0x68, + 0x33, 0x95, 0xa1, 0x12, 0x5e, 0x42, 0xbc, 0xfd, 0x7b, 0x1a, 0x7a, 0x80, + 0x75, 0xb8, 0xe8, 0xfc, 0x9d, 0x0c, 0x3f, 0xf5, 0xc3, 0x41, 0x45, 0xa5, + 0x33, 0xa5, 0xa7, 0xd0, 0x0d, 0x31, 0x32, 0xc0, 0x8a, 0xa3, 0x5f, 0x2d, + 0x04, 0x42, 0xc2, 0x3f, 0x7c, 0x94, 0xa9, 0x61, 0xc0, 0xb0, 0x7d, 0x59, + 0x4d, 0x9d, 0xc6, 0xb5, 0xc8, 0xa5, 0xa9, 0xe2, 0xb9, 0x54, 0xaa, 0x5b, + 0x26, 0xe9, 0x78, 0x8a, 0xa6, 0xf3, 0xc5, 0x1b, 0xa4, 0x67, 0x54, 0x3d, + 0x6c, 0x1e, 0xb3, 0xe0, 0xab, 0x15, 0x2a, 0xe2, 0xf0, 0x0d, 0x7a, 0x4a, + 0x91, 0x93, 0x3e, 0x32, 0x43, 0x39, 0x69, 0x6a, 0xa6, 0x0d, 0x5e, 0x07, + 0xde, 0xb4, 0x33, 0x7c, 0x63, 0x65, 0xf4, 0x92, 0xfd, 0x21, 0xf4, 0x39, + 0x52, 0x4d, 0x5c, 0x0d, 0x53, 0xe1, 0xa8, 0x94, 0x5a, 0x1d, 0x49, 0x0b, + 0x86, 0x55, 0x29, 0x7d, 0xd8, 0x51, 0x0d, 0x5e, 0xb4, 0x1d, 0x80, 0xc6, + 0x0d, 0xbc, 0x98, 0x7a, 0x83, 0x69, 0x24, 0x5f, 0xd6, 0x03, 0xc6, 0x70, + 0x1a, 0x37, 0x2d, 0xf9, 0x22, 0xc1, 0x3c, 0x21, 0x3b, 0x23, 0xce, 0x26, + 0x6c, 0xe9, 0x21, 0x66, 0xd7, 0x06, 0xb9, 0x48, 0xb1, 0x4b, 0x4c, 0x31, + 0xee, 0x86, 0x43, 0xe2, 0x25, 0x30, 0x17, 0x5b, 0x22, 0x54, 0x82, 0x7c, + 0xf0, 0x40, 0xfd, 0xa2, 0xf2, 0x48, 0x35, 0x8a, 0xd5, 0xa4, 0xc4, 0x22, + 0x95, 0xc4, 0xa6, 0x42, 0xb6, 0xe0, 0x90, 0xc4, 0xfa, 0x52, 0x95, 0x22, + 0x15, 0x06, 0xc5, 0xcb, 0x4c, 0xc3, 0xbc, 0x92, 0xb4, 0x97, 0xb4, 0x8d, + 0xe2, 0x4c, 0x37, 0x0f, 0x73, 0xa6, 0xd2, 0xc0, 0x9c, 0x79, 0x28, 0xf0, + 0xa7, 0xd2, 0x6f, 0x85, 0x45, 0x9e, 0x2a, 0x2c, 0x61, 0x90, 0x35, 0x53, + 0xb1, 0x57, 0x17, 0x8a, 0xac, 0x64, 0xc6, 0x2c, 0xf6, 0x56, 0x95, 0x42, + 0x56, 0xde, 0xbd, 0x78, 0x75, 0xf8, 0xe6, 0xfb, 0x77, 0x15, 0xa8, 0x50, + 0x0a, 0xfb, 0x4d, 0x25, 0x91, 0x9a, 0x50, 0xe9, 0x49, 0x30, 0x59, 0x4b, + 0x46, 0xfc, 0xe0, 0x41, 0xfa, 0x93, 0x6b, 0x68, 0xc8, 0x9e, 0x89, 0xa1, + 0x23, 0x69, 0xa7, 0x75, 0xae, 0xe4, 0x44, 0xc0, 0xd9, 0x37, 0x14, 0x00, + 0x61, 0xd2, 0xcc, 0xe7, 0xa4, 0xf1, 0x14, 0xfd, 0x73, 0x59, 0x73, 0x51, + 0xdf, 0xb5, 0x1b, 0xeb, 0xd8, 0xee, 0x18, 0x31, 0x0d, 0x75, 0x05, 0x8b, + 0x82, 0x2a, 0x1a, 0x52, 0xb2, 0xea, 0x8c, 0x05, 0xe9, 0xea, 0x67, 0xb1, + 0x71, 0x29, 0xf5, 0x4b, 0x9b, 0x76, 0x11, 0xf9, 0x7d, 0xa1, 0x7e, 0xf3, + 0xa8, 0x8e, 0x19, 0x7a, 0xac, 0x06, 0xe7, 0xb4, 0xf7, 0xf7, 0x03, 0xf5, + 0x6c, 0x64, 0xa1, 0x28, 0x28, 0x47, 0x41, 0x0e, 0x41, 0xda, 0x45, 0x01, + 0x89, 0x8a, 0x8a, 0xa0, 0x7d, 0xf1, 0x1a, 0x53, 0x87, 0x0b, 0x8c, 0xf7, + 0xbd, 0x62, 0xff, 0x6e, 0x5d, 0xd6, 0xb1, 0xa4, 0x8e, 0x95, 0x34, 0x9a, + 0x57, 0xf7, 0x60, 0x51, 0x81, 0x7d, 0xec, 0x4d, 0x16, 0xfa, 0x19, 0xe2, + 0x5f, 0x8a, 0xfe, 0xcd, 0x77, 0x87, 0xaf, 0x97, 0x22, 0x6e, 0x7f, 0x01, + 0xe2, 0xa7, 0x2f, 0xdf, 0x1c, 0xad, 0x62, 0xba, 0xf3, 0x85, 0xb8, 0x0f, + 0xbf, 0x5d, 0x8a, 0xba, 0x7b, 0x63, 0xd4, 0xa9, 0x3f, 0xb6, 0x9e, 0xe0, + 0x45, 0xd3, 0x00, 0xdd, 0x0a, 0x4d, 0x6a, 0x8d, 0x15, 0xd4, 0x28, 0xfb, + 0x56, 0xe8, 0xa8, 0xc6, 0x59, 0x41, 0x8a, 0x20, 0x6e, 0xab, 0x56, 0xb2, + 0xb9, 0x56, 0x10, 0x93, 0x00, 0xb7, 0x42, 0xcb, 0x8c, 0x61, 0x4b, 0xe9, + 0xc9, 0x1e, 0x78, 0x1a, 0x7f, 0x43, 0x3f, 0x72, 0xc3, 0x60, 0x2f, 0xef, + 0x77, 0xc0, 0xd1, 0x63, 0x24, 0xc6, 0x3a, 0xe5, 0x21, 0xd0, 0xeb, 0x35, + 0x22, 0x72, 0x69, 0x0d, 0x4e, 0x03, 0x50, 0xbb, 0x95, 0xaa, 0x19, 0x77, + 0x6a, 0x69, 0xd5, 0xd8, 0xb7, 0x84, 0x3b, 0x58, 0xcd, 0x3b, 0x60, 0xf5, + 0xd6, 0xed, 0xf0, 0x30, 0x58, 0x8c, 0xc7, 0x02, 0xfb, 0x0d, 0x8f, 0x67, + 0x2b, 0xf9, 0x28, 0x3a, 0x64, 0x4d, 0x14, 0x5a, 0x0c, 0x45, 0xd5, 0x9e, + 0xc7, 0x68, 0xf0, 0x8a, 0xdc, 0x3e, 0xaa, 0xf4, 0xb5, 0xdf, 0x9d, 0x7c, + 0x23, 0xbe, 0xc2, 0x9c, 0x03, 0xeb, 0x92, 0x13, 0x1c, 0x68, 0x4b, 0x1c, + 0x6b, 0x1e, 0xf8, 0x04, 0x5e, 0xa0, 0xcc, 0xe5, 0x6b, 0x5f, 0xf8, 0xd7, + 0xe0, 0x3c, 0x11, 0x2f, 0x19, 0xb6, 0x2e, 0x2e, 0x51, 0xd3, 0xaf, 0xaa, + 0xc5, 0x26, 0xce, 0x32, 0xde, 0xbb, 0x25, 0x71, 0x88, 0x33, 0x0c, 0x05, + 0x31, 0x59, 0xf6, 0x6b, 0x68, 0x9b, 0x29, 0xd4, 0xab, 0x54, 0x6e, 0x85, + 0x0d, 0x3d, 0xde, 0x5c, 0x83, 0x09, 0x5d, 0xe4, 0xb6, 0x58, 0x88, 0x68, + 0x03, 0xf2, 0x08, 0xaf, 0xbd, 0xbd, 0x4e, 0xbf, 0x33, 0x85, 0x7a, 0xb7, + 0x6e, 0x4a, 0x17, 0xd1, 0x75, 0xc4, 0xb1, 0x88, 0xd6, 0x93, 0x84, 0x45, + 0xa2, 0x29, 0x27, 0x16, 0x19, 0x85, 0x36, 0xb3, 0x29, 0x41, 0x6b, 0x0b, + 0x3c, 0xbd, 0x2d, 0x9b, 0xb2, 0xb4, 0xca, 0x67, 0x43, 0x7a, 0x2e, 0x53, + 0xf4, 0x73, 0x56, 0xc9, 0x0e, 0x27, 0xd7, 0x28, 0x55, 0x59, 0x51, 0x03, + 0xc1, 0x14, 0x99, 0x2d, 0xb6, 0x6a, 0x59, 0xa7, 0xaa, 0x87, 0x37, 0x3f, + 0x30, 0x0a, 0x87, 0x1f, 0x47, 0x95, 0x32, 0x20, 0x9c, 0x02, 0xf8, 0x13, + 0x75, 0xde, 0x11, 0xbd, 0x27, 0xc7, 0x39, 0x8d, 0xd3, 0x8e, 0x58, 0xa9, + 0x5d, 0x66, 0x44, 0x91, 0xce, 0x5b, 0x73, 0xe2, 0x58, 0x3d, 0xe7, 0x2b, + 0x4e, 0xe3, 0x8a, 0xb3, 0x46, 0x63, 0x5a, 0xaf, 0xae, 0xb9, 0xea, 0xf6, + 0xc6, 0x4f, 0x66, 0x26, 0xf2, 0x1e, 0x97, 0xac, 0xa8, 0x49, 0xc8, 0x56, + 0x85, 0x27, 0x32, 0x19, 0x6f, 0x74, 0x25, 0x07, 0x7d, 0xc9, 0x01, 0x8f, + 0xcc, 0x4c, 0xdf, 0x48, 0x90, 0x10, 0xc1, 0x85, 0x57, 0xf4, 0xcd, 0x1c, + 0x09, 0x0c, 0x64, 0x01, 0x95, 0x90, 0x25, 0x6c, 0xd1, 0x70, 0xce, 0x17, + 0xf1, 0x14, 0xa5, 0x72, 0x6c, 0xe2, 0x84, 0x5d, 0xc6, 0x1b, 0xcd, 0x09, + 0x3e, 0x37, 0x6f, 0xff, 0x20, 0x3e, 0x3e, 0x78, 0x50, 0x4c, 0x93, 0xb8, + 0x93, 0x42, 0x63, 0xd2, 0x95, 0xf0, 0xd7, 0xc5, 0x5e, 0x2d, 0x26, 0xf6, + 0x4b, 0x28, 0xe2, 0x15, 0x2e, 0xd8, 0xc7, 0x29, 0x9b, 0x47, 0x72, 0x6b, + 0x5e, 0xe6, 0xea, 0xa9, 0x84, 0x64, 0xe8, 0x9b, 0x65, 0x3d, 0x39, 0xc7, + 0xef, 0xb7, 0xf6, 0x93, 0xaf, 0xb1, 0x10, 0xc6, 0x67, 0x1f, 0x63, 0x35, + 0x64, 0xec, 0x27, 0x5f, 0x7d, 0x55, 0x13, 0x1f, 0x92, 0x8f, 0xfd, 0x34, + 0x07, 0x0f, 0xfb, 0x19, 0x57, 0xbc, 0xc9, 0x88, 0x1f, 0x3c, 0xb0, 0x4e, + 0x6c, 0xd2, 0x81, 0x4f, 0xff, 0xbc, 0xaa, 0x52, 0xea, 0x1f, 0xb0, 0x6b, + 0x70, 0x74, 0x50, 0xf9, 0x48, 0xcb, 0x7d, 0x43, 0x37, 0x29, 0xb6, 0xc1, + 0x31, 0xac, 0xcb, 0x6b, 0x58, 0x73, 0x5e, 0xa9, 0xb1, 0x59, 0x94, 0xec, + 0x65, 0xc8, 0x81, 0x53, 0xd1, 0x5c, 0xb1, 0xbc, 0x93, 0x5f, 0x0d, 0x58, + 0xb5, 0x12, 0x84, 0xb5, 0x37, 0x20, 0x2b, 0x5b, 0x64, 0xaa, 0x47, 0x06, + 0x4b, 0x08, 0x2c, 0xa5, 0x0b, 0x51, 0x61, 0xdd, 0xa3, 0xe2, 0xee, 0x59, + 0xb1, 0xf8, 0xd0, 0x14, 0xf7, 0x50, 0xbc, 0x74, 0x81, 0xcb, 0xab, 0x2f, + 0xfa, 0x91, 0x5e, 0x5a, 0xca, 0x77, 0xd9, 0x83, 0x16, 0x34, 0x01, 0xf9, + 0x72, 0x95, 0x6b, 0x1e, 0x9e, 0x56, 0x83, 0x42, 0xb7, 0x6e, 0xb4, 0x6b, + 0xb5, 0x83, 0x21, 0xc3, 0x0d, 0x6b, 0xf5, 0x4c, 0x57, 0x08, 0x20, 0x4d, + 0xec, 0x95, 0xf1, 0x56, 0xff, 0xa2, 0x56, 0x5f, 0xe4, 0xe4, 0x7d, 0xea, + 0x7a, 0x49, 0xb9, 0x9c, 0x35, 0x3f, 0xb4, 0x8a, 0x8a, 0xf1, 0x00, 0x91, + 0xbf, 0x22, 0x33, 0x8f, 0xb3, 0xd6, 0x47, 0x92, 0x7a, 0xae, 0xe5, 0xaa, + 0x68, 0xd7, 0x25, 0x2d, 0xfb, 0x7d, 0xe4, 0x5b, 0xaa, 0xcf, 0xeb, 0x84, + 0x05, 0x67, 0x45, 0xa8, 0xc5, 0x41, 0x45, 0x97, 0x5a, 0x19, 0xea, 0xf3, + 0x89, 0x66, 0x99, 0xfb, 0x04, 0xaf, 0xcb, 0x5b, 0x25, 0x24, 0xe7, 0xd0, + 0x88, 0x2a, 0x83, 0x14, 0xfd, 0x9f, 0x65, 0x28, 0x13, 0x86, 0x4f, 0x9a, + 0x09, 0x36, 0x0a, 0x35, 0x4c, 0x72, 0x99, 0x4c, 0xe9, 0xc2, 0x8d, 0x43, + 0x9e, 0xd5, 0x63, 0xf3, 0xfa, 0x93, 0x4b, 0x37, 0x05, 0x7c, 0xff, 0xf6, + 0x65, 0xce, 0x4a, 0x6b, 0x93, 0xb7, 0x44, 0x84, 0x84, 0xf9, 0x5e, 0x61, + 0x2d, 0xee, 0xc1, 0x83, 0x52, 0x1b, 0x5e, 0xbb, 0x28, 0x59, 0xb5, 0x6b, + 0xc9, 0xd5, 0xae, 0x9c, 0xe2, 0x07, 0xf0, 0xd0, 0xcc, 0x0a, 0x25, 0x54, + 0xd7, 0xac, 0x38, 0x7e, 0x13, 0x5b, 0x39, 0x3d, 0xac, 0xd4, 0x02, 0xb4, + 0xb0, 0xc4, 0x69, 0x2b, 0x65, 0x84, 0x12, 0xc5, 0x35, 0xd0, 0xa8, 0xbe, + 0x40, 0xc1, 0x74, 0x6d, 0xb6, 0xee, 0x9a, 0x02, 0x8b, 0x6f, 0xbc, 0x6a, + 0xad, 0xb7, 0xa0, 0xba, 0x15, 0x54, 0xb5, 0x1f, 0xd6, 0x32, 0xca, 0x07, + 0x56, 0x9c, 0x48, 0xf2, 0x82, 0x6f, 0x8a, 0x25, 0x81, 0xfd, 0x2e, 0x38, + 0xd2, 0x95, 0x83, 0x3e, 0x2d, 0x42, 0xef, 0xe3, 0xfd, 0xa1, 0xe2, 0xa2, + 0x04, 0xed, 0x57, 0x5f, 0x65, 0x55, 0x5a, 0xb1, 0x5b, 0xc4, 0xa4, 0x55, + 0x5f, 0x9a, 0x5b, 0x6d, 0x69, 0x69, 0xb0, 0x4f, 0x55, 0x26, 0x5d, 0x89, + 0xae, 0x4e, 0xfb, 0x2e, 0xd6, 0xbd, 0x3b, 0x30, 0x91, 0x53, 0x3d, 0x35, + 0xab, 0x65, 0x9a, 0xfd, 0x75, 0xe8, 0xc8, 0x76, 0x4f, 0xc5, 0x20, 0x0f, + 0xdb, 0xd3, 0x06, 0xf2, 0x27, 0x0f, 0x51, 0x57, 0x6a, 0x2d, 0x72, 0xca, + 0x56, 0x50, 0x76, 0xa5, 0x6a, 0x8d, 0x15, 0xa9, 0x64, 0xc5, 0x30, 0xd3, + 0x03, 0xaa, 0x82, 0x57, 0x37, 0x6a, 0x97, 0x79, 0x70, 0xda, 0x81, 0xc9, + 0x0c, 0xe2, 0xdf, 0x88, 0xfc, 0x3a, 0x6e, 0x0f, 0x85, 0x0b, 0x92, 0xb8, + 0x00, 0x36, 0x18, 0xb1, 0x74, 0x95, 0xa4, 0x07, 0x98, 0xf4, 0x81, 0x9c, + 0x2c, 0x1a, 0x2d, 0xfb, 0x76, 0xe2, 0x37, 0xd4, 0xaf, 0x5d, 0xee, 0xba, + 0x26, 0xb1, 0xd6, 0x53, 0xa9, 0x28, 0x51, 0x98, 0x72, 0x65, 0x56, 0x33, + 0x0b, 0x6c, 0x51, 0x0a, 0x46, 0x50, 0x5b, 0xe8, 0x06, 0x66, 0xad, 0x35, + 0x55, 0xa1, 0x97, 0xaf, 0x34, 0x08, 0xfa, 0xda, 0x90, 0x0d, 0xc9, 0xa5, + 0xdd, 0xe9, 0x72, 0x60, 0x99, 0xae, 0x67, 0xab, 0x89, 0x5e, 0xb3, 0xd3, + 0x6b, 0x5d, 0xc5, 0xf5, 0xc2, 0x2a, 0x6f, 0x10, 0x55, 0xe5, 0x6f, 0xbd, + 0xf0, 0xa7, 0x00, 0x8b, 0x83, 0xa6, 0x17, 0x97, 0x3a, 0x64, 0xa4, 0xb0, + 0x25, 0x2e, 0xea, 0x15, 0x4e, 0xa7, 0x62, 0xb5, 0xa8, 0xa9, 0xfb, 0xd0, + 0xe5, 0x8b, 0x12, 0x7f, 0xb3, 0xb8, 0xbe, 0xc7, 0xdc, 0xf3, 0x92, 0x99, + 0x66, 0x18, 0x23, 0xea, 0x70, 0x4a, 0x36, 0xb5, 0x20, 0x30, 0xb3, 0x56, + 0xbd, 0x54, 0x5a, 0x12, 0xc4, 0xe1, 0xdb, 0x29, 0x6a, 0x45, 0xbf, 0xb1, + 0x95, 0xc5, 0x58, 0x5c, 0xbb, 0xcb, 0x49, 0xa5, 0xa2, 0xe4, 0xcc, 0xb2, + 0xa7, 0xcd, 0xc2, 0x6f, 0x92, 0xa6, 0x95, 0x04, 0x2e, 0x7b, 0xf4, 0x91, + 0xc1, 0x5a, 0x10, 0x47, 0x9e, 0x59, 0xb3, 0x20, 0x60, 0xf8, 0xce, 0x15, + 0xa9, 0x18, 0x19, 0x97, 0x79, 0x5d, 0x72, 0x2b, 0xa1, 0x52, 0xd8, 0x77, + 0xb8, 0xa2, 0x94, 0xda, 0x29, 0x2b, 0x36, 0xc2, 0x55, 0xe5, 0x94, 0xdb, + 0x59, 0x29, 0x59, 0x4f, 0xbf, 0xb2, 0xac, 0xdc, 0x42, 0x2c, 0xaa, 0x6d, + 0x56, 0x35, 0x65, 0xb7, 0xbb, 0x96, 0xc8, 0x24, 0x7c, 0x51, 0x5e, 0x48, + 0xbf, 0xae, 0xb0, 0x50, 0xe4, 0xfa, 0x92, 0x42, 0xa1, 0x9b, 0x89, 0x09, + 0x05, 0x6f, 0x2a, 0x23, 0xbb, 0x23, 0x66, 0x84, 0x64, 0x67, 0xb0, 0x98, + 0x8a, 0x5b, 0x43, 0x05, 0x90, 0xdc, 0x56, 0x11, 0xd1, 0xc2, 0x26, 0x31, + 0xfe, 0x4f, 0x43, 0x17, 0xe8, 0x76, 0x55, 0x44, 0x2c, 0xe0, 0xc8, 0x15, + 0xde, 0x4f, 0x0b, 0x47, 0x78, 0xc8, 0x91, 0xc0, 0x4d, 0x7d, 0xed, 0x2c, + 0xe0, 0xe8, 0x0e, 0x15, 0x09, 0xd5, 0xef, 0x3b, 0x15, 0x82, 0xf0, 0xe9, + 0xb1, 0x42, 0xf7, 0xa5, 0x98, 0xf4, 0x8a, 0xbe, 0x0e, 0x45, 0x63, 0xac, + 0xb4, 0x1f, 0x75, 0x9a, 0xed, 0xdd, 0xbd, 0x66, 0xbb, 0x83, 0xf7, 0x2e, + 0xb7, 0xbb, 0x15, 0xf9, 0x56, 0x51, 0xde, 0x3e, 0xc7, 0x74, 0x92, 0x46, + 0x15, 0x82, 0x3a, 0xa5, 0x80, 0x84, 0x8a, 0xf3, 0x15, 0x17, 0xc3, 0x57, + 0xa5, 0xb7, 0xd7, 0xae, 0x68, 0xee, 0xd2, 0x13, 0x9d, 0x26, 0xa6, 0xc2, + 0x77, 0x39, 0x28, 0xd8, 0x44, 0x8b, 0x25, 0x74, 0xe6, 0xf7, 0x78, 0x2c, + 0x63, 0xed, 0xee, 0x3f, 0xe3, 0xbf, 0x6c, 0x9e, 0x8e, 0x9d, 0xe5, 0x97, + 0x3b, 0xe7, 0x33, 0x07, 0x32, 0x0e, 0x4f, 0xbd, 0x76, 0x3b, 0x97, 0x97, + 0x04, 0xb2, 0xd8, 0x5e, 0xeb, 0x69, 0xab, 0x90, 0x85, 0xa0, 0x0f, 0x49, + 0x11, 0x58, 0xd3, 0xdc, 0x4f, 0x5e, 0xec, 0x0d, 0x3c, 0xdf, 0x4b, 0x10, + 0x0b, 0xf7, 0xe1, 0xa3, 0x4c, 0x54, 0xe7, 0x7b, 0x8f, 0xa9, 0x7d, 0x29, + 0x9a, 0x4d, 0x9f, 0xdb, 0xcd, 0x06, 0xba, 0xd2, 0x25, 0x39, 0x48, 0x4c, + 0x83, 0xdf, 0x8e, 0x03, 0x15, 0xfd, 0xc6, 0x31, 0x1f, 0x52, 0x1c, 0x72, + 0x4d, 0xc2, 0x08, 0x63, 0x6a, 0x22, 0x5a, 0x35, 0xc2, 0xf4, 0xca, 0xdc, + 0x7c, 0xda, 0x9c, 0x63, 0x55, 0x5b, 0x2a, 0x29, 0xbd, 0x49, 0xb5, 0x00, + 0x06, 0xbf, 0xc1, 0xa4, 0x51, 0x43, 0x0d, 0x03, 0x2a, 0x67, 0x9e, 0x29, + 0xc2, 0x2c, 0x0b, 0x81, 0x0b, 0x1b, 0x33, 0x10, 0xe3, 0xb3, 0x70, 0x6e, + 0x95, 0x11, 0x01, 0xad, 0xa1, 0x50, 0xb9, 0xd3, 0x1e, 0x0e, 0xd6, 0xc1, + 0x77, 0xaa, 0x9b, 0x2a, 0xe1, 0xa6, 0x05, 0x13, 0x72, 0xc3, 0x87, 0x11, + 0x4d, 0x41, 0xd5, 0x70, 0x17, 0xa7, 0x3d, 0xbc, 0xc7, 0x37, 0xa2, 0x8f, + 0x09, 0x7d, 0x0c, 0xe8, 0x63, 0x2a, 0xce, 0x7a, 0x95, 0x96, 0xfa, 0x43, + 0x58, 0xfa, 0x69, 0x87, 0x81, 0xf8, 0x73, 0xc2, 0x9f, 0x83, 0x8e, 0x82, + 0xeb, 0x64, 0x01, 0xbb, 0x0c, 0xc8, 0x9f, 0x13, 0xfe, 0x1c, 0x74, 0x15, + 0x60, 0xd7, 0x02, 0xd4, 0x47, 0x3f, 0xe4, 0xfb, 0x36, 0x02, 0x0e, 0x62, + 0x86, 0x46, 0xab, 0x54, 0x7e, 0x33, 0x04, 0x27, 0xa4, 0xb5, 0xee, 0xec, + 0xb5, 0x3b, 0xe3, 0xb3, 0x63, 0x59, 0x03, 0x8a, 0x01, 0xb1, 0x2b, 0x71, + 0x8c, 0xa5, 0x25, 0x80, 0xd7, 0x4d, 0x2d, 0x63, 0x4b, 0x3f, 0x8c, 0x57, + 0x9b, 0x29, 0x69, 0xde, 0xdf, 0x77, 0x6c, 0x20, 0xec, 0x72, 0x40, 0x7a, + 0x5c, 0x0e, 0x64, 0x64, 0xe8, 0xc5, 0x3a, 0x5d, 0x8c, 0x8c, 0xf4, 0x65, + 0xe4, 0xf8, 0x18, 0x53, 0x8b, 0xe9, 0x31, 0x47, 0xa0, 0xc2, 0x7f, 0x34, + 0x65, 0xe8, 0x46, 0x9f, 0x54, 0x21, 0x4d, 0x1d, 0x64, 0xf0, 0x66, 0x8a, + 0xc6, 0xb4, 0x21, 0xad, 0x6d, 0xbc, 0x48, 0xf6, 0xf9, 0x68, 0x00, 0xbd, + 0xd8, 0x83, 0xae, 0x7a, 0x99, 0x47, 0xe4, 0xcd, 0x50, 0xd8, 0x7f, 0x12, + 0xe3, 0xac, 0x24, 0xc3, 0xa0, 0x27, 0x9b, 0xa8, 0xa5, 0x5f, 0xe3, 0x04, + 0xaa, 0xef, 0xbb, 0xce, 0x2f, 0x62, 0x8a, 0x41, 0x54, 0xaf, 0x9b, 0x3e, + 0x52, 0x2f, 0xd1, 0x1a, 0x9c, 0x3b, 0xcf, 0x91, 0x30, 0x71, 0x9d, 0x5f, + 0x7b, 0x38, 0x06, 0x12, 0xfe, 0xf0, 0x07, 0x14, 0x86, 0x04, 0xfc, 0xf2, + 0xd8, 0xd1, 0xc8, 0xc1, 0xaa, 0x49, 0x74, 0x7e, 0x24, 0xc3, 0xae, 0xa2, + 0x1f, 0xfe, 0x20, 0x0d, 0x6d, 0xf8, 0x53, 0x5c, 0x8d, 0x39, 0xf5, 0xd0, + 0xaf, 0x29, 0x9d, 0x92, 0x4e, 0x9b, 0xb9, 0x23, 0x29, 0x53, 0xd4, 0x40, + 0x4b, 0xf3, 0xc4, 0x44, 0x64, 0x1a, 0xb1, 0x25, 0xdf, 0x34, 0x8e, 0xab, + 0x8d, 0x7c, 0xf8, 0xd4, 0x11, 0xe8, 0xf6, 0x89, 0xc2, 0xc3, 0xfb, 0xf8, + 0xf9, 0xb0, 0x56, 0x97, 0x71, 0xf6, 0x3a, 0x8d, 0x1f, 0x90, 0xca, 0x41, + 0xf6, 0x3a, 0x91, 0x7e, 0x23, 0x8d, 0x23, 0xec, 0xd3, 0x44, 0x7a, 0xa0, + 0x54, 0xa5, 0x5c, 0x3a, 0x59, 0x3e, 0x21, 0x5d, 0xaa, 0x97, 0x4e, 0xc6, + 0x03, 0x51, 0xdb, 0x77, 0x52, 0xde, 0x12, 0x6a, 0xf9, 0x3c, 0x6b, 0x88, + 0xa7, 0xff, 0xb5, 0xeb, 0xeb, 0x42, 0x32, 0x21, 0xe5, 0x31, 0x9b, 0xa9, + 0x93, 0x34, 0xb3, 0xd9, 0x5c, 0x95, 0xa2, 0xb9, 0xce, 0xe5, 0xea, 0x24, + 0xc3, 0x7e, 0x36, 0x3f, 0x4d, 0x4b, 0xeb, 0x91, 0xcd, 0xd7, 0x49, 0xa8, + 0x90, 0x25, 0x6b, 0xd5, 0xfc, 0xdf, 0xca, 0xcb, 0xa9, 0xb8, 0x4e, 0x52, + 0xe9, 0x54, 0x8a, 0x2e, 0x9d, 0x79, 0xc7, 0x59, 0x16, 0x85, 0x7c, 0xcf, + 0xb9, 0x91, 0xc7, 0xcb, 0x81, 0xa6, 0x69, 0x5e, 0x80, 0x8e, 0xe4, 0x8f, + 0xa9, 0x4c, 0xca, 0x00, 0x38, 0xe3, 0xa3, 0x96, 0x4b, 0x19, 0x04, 0xa5, + 0x7f, 0xd4, 0xb2, 0x29, 0x85, 0xe0, 0x8c, 0x8f, 0x46, 0x3e, 0x65, 0x30, + 0x32, 0x07, 0x40, 0xfb, 0x4a, 0xe5, 0x54, 0x95, 0xd4, 0x05, 0x17, 0x46, + 0xa1, 0x75, 0xc6, 0x53, 0x4e, 0xaf, 0xba, 0x3e, 0x70, 0xc9, 0xee, 0x97, + 0x8e, 0xb7, 0x34, 0x3e, 0xdf, 0x43, 0x06, 0x27, 0xac, 0x71, 0x23, 0x98, + 0x7c, 0xcf, 0x1f, 0x86, 0x5c, 0xb6, 0xbd, 0xcd, 0xd4, 0x3e, 0xe9, 0x1b, + 0xc2, 0xcc, 0x7b, 0xe1, 0x99, 0x28, 0xe8, 0xfd, 0x01, 0xa6, 0xbb, 0xfa, + 0xa3, 0x0b, 0x48, 0xaf, 0xc9, 0x77, 0x2e, 0x5e, 0xd6, 0x9d, 0x1f, 0x5d, + 0xb0, 0xa8, 0xac, 0x67, 0x12, 0x8c, 0x7a, 0xac, 0xfd, 0x61, 0x7f, 0x5d, + 0x4e, 0xf0, 0x96, 0xbf, 0x32, 0x4e, 0x3c, 0x58, 0xac, 0xe8, 0xe7, 0xef, + 0x5e, 0xbd, 0x24, 0x17, 0xe1, 0x3e, 0x41, 0x80, 0x85, 0x77, 0x21, 0xa0, + 0xab, 0x1f, 0x48, 0xbe, 0x8a, 0x52, 0xdd, 0x49, 0x79, 0x52, 0x8d, 0xaa, + 0x1f, 0x0c, 0x37, 0x1f, 0xed, 0xdb, 0xd7, 0x20, 0xe9, 0x23, 0x18, 0x22, + 0x29, 0x66, 0x93, 0x9c, 0xf1, 0x9b, 0xa4, 0x35, 0xb3, 0x4b, 0xc9, 0x14, + 0xb0, 0x52, 0x3a, 0x2b, 0x74, 0x2e, 0x28, 0x5d, 0x7a, 0x19, 0x55, 0x74, + 0x53, 0x48, 0x63, 0xa7, 0xd5, 0xd2, 0xe5, 0x2f, 0x1d, 0x5a, 0x2c, 0xb8, + 0x56, 0xd3, 0xb4, 0x2b, 0x57, 0x36, 0x85, 0x91, 0x57, 0x33, 0x02, 0xbd, + 0x4c, 0xc2, 0x24, 0x9f, 0x30, 0xb8, 0x66, 0x83, 0x10, 0xfd, 0x62, 0x03, + 0x58, 0x08, 0x31, 0x54, 0xae, 0x8d, 0x8f, 0xde, 0x99, 0x79, 0xbd, 0xfa, + 0x74, 0x0a, 0x15, 0x2a, 0xa4, 0x0c, 0x3a, 0xd7, 0xac, 0x52, 0x67, 0x8d, + 0x2a, 0x75, 0xd6, 0x46, 0x48, 0xaf, 0xc9, 0xbc, 0x5e, 0x9d, 0xba, 0x85, + 0x3a, 0x15, 0x52, 0x06, 0xdd, 0x6b, 0xd6, 0xa9, 0xbb, 0x46, 0x9d, 0xba, + 0x5a, 0x0b, 0xcd, 0xe0, 0xc6, 0xd7, 0xf5, 0xc1, 0x1e, 0x33, 0x0c, 0xad, + 0x1b, 0xa5, 0x17, 0x3d, 0x9d, 0x4e, 0x31, 0x98, 0x7d, 0xfb, 0xe6, 0x15, + 0x7c, 0x06, 0x7d, 0x5a, 0xcf, 0x18, 0x22, 0x09, 0x0f, 0xc3, 0x1d, 0xfd, + 0x1a, 0xd6, 0xa7, 0xaa, 0x06, 0x57, 0x33, 0xf0, 0xc8, 0xce, 0xe6, 0xf4, + 0x4d, 0x8f, 0x94, 0xa4, 0x65, 0xb7, 0xcc, 0xc2, 0xc8, 0x34, 0x1b, 0x8a, + 0xfb, 0x6b, 0x16, 0x88, 0x93, 0x32, 0x30, 0xd4, 0xf1, 0x73, 0x40, 0x9c, + 0x96, 0x85, 0x32, 0x83, 0x92, 0x01, 0x53, 0x89, 0x36, 0x9c, 0x19, 0x9b, + 0x0c, 0x98, 0x4c, 0x53, 0x50, 0x2c, 0x31, 0x53, 0x7f, 0xe5, 0x7b, 0xa7, + 0x95, 0x5f, 0xd5, 0x44, 0xe6, 0xa5, 0x1d, 0x35, 0x8d, 0x5a, 0x15, 0x37, + 0xf3, 0xaa, 0x2b, 0x30, 0xa4, 0x6e, 0x7c, 0x11, 0x45, 0x9a, 0xb5, 0x16, + 0x0e, 0x72, 0xfb, 0x8b, 0x38, 0x74, 0xd6, 0x7a, 0x38, 0x68, 0x9e, 0x50, + 0xc4, 0x91, 0x66, 0xad, 0x85, 0x83, 0xe6, 0x15, 0x45, 0x1c, 0x69, 0xd6, + 0x15, 0x38, 0xec, 0xbb, 0xfb, 0x8b, 0x58, 0x78, 0x92, 0x72, 0x65, 0x55, + 0xcc, 0xf9, 0x98, 0x52, 0x0c, 0x94, 0xb1, 0x1e, 0x0a, 0x4c, 0x77, 0x4a, + 0x31, 0x20, 0x7d, 0x3d, 0x04, 0xf2, 0xbc, 0x85, 0x85, 0xa3, 0xaa, 0x90, + 0xe8, 0xb9, 0x93, 0xf3, 0x80, 0xce, 0x5b, 0xd4, 0xd6, 0xc6, 0x46, 0x27, + 0x2f, 0xae, 0x40, 0xd7, 0xee, 0xac, 0x8f, 0x8e, 0xcf, 0x41, 0xac, 0xc6, + 0x77, 0x0d, 0xe6, 0x28, 0x56, 0x63, 0x35, 0xb2, 0x5d, 0x20, 0x2b, 0xb5, + 0x4f, 0xa5, 0x46, 0xc9, 0xf4, 0x49, 0x86, 0x95, 0x53, 0x06, 0xb6, 0xbd, + 0xa6, 0x67, 0x02, 0x8f, 0x7c, 0x2f, 0xd2, 0x60, 0xa2, 0x10, 0x71, 0xba, + 0xf2, 0x0b, 0x0b, 0x96, 0xbb, 0xd4, 0xc7, 0x69, 0x21, 0x9a, 0xe4, 0x0f, + 0xb6, 0x11, 0x5b, 0x55, 0xb2, 0x55, 0xcf, 0x7a, 0x44, 0x5c, 0xd6, 0x98, + 0xb6, 0xd5, 0x45, 0x51, 0x38, 0xef, 0x3e, 0x19, 0x83, 0xb7, 0x9a, 0x5f, + 0x06, 0xd1, 0x34, 0x97, 0x3d, 0x1a, 0xac, 0xc6, 0x40, 0xae, 0x46, 0x2b, + 0x61, 0x34, 0xa2, 0xd5, 0xcf, 0x06, 0x33, 0xcd, 0x05, 0xf9, 0x7a, 0xdf, + 0xbe, 0x45, 0x04, 0x87, 0xae, 0xfd, 0x11, 0x1f, 0xd4, 0xfb, 0xd0, 0xfa, + 0xb8, 0x6f, 0x5c, 0x56, 0x1b, 0x85, 0x73, 0xd0, 0x77, 0xda, 0x7b, 0x99, + 0x1b, 0x75, 0x19, 0x51, 0x93, 0xb7, 0x31, 0x5e, 0xbb, 0x33, 0x28, 0x4e, + 0x36, 0x81, 0xb6, 0xc5, 0xe0, 0x17, 0x23, 0xa8, 0x68, 0xeb, 0xf7, 0x03, + 0xfd, 0x3a, 0xcf, 0xdf, 0x0f, 0xb6, 0x26, 0x75, 0xa7, 0x82, 0x47, 0x9c, + 0x69, 0x39, 0xa9, 0x64, 0x5d, 0xb0, 0x9b, 0xe3, 0x26, 0x64, 0x0a, 0xb5, + 0xa6, 0x64, 0x70, 0xff, 0xf0, 0x07, 0xa9, 0xc6, 0xa9, 0x17, 0x5d, 0x15, + 0x55, 0xee, 0x86, 0xfa, 0x76, 0x53, 0x65, 0xbb, 0xa9, 0xa6, 0xdd, 0x85, + 0x9a, 0xdd, 0xaa, 0x8e, 0x69, 0x13, 0x31, 0x9c, 0xd2, 0x5b, 0x3b, 0x9d, + 0x88, 0x3f, 0x39, 0x9f, 0x56, 0x0c, 0x94, 0x1f, 0x23, 0xe7, 0xc5, 0xc6, + 0x48, 0x28, 0xe8, 0xb7, 0xf4, 0x21, 0x87, 0xfb, 0xa2, 0xf3, 0x52, 0x5c, + 0xaf, 0x7d, 0x28, 0x4b, 0x3d, 0xac, 0x3b, 0xd5, 0x5a, 0xff, 0xe0, 0x22, + 0x33, 0x83, 0x98, 0xb9, 0x27, 0x38, 0xe8, 0x84, 0x6b, 0x69, 0x52, 0xcf, + 0xc9, 0xc5, 0x6f, 0x94, 0x16, 0xb4, 0x42, 0x30, 0xc0, 0x65, 0x03, 0xb4, + 0x2a, 0xd0, 0xc2, 0x2a, 0x08, 0x9d, 0x87, 0xcf, 0x1c, 0xd5, 0x4f, 0xad, + 0x20, 0xbf, 0x71, 0x4d, 0xb1, 0x93, 0xb2, 0x61, 0x4d, 0x67, 0xb4, 0x7e, + 0xe9, 0xde, 0x92, 0x9d, 0x20, 0xf1, 0x92, 0x6b, 0xbb, 0xe6, 0xd8, 0x2e, + 0xa6, 0xed, 0x7a, 0x5d, 0x5d, 0xb8, 0x93, 0x2d, 0xdc, 0xb9, 0x5e, 0xe9, + 0x6e, 0xb6, 0x74, 0x77, 0x49, 0xe9, 0xa2, 0x79, 0x36, 0x99, 0xb9, 0x89, + 0x6d, 0xda, 0x9f, 0x6a, 0x76, 0x0f, 0xd8, 0x64, 0xeb, 0x30, 0xc1, 0xd2, + 0xf6, 0xb1, 0x58, 0x51, 0xb3, 0xcc, 0x1b, 0xb6, 0xd1, 0x44, 0xbb, 0xbe, + 0xeb, 0xca, 0xb9, 0x93, 0x2d, 0xde, 0xb9, 0x6e, 0xf9, 0x6e, 0xb6, 0x7c, + 0x57, 0x97, 0xbf, 0xd5, 0x96, 0x22, 0x7b, 0xb2, 0xc9, 0x86, 0x22, 0x7a, + 0xa5, 0xed, 0x64, 0x18, 0x91, 0xf3, 0xff, 0x1b, 0xb6, 0xd2, 0x40, 0xcd, + 0x3d, 0xd6, 0x15, 0x72, 0x27, 0x5b, 0xba, 0x73, 0xcd, 0xe2, 0xdd, 0x6c, + 0xf1, 0xae, 0x2a, 0x7e, 0xab, 0x4d, 0x44, 0x06, 0x7a, 0xa3, 0x6d, 0x44, + 0x04, 0xcb, 0x1b, 0xc9, 0x62, 0x45, 0xae, 0xa1, 0xdd, 0xb4, 0x99, 0x4e, + 0xd5, 0xec, 0x6f, 0x6d, 0x41, 0x77, 0xb2, 0xc5, 0x3b, 0xd7, 0x2d, 0xdf, + 0xcd, 0x96, 0xef, 0xaa, 0xf2, 0xb7, 0xdb, 0x52, 0x72, 0xd0, 0xdb, 0x64, + 0x53, 0x49, 0x8a, 0xa5, 0x6d, 0x65, 0x33, 0xa3, 0x57, 0x33, 0x0b, 0xad, + 0x25, 0x85, 0x62, 0xb6, 0x49, 0x52, 0xe7, 0xef, 0x7a, 0x72, 0xd1, 0x2b, + 0x73, 0x4f, 0x52, 0x44, 0xb7, 0xbb, 0x3c, 0x67, 0x18, 0x2c, 0x59, 0xa3, + 0xab, 0x99, 0x35, 0x81, 0xcd, 0xba, 0x04, 0x4c, 0xb0, 0x54, 0xf6, 0x16, + 0x2b, 0x6a, 0x1d, 0x7d, 0x89, 0xe4, 0x39, 0x2f, 0xb7, 0x76, 0x51, 0x14, + 0xeb, 0x11, 0xe5, 0xde, 0xae, 0x44, 0x99, 0xe0, 0x12, 0x61, 0x5e, 0x1a, + 0xff, 0x2b, 0x53, 0xab, 0x40, 0x55, 0x68, 0xb8, 0x88, 0xf0, 0x6d, 0x2d, + 0x61, 0xab, 0x1c, 0x3d, 0x1d, 0x20, 0x29, 0x65, 0x66, 0x03, 0xae, 0x8f, + 0x28, 0xef, 0xaa, 0xbe, 0x73, 0xea, 0x83, 0xde, 0x17, 0x6e, 0x52, 0xca, + 0xc7, 0x0f, 0x15, 0xeb, 0x9e, 0xa2, 0x4a, 0x66, 0xc1, 0x37, 0x83, 0xb6, + 0xaf, 0xe8, 0x66, 0xe6, 0x05, 0x05, 0xe2, 0x5f, 0x3b, 0xad, 0xeb, 0x92, + 0xa6, 0x3b, 0x8e, 0xae, 0x41, 0xd7, 0xde, 0x97, 0xca, 0x40, 0x1a, 0x1f, + 0x37, 0xb7, 0x1f, 0x46, 0xef, 0xf1, 0x88, 0x10, 0xf6, 0x94, 0x5f, 0x8f, + 0xe3, 0x7c, 0x9e, 0xf7, 0x9a, 0x19, 0x98, 0xdc, 0x77, 0xeb, 0x73, 0x38, + 0x24, 0x6b, 0x70, 0xaa, 0xb9, 0x9a, 0x41, 0xe8, 0x64, 0x89, 0x7a, 0xb3, + 0xdf, 0xcc, 0xda, 0xed, 0xf4, 0x0f, 0x9c, 0x8b, 0xa5, 0x26, 0x6b, 0xdd, + 0x1e, 0x5d, 0xf0, 0xbb, 0xed, 0xdc, 0xfc, 0x72, 0x62, 0x56, 0x65, 0xdf, + 0xa1, 0xb3, 0x4e, 0xe8, 0xe2, 0xbe, 0xe0, 0x29, 0x23, 0x51, 0x75, 0x4a, + 0x42, 0xd6, 0x4c, 0xe9, 0xf2, 0x9b, 0x02, 0xc6, 0x8d, 0x27, 0x4e, 0x29, + 0xb4, 0x48, 0x56, 0x9b, 0x0b, 0x65, 0xd4, 0xd2, 0x72, 0x2d, 0xff, 0x9f, + 0x04, 0xc0, 0x15, 0xba, 0x96, 0x08, 0xc8, 0xc3, 0xf8, 0x7f, 0x92, 0x00, + 0xd5, 0xe7, 0x5a, 0x02, 0xf0, 0xc6, 0xe9, 0x42, 0x94, 0x15, 0x9e, 0xb0, + 0xde, 0x16, 0x1a, 0x8d, 0xfa, 0xb4, 0xa2, 0x35, 0x77, 0x23, 0xa4, 0xd1, + 0xd2, 0x46, 0x66, 0x2d, 0xa1, 0x52, 0xc9, 0xad, 0x3b, 0xac, 0xf9, 0xae, + 0x9e, 0xab, 0xd0, 0xca, 0xb7, 0x29, 0x69, 0xe4, 0xe5, 0x9e, 0x56, 0x2b, + 0x9b, 0x9b, 0x71, 0x58, 0xae, 0xc8, 0xee, 0x5c, 0x91, 0xdf, 0xb5, 0xf2, + 0xd9, 0x48, 0x69, 0xea, 0xff, 0x57, 0x8a, 0x44, 0x15, 0xba, 0x9e, 0x26, + 0x49, 0xc7, 0xe2, 0x3a, 0x32, 0xf8, 0xef, 0xa8, 0xa9, 0xe4, 0xfb, 0x5a, + 0x55, 0xc5, 0x88, 0x7f, 0xbd, 0x91, 0x63, 0x63, 0x95, 0x01, 0x67, 0x6b, + 0x0f, 0x02, 0x97, 0xf6, 0xdd, 0x39, 0x2f, 0x66, 0x73, 0xd9, 0x07, 0x5d, + 0x35, 0xa8, 0x8e, 0x04, 0xa5, 0x6f, 0x65, 0xb6, 0x7e, 0xce, 0xe8, 0xe2, + 0x9c, 0xea, 0x22, 0x82, 0xe3, 0x32, 0x0f, 0xe9, 0xa6, 0x71, 0x8a, 0x29, + 0xa5, 0x25, 0xad, 0x9a, 0x63, 0xc6, 0x5d, 0x40, 0x45, 0x6a, 0xd4, 0xfd, + 0xcd, 0xab, 0x97, 0x3f, 0x47, 0x89, 0xb7, 0xe2, 0x4f, 0x58, 0x99, 0x4a, + 0x74, 0xcd, 0x08, 0x00, 0xa7, 0xd0, 0xf9, 0xfc, 0x50, 0x4c, 0xe7, 0x87, + 0xa4, 0x74, 0x50, 0xc6, 0x76, 0xad, 0x32, 0xd3, 0x10, 0x19, 0xc3, 0x67, + 0x4e, 0x1c, 0xf1, 0x3c, 0x64, 0xdb, 0x79, 0xf0, 0xc0, 0xe1, 0x0c, 0xc2, + 0xb2, 0x88, 0xe5, 0xe4, 0xa6, 0x55, 0xfa, 0x3e, 0xb2, 0x44, 0xba, 0x02, + 0x0a, 0x4d, 0x3c, 0x0f, 0x11, 0xb5, 0x46, 0xf7, 0xd1, 0x29, 0x8e, 0x6c, + 0x52, 0x1a, 0xfa, 0x1e, 0xb0, 0x3d, 0x7c, 0x08, 0x1a, 0x69, 0x52, 0xcd, + 0x60, 0x36, 0x7f, 0xa9, 0x0c, 0x52, 0x28, 0x0b, 0xa7, 0xb1, 0x7e, 0x2b, + 0x4b, 0x56, 0x8e, 0x16, 0xc3, 0x21, 0x5c, 0xa7, 0x7b, 0x95, 0x42, 0x61, + 0xf9, 0x58, 0xc4, 0x73, 0xa5, 0x70, 0x6a, 0x16, 0xfa, 0xc3, 0xb7, 0x6f, + 0xdf, 0xbc, 0xbd, 0xe7, 0x14, 0xde, 0x71, 0x25, 0xe9, 0xe5, 0x68, 0x5d, + 0x5a, 0x6b, 0xd3, 0xd4, 0xca, 0x35, 0x6e, 0x2f, 0xbe, 0xaf, 0xa2, 0xf2, + 0xdd, 0x1b, 0xba, 0xaa, 0xca, 0x61, 0x0d, 0x48, 0xa2, 0xd4, 0x09, 0x97, + 0x9c, 0x19, 0xb0, 0xe7, 0x87, 0x65, 0x50, 0x0c, 0x40, 0x4a, 0xcb, 0x68, + 0xf3, 0xde, 0x31, 0x46, 0x01, 0xbe, 0xce, 0x36, 0x6d, 0x7b, 0xa5, 0x6d, + 0x15, 0xfa, 0xcc, 0x85, 0x46, 0x6e, 0x01, 0x98, 0x03, 0xcc, 0x70, 0xe2, + 0x54, 0x85, 0x72, 0x59, 0x77, 0x03, 0x31, 0x02, 0xd3, 0x83, 0x32, 0x6f, + 0xa3, 0x7b, 0x2e, 0x9d, 0x56, 0x19, 0x79, 0xc6, 0xb7, 0x3c, 0x20, 0x52, + 0xd1, 0xc5, 0x3b, 0xba, 0x8e, 0xde, 0xf5, 0x80, 0xab, 0x30, 0xfb, 0x16, + 0xd4, 0xfe, 0x58, 0x10, 0x5e, 0x0c, 0xe4, 0xf1, 0x14, 0x2c, 0x1d, 0xef, + 0xd6, 0x58, 0x35, 0x94, 0x50, 0x2b, 0x79, 0x9d, 0x50, 0xa8, 0xfb, 0xce, + 0x2f, 0x8e, 0xde, 0xbc, 0xa6, 0x31, 0x8c, 0xaf, 0x5a, 0x28, 0xd1, 0x33, + 0x75, 0xcc, 0x65, 0xa6, 0x76, 0x04, 0x18, 0xa9, 0xb9, 0x7f, 0x27, 0x87, + 0xb7, 0x40, 0x20, 0xbd, 0xa8, 0x01, 0x66, 0x7a, 0x96, 0x5a, 0x1b, 0xf3, + 0x97, 0xa3, 0xc6, 0x60, 0x4d, 0x6c, 0xb8, 0x72, 0x85, 0xd2, 0x07, 0x75, + 0x54, 0xcc, 0xbc, 0xc5, 0x2f, 0xf7, 0x57, 0x18, 0x03, 0x99, 0xb6, 0x3c, + 0x31, 0x77, 0xa1, 0xee, 0x77, 0x36, 0xd8, 0xea, 0x78, 0x6d, 0xa2, 0x7c, + 0x64, 0x38, 0x3d, 0x9d, 0x34, 0x7f, 0x45, 0xcd, 0x2e, 0x26, 0x5f, 0xbb, + 0x07, 0xe8, 0xf6, 0x55, 0x17, 0x7a, 0xac, 0xfd, 0x8e, 0x41, 0x1c, 0x97, + 0x1d, 0xe2, 0x01, 0x53, 0x99, 0x5c, 0xfc, 0x80, 0x9e, 0xe1, 0xc0, 0x21, + 0x92, 0x48, 0x53, 0x8c, 0xe6, 0xa2, 0xc7, 0xa3, 0x00, 0x1d, 0x6b, 0xe0, + 0x46, 0x55, 0x1b, 0x38, 0xbd, 0x61, 0xb8, 0xee, 0xa8, 0x30, 0x67, 0x9e, + 0x10, 0xb6, 0xca, 0x3a, 0x19, 0xa5, 0x15, 0x3a, 0xc0, 0x53, 0x76, 0xc4, + 0xd6, 0xea, 0x01, 0xd2, 0x67, 0xbb, 0x52, 0xfd, 0x4b, 0x95, 0x5f, 0x96, + 0xbd, 0x75, 0xc5, 0xe7, 0xeb, 0xaa, 0xd6, 0x52, 0x7d, 0x40, 0xa5, 0xa5, + 0x97, 0x74, 0x0b, 0x80, 0xa4, 0x31, 0x02, 0x4e, 0xa1, 0x6f, 0xa8, 0x2a, + 0x18, 0x88, 0x7e, 0xa6, 0xc0, 0xfe, 0x95, 0xa8, 0xd3, 0xd8, 0x81, 0xa5, + 0xa8, 0x0d, 0x44, 0x3f, 0x5b, 0x62, 0x4d, 0xe4, 0x08, 0x2a, 0x58, 0x8e, + 0xdc, 0x40, 0xf4, 0x33, 0x25, 0xd6, 0x45, 0x4e, 0xd1, 0x06, 0x4b, 0x91, + 0x1b, 0x88, 0x7e, 0xb6, 0xc4, 0x9a, 0xc8, 0x29, 0x0c, 0x61, 0x29, 0x72, + 0x03, 0xd1, 0xcf, 0x96, 0xb8, 0x1a, 0xb9, 0x8c, 0x4e, 0x40, 0xfa, 0x32, + 0xe4, 0x1a, 0xa2, 0x6f, 0xc0, 0xd7, 0x10, 0x88, 0x0a, 0x59, 0x70, 0x9c, + 0xf5, 0x2d, 0xa8, 0x22, 0x67, 0x4a, 0xf6, 0x6d, 0x4c, 0xcb, 0x8c, 0x56, + 0x71, 0x9a, 0x54, 0x88, 0x9b, 0x80, 0x1d, 0x19, 0xfa, 0x0b, 0x1a, 0xc5, + 0x2a, 0xef, 0x79, 0x6c, 0x5d, 0xc3, 0xea, 0x65, 0xab, 0xa3, 0xe2, 0x27, + 0x56, 0x48, 0x49, 0x43, 0xf4, 0x2d, 0xf0, 0xb5, 0xa4, 0xf4, 0xef, 0xf6, + 0xae, 0x85, 0xb9, 0x71, 0x1a, 0x08, 0xff, 0x15, 0x13, 0x60, 0xea, 0x70, + 0x49, 0xdb, 0xa4, 0xd7, 0x03, 0xae, 0x14, 0x06, 0xee, 0x78, 0xdc, 0x0c, + 0xaf, 0xb9, 0x3b, 0x5e, 0xd3, 0xe9, 0xdc, 0x24, 0xad, 0xdb, 0x06, 0xd2, + 0xa4, 0xd8, 0x2e, 0xd7, 0x0e, 0x94, 0xe1, 0x1f, 0xf2, 0x97, 0xf8, 0x76, + 0x25, 0x59, 0x4f, 0xdb, 0xb2, 0x69, 0x81, 0x01, 0x3a, 0x70, 0x49, 0xec, + 0xdd, 0xd5, 0x6a, 0xb5, 0x92, 0x56, 0xd2, 0x6a, 0x97, 0xbd, 0x0c, 0x6a, + 0xc9, 0x6a, 0x88, 0x7d, 0x0b, 0xe1, 0x3f, 0x31, 0x1c, 0x47, 0xae, 0x84, + 0xff, 0xd4, 0xb2, 0x95, 0x16, 0xac, 0xed, 0x36, 0x61, 0x6f, 0xf2, 0xf6, + 0xaa, 0x38, 0x7e, 0x65, 0x1c, 0xb1, 0x3a, 0x8e, 0x59, 0x21, 0x37, 0xad, + 0x92, 0xb9, 0xc6, 0xe1, 0x4d, 0x51, 0x6e, 0x3d, 0x61, 0xf7, 0x91, 0xc9, + 0x30, 0x4a, 0x38, 0xc7, 0x30, 0x0b, 0x3d, 0x60, 0xbd, 0x11, 0xe0, 0xc3, + 0x84, 0xe6, 0x41, 0x02, 0xde, 0x64, 0xfb, 0x83, 0x66, 0xc3, 0x64, 0x9c, + 0x3c, 0x79, 0x6c, 0xbc, 0x58, 0x1c, 0xcb, 0xa7, 0x9f, 0xb0, 0x50, 0x8c, + 0x37, 0x42, 0x4a, 0x43, 0xc3, 0x4f, 0x83, 0x92, 0x43, 0xef, 0x2b, 0xb1, + 0xab, 0x20, 0x95, 0x52, 0xf2, 0xe9, 0xe0, 0xf1, 0x93, 0xaf, 0x07, 0x26, + 0x74, 0x71, 0xb1, 0x6a, 0x80, 0x7e, 0xf6, 0xe5, 0xfb, 0x9f, 0x03, 0xdc, + 0x72, 0x02, 0x69, 0x00, 0x7f, 0x62, 0xc1, 0xce, 0xcb, 0x26, 0xd2, 0x1f, + 0x7c, 0xf5, 0xfc, 0xf9, 0x17, 0x36, 0xf1, 0x79, 0x27, 0xce, 0xcb, 0xab, + 0xd2, 0x87, 0xc6, 0x12, 0x88, 0x55, 0x29, 0x75, 0xe4, 0x99, 0x3a, 0xa2, + 0x1c, 0x2a, 0x52, 0x54, 0x28, 0x45, 0x08, 0xc8, 0xe0, 0xe5, 0x49, 0xfe, + 0x2c, 0x29, 0xc8, 0x1a, 0xaf, 0x6c, 0x95, 0xb4, 0x92, 0x61, 0x4b, 0x20, + 0x3c, 0xb3, 0xf0, 0x81, 0x34, 0x34, 0x5e, 0x61, 0xc4, 0x22, 0x54, 0x95, + 0x66, 0x5b, 0xbf, 0x21, 0x46, 0xf6, 0x15, 0x4b, 0xfa, 0x31, 0x47, 0x33, + 0xc3, 0xad, 0x22, 0xbc, 0xf3, 0xf6, 0xe5, 0x09, 0x38, 0x95, 0x18, 0xb4, + 0x3b, 0xaf, 0xb1, 0x2c, 0x36, 0x9d, 0x04, 0xec, 0x66, 0xa1, 0xb5, 0x9e, + 0xad, 0xd5, 0xde, 0x77, 0x75, 0x09, 0x4a, 0x22, 0xa1, 0xc1, 0x6d, 0xe2, + 0xec, 0x06, 0x44, 0xff, 0x8c, 0x39, 0x7d, 0xb9, 0x9b, 0xf0, 0x5b, 0xa3, + 0x59, 0x63, 0x5e, 0x6a, 0x28, 0x2b, 0x2f, 0xe7, 0x78, 0x19, 0x95, 0xbc, + 0x97, 0x0c, 0xf8, 0x10, 0xe1, 0xc5, 0x7c, 0x7d, 0xf5, 0x02, 0x67, 0x11, + 0xa0, 0x98, 0xc9, 0x34, 0xe8, 0xc9, 0x43, 0xe3, 0x9d, 0x41, 0xb6, 0x4e, + 0x40, 0xe5, 0xfa, 0xf4, 0x74, 0x99, 0x89, 0x4e, 0xc7, 0xcb, 0x62, 0x2d, + 0x21, 0x52, 0xf2, 0x86, 0xb1, 0x05, 0xaf, 0xed, 0x26, 0x44, 0x29, 0x95, + 0x13, 0x9c, 0xa3, 0x1d, 0x00, 0xad, 0x7b, 0x35, 0x2f, 0xcd, 0x57, 0x56, + 0x79, 0x3a, 0x9b, 0x7e, 0x52, 0x9c, 0x3f, 0x48, 0xce, 0x8f, 0xef, 0x27, + 0x4b, 0x9c, 0xd9, 0x5f, 0x2d, 0xa7, 0xa4, 0x96, 0x69, 0xbd, 0x70, 0x12, + 0xf1, 0x90, 0x85, 0x31, 0x68, 0x75, 0xcc, 0x13, 0x0b, 0xc8, 0xa1, 0xc5, + 0x15, 0x58, 0x71, 0x47, 0xa8, 0x3c, 0xd3, 0xf9, 0x4f, 0x84, 0x69, 0xde, + 0x6f, 0x1e, 0x1b, 0xec, 0xec, 0xbc, 0x3e, 0xd8, 0x8b, 0xc6, 0x1e, 0x1f, + 0xaf, 0x57, 0x44, 0x02, 0xaa, 0xf6, 0x7e, 0x09, 0x13, 0x1c, 0x3d, 0x22, + 0xe3, 0x20, 0x09, 0xeb, 0x1f, 0xf0, 0x6e, 0x56, 0x9c, 0xcd, 0xf2, 0x9c, + 0x22, 0x44, 0x10, 0xdd, 0xd1, 0x64, 0x7b, 0x3b, 0xaa, 0xbe, 0xd0, 0x3b, + 0xd9, 0x1f, 0x1b, 0x26, 0x59, 0x33, 0xe1, 0xcb, 0x5e, 0xeb, 0x42, 0xe4, + 0x72, 0xc1, 0x7b, 0x38, 0x88, 0xad, 0xbc, 0x5e, 0xb5, 0x2e, 0x47, 0x9c, + 0xf1, 0xdc, 0x16, 0xad, 0xbb, 0x0c, 0x29, 0xcf, 0x2f, 0xf4, 0xb5, 0xc7, + 0xb8, 0x15, 0xc9, 0x7b, 0xf6, 0xd2, 0x03, 0x7a, 0xf0, 0xf3, 0x8d, 0xbd, + 0x9d, 0xf6, 0x54, 0x78, 0xb4, 0x55, 0xc9, 0xd0, 0xab, 0x12, 0x5e, 0x2e, + 0xca, 0x33, 0x11, 0xc4, 0x3e, 0x81, 0xe0, 0x0b, 0x8d, 0x74, 0x82, 0x1e, + 0x9f, 0xca, 0x3b, 0x98, 0x98, 0x9e, 0x2a, 0x8c, 0x61, 0x68, 0x2b, 0xe6, + 0x15, 0xf5, 0xd6, 0x8d, 0xb3, 0x8c, 0xe7, 0x43, 0x36, 0xb5, 0xf0, 0xf6, + 0x32, 0xab, 0xdd, 0x0e, 0x48, 0x8d, 0x4a, 0xd3, 0x09, 0xdb, 0xe1, 0xd0, + 0xb7, 0xd7, 0xac, 0xf7, 0x90, 0x8c, 0x8b, 0x12, 0x36, 0x6f, 0x38, 0xac, + 0x4b, 0x25, 0xec, 0x3e, 0xcb, 0x3d, 0xb9, 0x69, 0xa4, 0x13, 0xa0, 0xd2, + 0xcc, 0x61, 0x93, 0x62, 0xab, 0x46, 0x35, 0x31, 0x65, 0xae, 0x91, 0x7b, + 0x4f, 0xc9, 0xd2, 0x49, 0x2f, 0xae, 0xdb, 0xda, 0xb7, 0x09, 0x5c, 0x56, + 0xb5, 0x31, 0x90, 0x7c, 0xa6, 0x8e, 0x97, 0x75, 0xba, 0x7a, 0x99, 0xd9, + 0xbf, 0x48, 0xe8, 0x4a, 0x10, 0x86, 0x63, 0x91, 0xf7, 0x3e, 0x39, 0xc9, + 0xd7, 0xe7, 0x2a, 0xcd, 0xbd, 0x99, 0x21, 0x7f, 0x53, 0x6f, 0x6e, 0x59, + 0x07, 0x98, 0xa2, 0xae, 0x18, 0x3b, 0x50, 0x9c, 0xdf, 0xf6, 0x4c, 0x14, + 0x8d, 0x6f, 0xf6, 0x93, 0x70, 0xfb, 0x1b, 0x00, 0xae, 0x0a, 0x10, 0x0d, + 0x5f, 0x07, 0xc2, 0x5d, 0x83, 0x61, 0x6b, 0xb5, 0xa4, 0xf6, 0x10, 0x96, + 0xd0, 0xa0, 0x32, 0xfb, 0xae, 0xca, 0x34, 0xc2, 0xdb, 0xdd, 0x9f, 0x9f, + 0xb9, 0x3a, 0xa4, 0x3f, 0x94, 0x28, 0xb3, 0xb4, 0x1a, 0x67, 0xe6, 0xeb, + 0xe3, 0x6b, 0x77, 0xf0, 0x91, 0xb6, 0xc4, 0x7e, 0x5d, 0xc9, 0xe2, 0x3d, + 0x90, 0x2a, 0xbb, 0xd1, 0xde, 0xd5, 0xa2, 0x5f, 0xce, 0xae, 0x96, 0x35, + 0xea, 0xf3, 0x38, 0xa3, 0xf0, 0xbd, 0x06, 0xd5, 0x97, 0x8f, 0x37, 0xd9, + 0x9e, 0xfc, 0xe2, 0xa4, 0xb2, 0x03, 0xb0, 0xd5, 0x35, 0x9e, 0xe8, 0xa6, + 0x0b, 0xd2, 0x2e, 0xf3, 0x40, 0xeb, 0xf0, 0x26, 0xeb, 0x6b, 0x28, 0x22, + 0xe5, 0x6f, 0xcc, 0xae, 0x34, 0x57, 0x47, 0x8c, 0x1f, 0x5e, 0x56, 0xd8, + 0x06, 0xae, 0xad, 0xf3, 0x7e, 0xb3, 0x6b, 0x49, 0x38, 0x7d, 0x82, 0x47, + 0x26, 0xbf, 0x4b, 0x90, 0x6a, 0x42, 0x64, 0xe7, 0x8f, 0x81, 0x27, 0xf7, + 0xdc, 0x3f, 0x92, 0x3f, 0x53, 0xcb, 0x54, 0x5c, 0xae, 0xe7, 0xf2, 0xfd, + 0x07, 0xf8, 0x9a, 0x1e, 0xf0, 0x30, 0x29, 0xba, 0xfa, 0xe2, 0xe4, 0xba, + 0x92, 0xdc, 0xf0, 0x70, 0x94, 0xfc, 0x2c, 0xae, 0x67, 0x6f, 0x50, 0x2f, + 0x5c, 0x88, 0x5b, 0xf0, 0x5b, 0x34, 0xb8, 0x6f, 0x28, 0x9e, 0xab, 0x12, + 0xe5, 0xcc, 0x99, 0x6e, 0x28, 0xf4, 0x8d, 0x11, 0x97, 0x34, 0x4a, 0x36, + 0xac, 0x69, 0x81, 0xcf, 0xdb, 0x83, 0x06, 0x3d, 0xb9, 0x64, 0x88, 0xe4, + 0x56, 0xa3, 0x8a, 0xea, 0xb0, 0x7d, 0xce, 0xc9, 0x30, 0x02, 0x19, 0x18, + 0xce, 0x74, 0xd3, 0x7d, 0x64, 0x73, 0xb4, 0xc1, 0x66, 0xf1, 0xab, 0x47, + 0x8f, 0x3e, 0x7c, 0xf6, 0xcc, 0x69, 0x00, 0x1a, 0xbf, 0x46, 0x7a, 0x2a, + 0x88, 0x59, 0x92, 0xba, 0x3d, 0x80, 0xe7, 0x1a, 0x4c, 0xdf, 0x85, 0xd8, + 0xfb, 0x07, 0xc5, 0x1d, 0xb5, 0x38, 0xd5, 0x7f, 0x31, 0x83, 0x6e, 0xd5, + 0x85, 0x20, 0x16, 0x61, 0xf5, 0xaa, 0xfe, 0xd1, 0xba, 0xe2, 0xb4, 0x17, + 0xeb, 0x42, 0x20, 0x81, 0x9a, 0xf6, 0xaf, 0x5f, 0xe4, 0xfa, 0xdb, 0x9d, + 0x02, 0x6c, 0xf3, 0x34, 0x13, 0x0e, 0x32, 0x7e, 0x47, 0x7d, 0xc5, 0xf8, + 0x59, 0x9d, 0x44, 0xd4, 0x1a, 0xd2, 0xdd, 0xed, 0x67, 0xea, 0x3a, 0x17, + 0x6b, 0xb2, 0x3e, 0x62, 0x86, 0x16, 0xe3, 0xdc, 0xc4, 0x64, 0x0c, 0xfa, + 0x47, 0x44, 0xbc, 0x81, 0x27, 0x48, 0xb3, 0xa0, 0x3e, 0x97, 0xa5, 0x80, + 0x1f, 0x25, 0x13, 0xdb, 0x6f, 0x9f, 0x09, 0xfb, 0x74, 0x69, 0xb0, 0x8f, + 0xa1, 0x4c, 0x7b, 0xf6, 0x2e, 0xab, 0x37, 0xc1, 0x4e, 0x29, 0x16, 0xcd, + 0xbc, 0x8f, 0x5f, 0xf0, 0xd2, 0x39, 0x44, 0x4f, 0x36, 0x98, 0xd7, 0x64, + 0x2a, 0xed, 0x51, 0x2a, 0xce, 0xe4, 0xac, 0x91, 0x4a, 0xc5, 0x1d, 0xdf, + 0x4f, 0xe4, 0x5b, 0x6e, 0x11, 0x7c, 0xcd, 0x4b, 0x96, 0x7f, 0x01, 0x54, + 0x25, 0x7a, 0x6c, 0x3f, 0xf1, 0x51, 0x91, 0xc4, 0xb1, 0x84, 0x2b, 0x90, + 0xe3, 0x7c, 0x14, 0x66, 0x92, 0x1f, 0xd8, 0xbb, 0xdc, 0xbc, 0xd9, 0xb1, + 0xea, 0x1c, 0x31, 0x57, 0x0c, 0x15, 0xf6, 0xfc, 0x94, 0xb7, 0x35, 0xea, + 0xef, 0x3a, 0xea, 0xed, 0x1d, 0x93, 0xf9, 0xc1, 0x6b, 0x83, 0x1e, 0xd7, + 0x5f, 0x7d, 0x96, 0xbd, 0x39, 0x49, 0x4f, 0x99, 0x54, 0xf4, 0x64, 0x70, + 0xbb, 0x75, 0xa9, 0x5d, 0xdd, 0xea, 0x4c, 0x5a, 0x2f, 0x44, 0xbe, 0xd4, + 0x17, 0x62, 0x9d, 0x8e, 0xe1, 0xc8, 0xcc, 0xc3, 0x64, 0x6a, 0xc5, 0x7a, + 0xf5, 0x4c, 0xe5, 0x15, 0xc3, 0xb1, 0x74, 0x8a, 0xa2, 0xe1, 0xe7, 0x55, + 0x35, 0x9d, 0xeb, 0x5d, 0x9a, 0x88, 0xf7, 0x20, 0xe1, 0x8d, 0xc3, 0xa2, + 0x5c, 0xc8, 0x82, 0xc1, 0x1f, 0x42, 0x2d, 0x25, 0xb0, 0x9e, 0x49, 0x13, + 0xce, 0xf4, 0x6f, 0x03, 0x4a, 0x3f, 0x44, 0xe3, 0x74, 0x1a, 0xa5, 0x04, + 0x64, 0x54, 0x7c, 0x70, 0xfd, 0x48, 0x2d, 0x41, 0xd3, 0x81, 0x60, 0x89, + 0x03, 0x94, 0xc0, 0xa7, 0xed, 0x14, 0x6d, 0xa9, 0x1a, 0x52, 0x9b, 0x84, + 0x0b, 0xde, 0xe1, 0xc2, 0xc7, 0x3b, 0xc9, 0x95, 0x3c, 0x47, 0xc3, 0xaf, + 0x7b, 0xf7, 0x2c, 0xbd, 0xbc, 0x3a, 0x58, 0x1c, 0x9a, 0x6b, 0x5b, 0x7e, + 0x10, 0xbe, 0x60, 0xa3, 0xb7, 0x21, 0xde, 0x96, 0x97, 0x6c, 0xf4, 0x93, + 0x9d, 0x81, 0xd3, 0x65, 0x51, 0x8b, 0xf6, 0xbb, 0xb9, 0xbe, 0x8c, 0xae, + 0x6c, 0x5e, 0xda, 0x18, 0xd9, 0xf1, 0x18, 0x79, 0x7b, 0x60, 0x8a, 0x3b, + 0x93, 0xf1, 0x0a, 0x44, 0x5e, 0xb5, 0x64, 0xb6, 0x3a, 0xae, 0x1c, 0xf5, + 0xca, 0xb5, 0xd3, 0x10, 0xc0, 0x72, 0xae, 0x7e, 0xe8, 0xc6, 0x3f, 0x18, + 0xe4, 0xc4, 0xab, 0xd4, 0x0e, 0x8c, 0x94, 0x13, 0x0c, 0x0c, 0xf2, 0x07, + 0x2f, 0xe5, 0x0f, 0xcd, 0xcb, 0x10, 0x41, 0x02, 0xa7, 0x71, 0x04, 0xe6, + 0xc0, 0x0c, 0xe2, 0xcf, 0xe3, 0xf0, 0x69, 0x2f, 0x35, 0x4c, 0xe0, 0x65, + 0x1c, 0x81, 0xa0, 0xcf, 0x4b, 0xb3, 0x8b, 0x88, 0xef, 0x1e, 0x72, 0xe3, + 0x5c, 0xfd, 0x0b, 0xae, 0x95, 0x60, 0x32, 0x54, 0xd6, 0x37, 0xb7, 0x87, + 0xfa, 0x21, 0x1b, 0x46, 0x77, 0x09, 0x7a, 0xd1, 0xa4, 0x4f, 0x0a, 0xd1, + 0xeb, 0x03, 0xec, 0x26, 0x62, 0x2e, 0x8b, 0xb8, 0xfc, 0xe0, 0x7a, 0xc8, + 0x5d, 0x0c, 0x11, 0x66, 0x78, 0x31, 0x44, 0x74, 0x39, 0x6c, 0x62, 0xd3, + 0x76, 0x28, 0x52, 0x1a, 0x3e, 0xd1, 0xdb, 0xa1, 0xf4, 0x27, 0x71, 0x9c, + 0xfd, 0x12, 0x6e, 0xa9, 0xc1, 0x88, 0x19, 0xf5, 0x81, 0x83, 0x5b, 0x20, + 0x07, 0x04, 0x7b, 0xb8, 0x59, 0xe5, 0x36, 0xd6, 0x58, 0x0c, 0x62, 0x6d, + 0x17, 0x09, 0x32, 0x66, 0xdf, 0x54, 0x50, 0x4a, 0x45, 0x2c, 0xa3, 0x68, + 0x4f, 0x03, 0x74, 0x72, 0xab, 0x3e, 0x46, 0x67, 0x5a, 0x9f, 0x67, 0xe5, + 0x19, 0x28, 0x25, 0x67, 0x59, 0x9e, 0xc9, 0xf2, 0x4c, 0x13, 0x5f, 0x1f, + 0x85, 0xc6, 0x5c, 0xc7, 0x96, 0x88, 0xea, 0x41, 0xe3, 0xed, 0x6c, 0x0d, + 0xd6, 0x81, 0x69, 0xef, 0x80, 0x56, 0x13, 0xf1, 0x5d, 0xb3, 0xab, 0xf9, + 0xf2, 0xd1, 0x19, 0x7a, 0x91, 0x8b, 0x6b, 0xb6, 0x9b, 0x86, 0x44, 0x1d, + 0x02, 0x52, 0x30, 0x4e, 0x6d, 0xa3, 0xee, 0x94, 0x0b, 0x54, 0x8d, 0xd6, + 0x78, 0xc7, 0xdc, 0x04, 0xec, 0x2e, 0x0a, 0x83, 0x35, 0xb7, 0xbc, 0x60, + 0x05, 0xcf, 0x49, 0x16, 0x1e, 0x72, 0x67, 0x61, 0xe0, 0x54, 0xb9, 0x5d, + 0x18, 0x04, 0xa4, 0x68, 0x68, 0xb4, 0xe6, 0xcb, 0xf2, 0x1a, 0xb0, 0xaf, + 0x30, 0x24, 0x6b, 0xea, 0x7b, 0xa3, 0x30, 0x2e, 0x20, 0x0c, 0x17, 0xb9, + 0xbb, 0x30, 0xe8, 0x14, 0xbc, 0x55, 0x18, 0x04, 0xa4, 0x68, 0x68, 0xb4, + 0xc6, 0x5b, 0xff, 0x26, 0x60, 0x4f, 0x61, 0x08, 0xd6, 0x34, 0x99, 0x26, + 0x61, 0x5c, 0x42, 0x18, 0x1e, 0x72, 0x67, 0x61, 0xd0, 0xa9, 0x7d, 0xab, + 0x30, 0x08, 0x48, 0xd1, 0xd0, 0x68, 0x8d, 0xe1, 0x0b, 0x4c, 0xc0, 0x9e, + 0xc2, 0x10, 0xac, 0x69, 0x32, 0x4d, 0xc2, 0xa0, 0x89, 0xd7, 0x43, 0xee, + 0x22, 0x0c, 0x0e, 0xa6, 0x80, 0xd2, 0xe2, 0x62, 0x2e, 0x48, 0x44, 0xfe, + 0xd5, 0x14, 0x7f, 0x81, 0x21, 0x7a, 0xf4, 0x0c, 0xe5, 0x03, 0x21, 0xf0, + 0x1b, 0x2a, 0x5e, 0x1c, 0xa1, 0xe2, 0x16, 0x56, 0xa7, 0xfe, 0x00, 0xaf, + 0x81, 0xf6, 0x3a, 0x03, 0x48, 0x61, 0x13, 0x42, 0x38, 0xd6, 0x83, 0x7e, + 0xdf, 0xab, 0xb6, 0x82, 0x11, 0xfc, 0xdb, 0x54, 0x57, 0xd5, 0xfd, 0x35, + 0x4e, 0x97, 0xba, 0x92, 0x6b, 0x46, 0x7b, 0x65, 0x09, 0xaa, 0xde, 0xc4, + 0xd1, 0x30, 0x30, 0x72, 0xfe, 0x7e, 0x6b, 0x45, 0xb3, 0x23, 0xec, 0x15, + 0x03, 0x9a, 0x1e, 0xb6, 0x5b, 0x29, 0x04, 0xd5, 0x18, 0xfd, 0x83, 0x21, + 0x7a, 0xb5, 0xa8, 0x14, 0x37, 0x7d, 0x34, 0xb5, 0x29, 0xd9, 0xfc, 0x0e, + 0x56, 0x97, 0x46, 0x15, 0xc1, 0x43, 0xda, 0x9b, 0x55, 0xc0, 0x35, 0x35, + 0xac, 0x86, 0xfa, 0x07, 0x35, 0xad, 0x60, 0xc8, 0x6b, 0x5c, 0xf1, 0xb8, + 0xbd, 0x79, 0x05, 0x5c, 0x64, 0x60, 0x15, 0x01, 0xdc, 0xab, 0xad, 0xa5, + 0xcb, 0x90, 0x5d, 0xde, 0x2f, 0x89, 0x8c, 0xc5, 0xa2, 0x7f, 0xcb, 0x60, + 0x2a, 0xfa, 0x81, 0x88, 0x87, 0xd2, 0xa4, 0x1f, 0x6b, 0xe8, 0x87, 0x53, + 0x52, 0xa7, 0x11, 0x4e, 0xf2, 0x10, 0xa5, 0x21, 0x04, 0x18, 0xa1, 0x22, + 0x04, 0xf6, 0xcf, 0xd2, 0x11, 0xe2, 0xc8, 0x53, 0x12, 0xf9, 0x3c, 0x4a, + 0x4b, 0x08, 0x30, 0x32, 0x60, 0x8e, 0x80, 0xee, 0xb1, 0x0a, 0xf8, 0xc7, + 0xeb, 0x09, 0x97, 0x19, 0xa5, 0x28, 0x0c, 0x19, 0xa1, 0x29, 0x0c, 0xf7, + 0xcf, 0x52, 0x15, 0x66, 0xc9, 0xd3, 0x15, 0xf5, 0x22, 0x4a, 0x59, 0x18, + 0x32, 0x2a, 0x1c, 0x92, 0x02, 0xfe, 0x17, 0x2a, 0x0b, 0x8a, 0x88, 0x1b, + 0x54, 0x00, 0x18, 0x33, 0xa8, 0x00, 0xec, 0x1f, 0x36, 0xa8, 0x10, 0x47, + 0xbe, 0xa2, 0xf0, 0xf3, 0xb8, 0x41, 0x85, 0x00, 0x9b, 0x03, 0x5d, 0x99, + 0xa0, 0xff, 0xaa, 0x11, 0x85, 0x63, 0x56, 0x73, 0xc8, 0x6a, 0x7f, 0x0f, + 0xc8, 0x88, 0x67, 0xdd, 0x6f, 0x2b, 0xc8, 0x76, 0x59, 0xd8, 0x17, 0xe8, + 0xa2, 0x11, 0x8a, 0x03, 0xfe, 0xa1, 0x36, 0x5d, 0x9f, 0xd0, 0xe1, 0xd4, + 0xa1, 0x60, 0x21, 0x6c, 0xfe, 0x1f, 0xfd, 0xd0, 0xbc, 0x16, 0x16, 0x10, + 0x7c, 0x46, 0xa0, 0x6a, 0x29, 0xb1, 0xf4, 0xb1, 0x84, 0x71, 0xe6, 0x6e, + 0xc4, 0xf6, 0x16, 0xfe, 0x07, 0x47, 0x8b, 0xfc, 0xc8, 0x40, 0xcd, 0xb3, + 0xe3, 0x7c, 0xf6, 0xd2, 0xd8, 0x2e, 0xc6, 0x4e, 0x26, 0x3b, 0xe4, 0xf0, + 0x73, 0xb1, 0xc9, 0x29, 0x99, 0x2a, 0xd7, 0xd2, 0x11, 0x47, 0x11, 0xd7, + 0x85, 0x77, 0x5a, 0x5e, 0x07, 0x79, 0x03, 0xcf, 0x76, 0x2d, 0x70, 0x08, + 0x55, 0x31, 0x9b, 0x54, 0x61, 0xc9, 0x25, 0xd7, 0x75, 0x9c, 0xfb, 0x12, + 0xa5, 0xd2, 0xd4, 0x11, 0x4b, 0xf3, 0xe8, 0x50, 0x8e, 0x15, 0x9c, 0x12, + 0x8e, 0x89, 0xab, 0x85, 0xab, 0xf9, 0x57, 0xef, 0xcc, 0x43, 0x30, 0x1f, + 0x05, 0x35, 0x51, 0x4f, 0x0c, 0x2f, 0x61, 0xf3, 0x2b, 0x37, 0xa6, 0x71, + 0x88, 0xe7, 0xfb, 0xf6, 0x19, 0x54, 0xfb, 0x08, 0x5a, 0x0b, 0x20, 0x54, + 0x25, 0x67, 0x93, 0x57, 0x00, 0xb6, 0x1f, 0x58, 0x0d, 0x86, 0xc1, 0xea, + 0x78, 0xde, 0x1f, 0x7e, 0x81, 0xde, 0xc9, 0x3e, 0xbd, 0x0c, 0x4a, 0x81, + 0x7f, 0x41, 0x01, 0x62, 0xbd, 0xd5, 0x51, 0xd8, 0x2d, 0x9d, 0xa7, 0x89, + 0x83, 0xc1, 0x68, 0x46, 0x45, 0x73, 0xdd, 0x0d, 0x9f, 0xb6, 0x8b, 0x7a, + 0x70, 0xa7, 0x64, 0x79, 0x3e, 0x5b, 0xac, 0x5a, 0xcf, 0x9e, 0xc6, 0x04, + 0xa5, 0x94, 0x5b, 0x61, 0xf9, 0xc3, 0xa1, 0x91, 0x95, 0xc0, 0x04, 0xed, + 0xb4, 0x8f, 0x10, 0x22, 0x86, 0x32, 0xac, 0x32, 0x1d, 0xbd, 0x3b, 0xcb, + 0xae, 0x18, 0xac, 0x89, 0x15, 0x0d, 0x7d, 0xbd, 0xf8, 0x91, 0xc6, 0x8c, + 0x94, 0x7d, 0x0a, 0x9f, 0x60, 0xe6, 0x55, 0xe8, 0xd2, 0xa5, 0x24, 0x9d, + 0x8c, 0xa6, 0xc3, 0xd1, 0xe4, 0xc1, 0xf0, 0x8d, 0xe9, 0xdb, 0x6f, 0x0f, + 0xef, 0xd5, 0xc3, 0xed, 0x28, 0xb8, 0xdd, 0xb7, 0xde, 0x6c, 0x82, 0xdb, + 0x55, 0x70, 0x93, 0xc9, 0xfd, 0xe1, 0x70, 0x6b, 0x02, 0x8f, 0x89, 0x98, + 0xe3, 0xdd, 0x72, 0xbd, 0x5e, 0xce, 0x67, 0x1d, 0xd4, 0x90, 0x0b, 0x8d, + 0xa1, 0x7c, 0xb2, 0x5e, 0x97, 0xd9, 0x5d, 0x10, 0x76, 0x59, 0x56, 0xad, + 0x92, 0x42, 0xe6, 0x1c, 0x09, 0x71, 0xba, 0x4b, 0x83, 0xf3, 0xc6, 0xab, + 0x93, 0xc9, 0x64, 0x23, 0x79, 0x88, 0x2f, 0x1f, 0x7e, 0xf8, 0xe1, 0x46, + 0x0c, 0x65, 0x66, 0xf9, 0xee, 0x08, 0xb3, 0x2b, 0x77, 0x3f, 0xea, 0x6e, + 0x7f, 0xa2, 0x7c, 0x1d, 0xed, 0xfd, 0x89, 0xa0, 0xcc, 0xfe, 0x44, 0xbf, + 0xeb, 0xfa, 0x13, 0xbd, 0x33, 0x21, 0x3b, 0x6d, 0x42, 0x06, 0x68, 0xa1, + 0x04, 0xb3, 0xc4, 0x28, 0xbf, 0x09, 0x76, 0x61, 0x73, 0x05, 0x14, 0x22, + 0x5e, 0x23, 0x15, 0xd2, 0xb1, 0x76, 0xa9, 0x10, 0x94, 0x29, 0x15, 0xfa, + 0x5d, 0x27, 0x15, 0x7a, 0x67, 0x43, 0xf6, 0x97, 0x8a, 0xe0, 0x4e, 0xd1, + 0x89, 0x97, 0x8a, 0x74, 0x55, 0xed, 0xd2, 0x97, 0x08, 0x20, 0x86, 0xb4, + 0x3a, 0xbc, 0xbc, 0x7d, 0xca, 0x7a, 0xa3, 0xf1, 0xae, 0x68, 0x0b, 0x03, + 0xfe, 0x0e, 0xa9, 0x63, 0x3d, 0x70, 0x67, 0x82, 0x51, 0xcb, 0x8b, 0x3b, + 0xa4, 0x8f, 0xd5, 0x4a, 0x7f, 0xf6, 0xa5, 0x9b, 0x46, 0x99, 0x5d, 0x95, + 0x5b, 0x7c, 0x17, 0x45, 0x74, 0xc6, 0xe3, 0xec, 0x42, 0xb8, 0x5e, 0x26, + 0x78, 0xa4, 0x69, 0x26, 0x14, 0xe2, 0x95, 0x62, 0x83, 0xc5, 0xce, 0x98, + 0x84, 0xfa, 0xcf, 0x9e, 0x30, 0x55, 0x2c, 0xde, 0x22, 0xc6, 0xef, 0xa7, + 0xba, 0xa8, 0xa3, 0xc7, 0x95, 0x3a, 0x9f, 0x1f, 0xa6, 0xe9, 0xfb, 0xfd, + 0xe8, 0x3f, 0x01, 0x01, 0x77, 0x9f, 0xb6, 0x69, 0x62, 0x3a, 0x9d, 0x06, + 0x27, 0xa1, 0x9b, 0x08, 0x25, 0x51, 0xc6, 0x1d, 0x02, 0x0c, 0xf7, 0x9b, + 0x8f, 0x1a, 0xa9, 0x8b, 0x80, 0x52, 0x77, 0x40, 0x98, 0xfd, 0x78, 0xee, + 0x86, 0x34, 0x79, 0xf8, 0xdc, 0x0d, 0x65, 0xf2, 0xfd, 0xb9, 0x23, 0xd2, + 0x22, 0x06, 0xcd, 0xdd, 0xd0, 0x2e, 0x2e, 0xb2, 0xbb, 0x6a, 0x46, 0x35, + 0x18, 0xf4, 0x23, 0xed, 0x4d, 0xfa, 0x65, 0xc4, 0xca, 0x02, 0x40, 0xd6, + 0x94, 0x5f, 0xd6, 0xae, 0x2b, 0xf0, 0xca, 0x84, 0xfb, 0x13, 0x8b, 0x0a, + 0x66, 0x4c, 0x52, 0x89, 0x9f, 0xed, 0x15, 0x91, 0x31, 0xf6, 0x32, 0xba, + 0x8c, 0xdf, 0xe5, 0x2a, 0x86, 0xba, 0xd8, 0xc3, 0x68, 0x5f, 0xd3, 0xf9, + 0xd4, 0x63, 0x96, 0xcd, 0xb7, 0xb3, 0x9e, 0x6c, 0x2d, 0xbb, 0x75, 0x58, + 0x1b, 0x0c, 0x23, 0x78, 0xba, 0x25, 0x86, 0x9a, 0x1d, 0x5b, 0x7d, 0x5d, + 0x2d, 0xa2, 0x94, 0x15, 0x54, 0x1d, 0x7d, 0x2d, 0x1a, 0x14, 0x16, 0xd0, + 0x16, 0x6c, 0x17, 0xff, 0x89, 0x20, 0x35, 0x94, 0x62, 0x95, 0xda, 0xb9, + 0xbe, 0xd2, 0x7e, 0xe0, 0xdc, 0x68, 0x27, 0xb3, 0xa3, 0x4c, 0x86, 0x74, + 0xef, 0x12, 0x65, 0x51, 0xae, 0xc5, 0xeb, 0xe3, 0x51, 0xe9, 0x85, 0x4a, + 0x33, 0x08, 0x35, 0x68, 0x1b, 0x48, 0xb9, 0x6a, 0x87, 0x28, 0xea, 0x40, + 0x5a, 0x33, 0x39, 0xc8, 0x1e, 0x2d, 0x52, 0xae, 0x06, 0xda, 0x86, 0xaf, + 0xda, 0xaa, 0xa6, 0xb9, 0x5d, 0x1b, 0x44, 0xdd, 0x40, 0xdc, 0x6f, 0xe7, + 0xcf, 0xc3, 0x9b, 0xe5, 0x52, 0xfb, 0xb5, 0xc3, 0x2f, 0xdf, 0x34, 0xc0, + 0x31, 0x42, 0x32, 0x70, 0xaf, 0x02, 0x02, 0xb8, 0xba, 0xda, 0xa0, 0xb6, + 0x9b, 0x86, 0xfe, 0x2d, 0x03, 0xfe, 0xb3, 0x69, 0x26, 0xf7, 0xf6, 0xf5, + 0x1d, 0x5c, 0xef, 0x02, 0x15, 0xbd, 0xc8, 0x44, 0x10, 0x54, 0x5c, 0xb1, + 0xc8, 0x0a, 0x76, 0x17, 0x56, 0xa9, 0xf4, 0x12, 0xa1, 0x7f, 0xd0, 0xab, + 0x9a, 0x90, 0x43, 0xe7, 0xb3, 0x0b, 0xef, 0x52, 0x98, 0xfe, 0x73, 0xef, + 0x46, 0x54, 0x7c, 0xc6, 0x86, 0x57, 0x90, 0x17, 0x23, 0xcc, 0x9d, 0xc6, + 0xb8, 0x7a, 0x39, 0x86, 0x9a, 0xd5, 0x77, 0xfe, 0x9c, 0xf9, 0x68, 0x9a, + 0x90, 0xf5, 0x6c, 0x49, 0xae, 0xba, 0x46, 0xe9, 0xb0, 0xdb, 0x8d, 0x75, + 0x23, 0xec, 0x0c, 0x2e, 0xab, 0x2d, 0x1d, 0xc1, 0x07, 0x43, 0xaf, 0x59, + 0xf9, 0x32, 0x90, 0xdb, 0xac, 0xb3, 0xe5, 0xf2, 0xaf, 0x6a, 0x51, 0x92, + 0xab, 0x90, 0x4e, 0xb2, 0xdf, 0xa5, 0x79, 0xf7, 0xc2, 0xe4, 0x18, 0xc0, + 0x96, 0x0d, 0x3f, 0xea, 0x27, 0x9e, 0xbf, 0x53, 0x3b, 0xf6, 0x9b, 0xdf, + 0x9b, 0xb5, 0x68, 0xae, 0xc4, 0x8d, 0xbf, 0x29, 0xdc, 0x7a, 0xd7, 0xdc, + 0x32, 0x7e, 0xba, 0x0c, 0x95, 0xa1, 0xb3, 0xb2, 0xa6, 0x31, 0x4f, 0x1f, + 0xb7, 0xa1, 0x14, 0x67, 0x8a, 0x73, 0x6e, 0xb2, 0xdd, 0xf2, 0xa2, 0x30, + 0x4e, 0x95, 0x63, 0xd4, 0xb8, 0x83, 0xd6, 0xc6, 0x0d, 0x4a, 0x66, 0x8b, + 0xdd, 0xe2, 0x3a, 0xb6, 0x0b, 0x1b, 0x06, 0x0b, 0xfa, 0x5b, 0x84, 0x5d, + 0xab, 0xe7, 0xb0, 0xe6, 0x32, 0x6e, 0xbc, 0x0b, 0x68, 0xf6, 0xad, 0xc4, + 0xf3, 0xe2, 0x94, 0xc2, 0xea, 0x5f, 0x8f, 0x12, 0x4a, 0xfb, 0x8c, 0x3a, + 0xb5, 0xde, 0x00, 0x92, 0xe5, 0x4b, 0x02, 0x55, 0x53, 0x5f, 0x59, 0x47, + 0xe4, 0x20, 0xab, 0x9e, 0xd7, 0x5a, 0x99, 0x29, 0x8a, 0xa5, 0xf9, 0x52, + 0xdd, 0x7a, 0xe4, 0x03, 0xc6, 0x57, 0x67, 0xc7, 0xd3, 0x37, 0xa7, 0x6f, + 0xf2, 0x09, 0xe3, 0xab, 0xf7, 0x8f, 0x66, 0x27, 0xbb, 0xdb, 0x03, 0x6d, + 0x62, 0xbd, 0xbf, 0x5a, 0x9c, 0xcf, 0xb8, 0x12, 0x8b, 0x82, 0x19, 0x3e, + 0x16, 0xf1, 0x08, 0x58, 0x04, 0xec, 0x3f, 0x9f, 0xd2, 0xe5, 0x50, 0x71, + 0x7f, 0x32, 0x41, 0x29, 0x13, 0xfa, 0x32, 0x0c, 0x5d, 0xea, 0x19, 0x40, + 0x0c, 0xe4, 0x12, 0xcb, 0x64, 0x64, 0x09, 0xe1, 0x24, 0xfe, 0x11, 0xb7, + 0x81, 0x2c, 0x62, 0x62, 0x6c, 0x48, 0x6e, 0xa4, 0x48, 0x75, 0x04, 0xd1, + 0xe4, 0x9b, 0x6c, 0xfe, 0x6c, 0x0d, 0x2b, 0xbd, 0x64, 0x2f, 0x03, 0x8e, + 0x1a, 0xba, 0xcc, 0x38, 0xb9, 0xb5, 0x3c, 0x9b, 0x06, 0xf9, 0x9f, 0xdd, + 0x14, 0xbf, 0x92, 0xa3, 0x87, 0xc9, 0x84, 0x6a, 0x26, 0xde, 0x9e, 0xcf, + 0xae, 0x9e, 0x66, 0x65, 0xbe, 0xa0, 0xac, 0xc0, 0x53, 0xf9, 0x2c, 0xcf, + 0x34, 0xce, 0xe3, 0x0c, 0x76, 0xfe, 0xc7, 0xf9, 0xfa, 0xe5, 0x47, 0x33, + 0x4a, 0x5a, 0xab, 0x81, 0x38, 0x4f, 0xba, 0x48, 0xd5, 0x4b, 0x57, 0xd0, + 0xec, 0xbc, 0xa1, 0xea, 0x0e, 0xed, 0x72, 0xe9, 0x5e, 0xa3, 0x35, 0xef, + 0xcb, 0x70, 0xce, 0xf3, 0xe4, 0x62, 0x5d, 0x42, 0x17, 0x16, 0x98, 0xc0, + 0xae, 0x39, 0xb3, 0xbe, 0xc1, 0x70, 0x61, 0xdc, 0x59, 0x0b, 0x66, 0x1b, + 0xd6, 0xd7, 0xd7, 0x53, 0x7a, 0xe8, 0x05, 0x81, 0xc5, 0x33, 0xc8, 0x18, + 0xa5, 0xa4, 0x5c, 0xe5, 0x64, 0xf0, 0xd9, 0x6c, 0x75, 0xc9, 0x25, 0xf1, + 0xd3, 0xe3, 0x87, 0x0f, 0x1b, 0x98, 0xe5, 0x9b, 0xb8, 0x3f, 0xff, 0x90, + 0x65, 0x17, 0x8f, 0x18, 0x58, 0x54, 0xf6, 0xc6, 0x30, 0xd8, 0x5b, 0xd9, + 0x43, 0x2b, 0x1c, 0x1c, 0x9a, 0x60, 0xf5, 0x79, 0x93, 0x79, 0x7c, 0x30, + 0x57, 0x3c, 0x8d, 0x4b, 0x73, 0x4d, 0x63, 0x0c, 0x48, 0xee, 0x3a, 0xb6, + 0xe9, 0x89, 0xa7, 0x75, 0xa6, 0x67, 0x67, 0xb3, 0x13, 0xb4, 0x5a, 0x86, + 0x06, 0xfb, 0x82, 0x94, 0xac, 0x55, 0x6d, 0xd3, 0x37, 0x2b, 0x08, 0x68, + 0x6a, 0x0d, 0x11, 0x60, 0xe4, 0x9f, 0x80, 0x35, 0x96, 0x74, 0x10, 0xb9, + 0xcc, 0xd1, 0x59, 0x79, 0x02, 0x12, 0x70, 0x50, 0x7c, 0xf1, 0xb3, 0xc6, + 0xf1, 0x43, 0xd5, 0x7e, 0x4f, 0xd5, 0x9e, 0xa1, 0x0d, 0xd5, 0xa1, 0x5b, + 0x1e, 0xae, 0xea, 0xd0, 0x33, 0x79, 0x85, 0x66, 0x13, 0xdd, 0xe3, 0xdc, + 0x8b, 0xdf, 0xa1, 0x43, 0x19, 0xfa, 0xd7, 0xd9, 0xc1, 0x11, 0x0b, 0x41, + 0x2e, 0xd2, 0x9e, 0xaa, 0xfe, 0x04, 0xce, 0xaa, 0x8e, 0x9b, 0x86, 0xf3, + 0xcf, 0x43, 0x47, 0x67, 0xf9, 0xf1, 0xe5, 0x62, 0xb5, 0xc6, 0x57, 0xdd, + 0x9d, 0x51, 0x7a, 0xfd, 0x85, 0xf9, 0x47, 0x15, 0x75, 0x12, 0x94, 0x56, + 0x0d, 0xae, 0x27, 0xc8, 0xb8, 0xb7, 0x58, 0x9a, 0x95, 0x56, 0x06, 0x1b, + 0xa5, 0x07, 0x02, 0xc9, 0x2b, 0x99, 0x62, 0x40, 0x71, 0x4f, 0xdd, 0x77, + 0xe3, 0x2e, 0x37, 0x33, 0x98, 0x1d, 0xc7, 0xf3, 0x17, 0xd1, 0x63, 0xee, + 0xdd, 0x73, 0x70, 0xfe, 0x5c, 0xdf, 0x71, 0xb8, 0x37, 0x47, 0x6a, 0xef, + 0xf7, 0x60, 0x10, 0x46, 0xb2, 0xc3, 0x0f, 0xdd, 0x43, 0xe3, 0xb6, 0x55, + 0xc2, 0xb5, 0x23, 0xf6, 0x82, 0xd2, 0xe6, 0xd1, 0x2a, 0x5a, 0xdc, 0x8f, + 0xd1, 0xbf, 0xee, 0x44, 0xe2, 0xe3, 0xf1, 0x9d, 0x4a, 0xfc, 0xcf, 0x0a, + 0x4f, 0x75, 0xcd, 0xb6, 0x91, 0xf6, 0x9d, 0xfd, 0x44, 0x0f, 0x70, 0x01, + 0x46, 0x62, 0xc3, 0xfc, 0xdd, 0x44, 0xb5, 0x1d, 0x9b, 0x24, 0xd1, 0x6d, + 0xf7, 0x21, 0x43, 0xaf, 0x57, 0x91, 0x8d, 0x76, 0x13, 0x11, 0xd9, 0x01, + 0xa3, 0x48, 0x35, 0xa3, 0x9b, 0xf3, 0x2f, 0x8b, 0x49, 0xcb, 0x65, 0xd3, + 0x00, 0xd2, 0x21, 0x01, 0xaa, 0x47, 0xf1, 0x73, 0x93, 0x26, 0x39, 0x3e, + 0x99, 0x2d, 0x96, 0x99, 0xbc, 0xc9, 0xdd, 0x2c, 0x5b, 0x30, 0x6c, 0xb3, + 0xec, 0x31, 0x6c, 0xb3, 0xdb, 0x3c, 0xb6, 0x02, 0xff, 0x32, 0x5f, 0xd6, + 0x8c, 0xa5, 0xad, 0x4b, 0xa9, 0xfa, 0x80, 0x62, 0x0f, 0xde, 0xbc, 0x9b, + 0x80, 0x62, 0x0f, 0xde, 0xbc, 0xbd, 0x80, 0x62, 0x4e, 0x54, 0x10, 0x0e, + 0x2e, 0x06, 0xc9, 0x14, 0x90, 0x8c, 0x39, 0xb5, 0x7e, 0x73, 0x96, 0xad, + 0x78, 0x52, 0x35, 0x44, 0xba, 0x28, 0xd8, 0x02, 0x1b, 0x71, 0xa0, 0x7b, + 0xbe, 0x00, 0xcb, 0x52, 0x97, 0xd3, 0x2f, 0x9e, 0xe6, 0x3f, 0x65, 0x79, + 0xa8, 0x35, 0xf4, 0x8c, 0xe0, 0x47, 0x94, 0xf7, 0x75, 0xbc, 0x6a, 0x27, + 0x2e, 0xcd, 0x5f, 0xe2, 0x2d, 0xaa, 0xd6, 0xaf, 0x0d, 0xc4, 0x90, 0x67, + 0x27, 0x79, 0x56, 0x9c, 0xbd, 0xe0, 0x5d, 0x52, 0x2c, 0x42, 0xc5, 0xd4, + 0xff, 0x44, 0xfe, 0x4a, 0xb9, 0xaf, 0x59, 0x41, 0x21, 0x46, 0x6c, 0xf4, + 0x6e, 0x53, 0x59, 0x1d, 0x06, 0x2e, 0x6d, 0xa9, 0x48, 0x2d, 0xee, 0x30, + 0x4a, 0xc4, 0xf5, 0x12, 0x49, 0xb7, 0xd7, 0xc4, 0x13, 0xa1, 0x82, 0xae, + 0x02, 0x43, 0x08, 0xaf, 0x77, 0x24, 0x11, 0xaf, 0xc5, 0x20, 0x2e, 0xd4, + 0x38, 0xa6, 0x80, 0xbe, 0xaa, 0xfc, 0x94, 0xa2, 0xee, 0x5b, 0xc7, 0xed, + 0x75, 0x99, 0xa2, 0x74, 0xf3, 0xcb, 0x45, 0xd4, 0x94, 0x14, 0xa0, 0x1b, + 0xea, 0x23, 0x89, 0xba, 0xd3, 0x1d, 0xf5, 0x57, 0x89, 0x7a, 0xdf, 0x40, + 0xbd, 0xb9, 0xd3, 0x1e, 0xc8, 0x56, 0x42, 0xd7, 0x2e, 0x28, 0x16, 0x42, + 0xad, 0x9d, 0x50, 0x07, 0x70, 0x31, 0xd2, 0x78, 0x55, 0xfd, 0x2d, 0xd8, + 0x27, 0x83, 0x95, 0xfe, 0x74, 0x7d, 0x9a, 0xf0, 0x8c, 0x58, 0xd4, 0xd5, + 0x82, 0xdf, 0x9a, 0xb5, 0xe0, 0x07, 0xc1, 0xaa, 0xf0, 0x1b, 0xb3, 0x32, + 0x2a, 0xe8, 0x11, 0x7f, 0x76, 0xad, 0x12, 0x99, 0x0e, 0xfe, 0x9c, 0x58, + 0xe6, 0xd7, 0x8f, 0xf8, 0xba, 0xea, 0xbb, 0xfb, 0xc6, 0x1c, 0xb2, 0xa9, + 0xd7, 0xcd, 0xcc, 0x59, 0x47, 0x83, 0xc8, 0x1f, 0x57, 0xf4, 0x5f, 0xbb, + 0xb1, 0xd9, 0x6b, 0x64, 0x89, 0x1a, 0x5d, 0xd4, 0x28, 0xd6, 0xb9, 0x42, + 0xce, 0x9c, 0xdf, 0xa7, 0xec, 0x41, 0x9f, 0x90, 0x57, 0xb2, 0x5c, 0xb6, + 0x9a, 0x26, 0xc9, 0xbd, 0x70, 0x0b, 0xe1, 0x79, 0x0c, 0xfe, 0xd4, 0x88, + 0x9a, 0x35, 0xf1, 0xc2, 0x66, 0x85, 0x75, 0x59, 0x45, 0x58, 0x12, 0xe1, + 0x0f, 0x23, 0xfa, 0x68, 0x15, 0x91, 0x29, 0x2a, 0x7f, 0x80, 0xd6, 0x6c, + 0x22, 0x2f, 0x49, 0x73, 0xf6, 0x80, 0x4d, 0x22, 0x6d, 0x32, 0x08, 0x3d, + 0x8d, 0x4b, 0x0f, 0x50, 0x61, 0x6e, 0x6d, 0x45, 0xed, 0x89, 0x6e, 0xf0, + 0x48, 0xbd, 0xa1, 0xce, 0x78, 0x65, 0x1a, 0x25, 0x6a, 0xb1, 0x15, 0x3a, + 0xab, 0x7f, 0xea, 0x64, 0xd7, 0x00, 0xe5, 0x83, 0x5d, 0xfc, 0xdb, 0x25, + 0x2b, 0x01, 0x1d, 0x81, 0x8a, 0x04, 0x33, 0x1c, 0xaa, 0xaa, 0xe0, 0x08, + 0x1c, 0xad, 0x01, 0xd7, 0xc1, 0x67, 0xe6, 0xc5, 0xee, 0x34, 0xe3, 0x36, + 0x29, 0xa8, 0x88, 0x6c, 0x05, 0x2f, 0x8b, 0xe9, 0x5b, 0x93, 0xe9, 0xc9, + 0xd5, 0x8b, 0x7a, 0xa2, 0x0e, 0xcc, 0xbe, 0x8d, 0x17, 0x57, 0x0c, 0x7b, + 0x8a, 0xc4, 0x47, 0xd1, 0x37, 0xb3, 0x2e, 0x6a, 0xfc, 0xbd, 0x30, 0xb4, + 0x4c, 0x68, 0x2f, 0xe2, 0x03, 0x71, 0x24, 0x1b, 0x0f, 0xce, 0x4f, 0x04, + 0xa9, 0xa9, 0xb6, 0xaf, 0x77, 0xfc, 0xfa, 0x18, 0xb9, 0x38, 0xa3, 0x2b, + 0xe5, 0xe5, 0xf0, 0x74, 0x08, 0xb5, 0xd4, 0x8e, 0xb7, 0x80, 0xeb, 0xab, + 0xe8, 0x27, 0x1a, 0x8d, 0x29, 0xa0, 0xbd, 0xa2, 0x7c, 0x26, 0xdf, 0xad, + 0x8e, 0x55, 0xb4, 0x77, 0x4d, 0x80, 0xd2, 0xd2, 0xb7, 0x62, 0xe4, 0x16, + 0xc6, 0x24, 0x02, 0xe3, 0xd4, 0xc2, 0x98, 0x46, 0x60, 0xcc, 0x2d, 0x8c, + 0x9d, 0x08, 0x0c, 0xb8, 0x04, 0x8a, 0x0b, 0xe7, 0xcf, 0xd7, 0x9f, 0x64, + 0x57, 0xe9, 0x81, 0x59, 0xa7, 0x91, 0xc5, 0xef, 0xc8, 0xe2, 0x65, 0x64, + 0x95, 0x73, 0x38, 0x6c, 0x2f, 0xe9, 0xe5, 0xd4, 0x62, 0xee, 0x7e, 0x04, + 0x73, 0xb9, 0x8d, 0xb2, 0x1b, 0x81, 0x72, 0x6a, 0xa3, 0x3c, 0x88, 0x40, + 0x99, 0xdb, 0x28, 0x6f, 0x46, 0xa0, 0x40, 0x6a, 0xd3, 0xb0, 0xd8, 0x50, + 0xaf, 0x91, 0xc5, 0xf2, 0xc8, 0xe2, 0x66, 0x64, 0x16, 0x14, 0x27, 0xb6, + 0x1d, 0x8b, 0xbb, 0xb7, 0x22, 0xb8, 0xcb, 0x6d, 0x94, 0xb7, 0x23, 0x50, + 0x4e, 0x6d, 0x94, 0x49, 0x8c, 0x42, 0xcf, 0x1d, 0x9c, 0x18, 0x95, 0x86, + 0xe0, 0x76, 0x6a, 0x04, 0xf7, 0x96, 0x25, 0x9c, 0xb7, 0x6d, 0xed, 0x73, + 0x94, 0x71, 0x02, 0xd1, 0xdd, 0xc6, 0x80, 0x52, 0x97, 0x26, 0xba, 0x76, + 0x04, 0xa8, 0x8f, 0xc4, 0xb6, 0x99, 0xd7, 0x30, 0xd4, 0x10, 0x7d, 0x0d, + 0x72, 0x6f, 0x40, 0x0a, 0x47, 0x5c, 0x83, 0xdc, 0x6b, 0x71, 0xfc, 0x28, + 0x6b, 0x5a, 0x8d, 0x80, 0xd4, 0x21, 0x99, 0x54, 0x8d, 0x60, 0xa6, 0xbd, + 0x04, 0x33, 0xed, 0x25, 0x99, 0x69, 0x1f, 0xd1, 0x4c, 0x7b, 0xc9, 0x66, + 0xda, 0x49, 0x38, 0x35, 0xb2, 0xd9, 0xe9, 0x25, 0x9b, 0x9d, 0x5e, 0xb2, + 0xd9, 0xe9, 0x23, 0x1b, 0x42, 0xea, 0x2c, 0x9a, 0x9d, 0x78, 0xd1, 0xdc, + 0x04, 0x0d, 0x40, 0x91, 0x99, 0xab, 0x93, 0x01, 0xd8, 0x21, 0x7b, 0xd5, + 0xff, 0xe9, 0xab, 0xfe, 0x4f, 0x5f, 0xf5, 0x7f, 0xfa, 0xaa, 0xbf, 0x22, + 0x7d, 0x95, 0xec, 0xce, 0x14, 0x90, 0xbd, 0xd3, 0x72, 0xae, 0x53, 0x82, + 0xc6, 0xfc, 0x3f, 0x94, 0x9e, 0x51, 0xc2, 0x36, 0xda, 0x2f, 0x89, 0x6d, + 0xba, 0xb4, 0xa7, 0xbd, 0xb5, 0x55, 0xd6, 0x7b, 0x1d, 0x95, 0x3f, 0xd8, + 0xe5, 0x44, 0x66, 0xcf, 0x7d, 0xca, 0xff, 0x82, 0xa4, 0x86, 0x8c, 0x4b, + 0xd2, 0x1b, 0xac, 0x99, 0x4a, 0x48, 0x5f, 0x5b, 0x3d, 0x66, 0xaf, 0x85, + 0x33, 0xb9, 0x87, 0x21, 0x29, 0x6a, 0xb8, 0x70, 0xaa, 0x68, 0x3a, 0x7f, + 0x30, 0xa9, 0x45, 0xb9, 0x73, 0x87, 0x5b, 0x4a, 0xdb, 0x00, 0xcc, 0x87, + 0x4a, 0xa5, 0x53, 0xbb, 0x09, 0x92, 0x95, 0x3a, 0xa6, 0x2f, 0x6b, 0x90, + 0x28, 0x25, 0x04, 0x5c, 0xb7, 0x7d, 0xe3, 0x6f, 0x55, 0x74, 0xf1, 0xd6, + 0x47, 0xe9, 0x7e, 0xcd, 0xb5, 0xef, 0xce, 0xa7, 0x32, 0xc9, 0x08, 0x7a, + 0xb7, 0xdf, 0xbe, 0xa6, 0x17, 0x94, 0x38, 0x91, 0xe9, 0xea, 0x23, 0xdc, + 0x6d, 0xeb, 0xa9, 0x95, 0x5a, 0x75, 0x1b, 0x34, 0x44, 0x31, 0x78, 0xc0, + 0xcb, 0xee, 0x5f, 0xb5, 0x1d, 0x41, 0x48, 0x2b, 0xac, 0x6a, 0xba, 0x91, + 0xe5, 0x46, 0x73, 0x93, 0xbf, 0xf0, 0x11, 0x79, 0xc6, 0x27, 0xbc, 0x11, + 0xa8, 0xf7, 0x19, 0xfd, 0x23, 0x51, 0x33, 0x3c, 0x3b, 0xab, 0x8c, 0xbf, + 0x5f, 0xf8, 0x2c, 0x21, 0x20, 0xce, 0xee, 0xa0, 0x00, 0xf7, 0xc2, 0x5b, + 0x91, 0x35, 0xb1, 0xde, 0xd5, 0xa3, 0x57, 0xf6, 0x71, 0x6c, 0xc2, 0x85, + 0xc4, 0x78, 0x8c, 0x34, 0x7a, 0x61, 0xd5, 0x71, 0x69, 0x1e, 0x71, 0x97, + 0x6b, 0xe6, 0x99, 0x8f, 0xcc, 0x71, 0x72, 0x1b, 0xd8, 0x3c, 0xf6, 0x39, + 0xd6, 0x23, 0x64, 0xd0, 0x0d, 0x49, 0x79, 0xba, 0xbf, 0x10, 0xe6, 0x36, + 0xf5, 0x23, 0x7e, 0xee, 0xc6, 0xc9, 0x37, 0x4c, 0x72, 0x81, 0xc1, 0xbb, + 0x6b, 0x02, 0xa8, 0xed, 0x3c, 0x36, 0xa7, 0x59, 0x69, 0xb3, 0x0f, 0x1a, + 0xc6, 0xbb, 0x9e, 0x98, 0x7d, 0xd0, 0x78, 0x45, 0xd0, 0x1b, 0xb1, 0x27, + 0xaf, 0xb4, 0xa0, 0xe8, 0x8b, 0xd7, 0xb3, 0x48, 0x5a, 0x8f, 0xf4, 0x2a, + 0x93, 0x11, 0x9b, 0x0b, 0x45, 0xe7, 0x70, 0x55, 0xe7, 0xc6, 0xed, 0xa4, + 0xe1, 0x29, 0x41, 0x81, 0xcf, 0xcb, 0x38, 0xf7, 0x67, 0xc0, 0xd9, 0x41, + 0xac, 0xb4, 0xf3, 0x30, 0x68, 0xd4, 0xfb, 0x0e, 0xe3, 0x25, 0xbb, 0x0d, + 0x77, 0x18, 0xdf, 0x75, 0xcf, 0x31, 0x67, 0x27, 0xb5, 0x95, 0x9e, 0x4c, + 0x22, 0x2e, 0x81, 0x05, 0xf3, 0x3c, 0xf8, 0xd4, 0x70, 0x7c, 0xb6, 0x1b, + 0x95, 0x40, 0xe2, 0x36, 0x27, 0x2c, 0xd9, 0x96, 0x4c, 0x45, 0xde, 0x8e, + 0x48, 0x89, 0x45, 0x73, 0xfc, 0xa8, 0x1b, 0x27, 0xea, 0x01, 0xc5, 0xde, + 0x71, 0x0c, 0x24, 0xef, 0xa4, 0x87, 0x00, 0xfd, 0x7b, 0x22, 0xbe, 0xc4, + 0xf6, 0xd1, 0xe8, 0xf1, 0xc9, 0x50, 0xd7, 0x27, 0x27, 0x9d, 0xee, 0xe1, + 0x69, 0x41, 0x75, 0x12, 0x56, 0x93, 0xc0, 0x4c, 0x43, 0xa9, 0x55, 0x66, + 0x4d, 0xc0, 0x2c, 0x36, 0x17, 0xb6, 0x35, 0x82, 0x8f, 0x2b, 0x3d, 0xde, + 0x8e, 0x63, 0x5f, 0xef, 0xaf, 0x9e, 0x7f, 0x11, 0x7f, 0x07, 0x20, 0x2a, + 0x1b, 0x48, 0x93, 0xcc, 0x4c, 0x6e, 0xfb, 0x8a, 0xad, 0xb3, 0xe8, 0xba, + 0x88, 0xcf, 0x17, 0x61, 0xa3, 0x18, 0xa7, 0x9d, 0xef, 0x76, 0x0d, 0xca, + 0x2e, 0xc1, 0x25, 0x4c, 0x5d, 0x8c, 0x91, 0xaf, 0xa5, 0x93, 0x7f, 0x56, + 0xc8, 0xdd, 0xfa, 0x75, 0x8c, 0xb4, 0x2d, 0xa4, 0x38, 0x91, 0xfb, 0x62, + 0x6f, 0xdd, 0x17, 0xac, 0x15, 0x7d, 0x36, 0xd9, 0x99, 0xdc, 0x92, 0xf0, + 0x7b, 0x35, 0x40, 0xdf, 0x46, 0xe8, 0xdf, 0x10, 0x5d, 0x55, 0x3f, 0x7e, + 0x2b, 0xd2, 0x34, 0xd2, 0xc3, 0x33, 0x7e, 0x98, 0x65, 0x6d, 0x65, 0xb6, + 0x67, 0x2f, 0x15, 0x88, 0x7d, 0x6c, 0x16, 0x81, 0x59, 0x6b, 0xb4, 0xf8, + 0x8c, 0x6a, 0x09, 0xf5, 0xe0, 0x13, 0x78, 0xfd, 0x6c, 0x4f, 0x46, 0xec, + 0xca, 0xa5, 0xa1, 0x6e, 0x9a, 0xc3, 0x2e, 0xb9, 0x0b, 0xb7, 0xb6, 0xfa, + 0xe7, 0x27, 0x6c, 0xbd, 0x1d, 0xe6, 0xd5, 0xa3, 0xe1, 0x8a, 0x94, 0x99, + 0x16, 0xf9, 0x05, 0x90, 0xa9, 0xa0, 0x1e, 0xb7, 0xf1, 0x13, 0xb5, 0x55, + 0xe0, 0x64, 0xfd, 0x52, 0x5d, 0x43, 0x13, 0xfd, 0x9c, 0xd3, 0x2f, 0xc1, + 0xd9, 0x89, 0xbc, 0xb3, 0x4e, 0xb3, 0xbc, 0x2a, 0x19, 0x45, 0x87, 0xd3, + 0x59, 0xed, 0xea, 0x0e, 0x12, 0xf6, 0x6c, 0x90, 0x14, 0x6a, 0xed, 0x16, + 0xcc, 0xb1, 0x1f, 0x61, 0x74, 0xa1, 0x2d, 0xaf, 0x63, 0x06, 0x2e, 0x6c, + 0x9b, 0x46, 0xe0, 0x73, 0x1d, 0xd8, 0x4e, 0x51, 0x9c, 0xf8, 0xbc, 0xf8, + 0x19, 0xcc, 0xc3, 0x54, 0xca, 0x9f, 0x9a, 0x88, 0x4c, 0xe3, 0x88, 0xd0, + 0x50, 0xd9, 0x44, 0x66, 0x27, 0x98, 0x93, 0xb3, 0x75, 0xeb, 0xa7, 0xf2, + 0x00, 0xe4, 0xcb, 0x1d, 0xb2, 0x40, 0xd6, 0x0c, 0x47, 0x2f, 0xb8, 0x67, + 0xd0, 0xf2, 0xc0, 0xc1, 0x7b, 0x0f, 0x78, 0xda, 0xd7, 0x23, 0x88, 0xaa, + 0xdd, 0x17, 0x02, 0xf8, 0xaf, 0x57, 0xf8, 0x1a, 0x2c, 0x44, 0x84, 0x87, + 0x67, 0x81, 0x1f, 0x7d, 0xa8, 0x59, 0x15, 0xf2, 0x2a, 0x0a, 0x31, 0xce, + 0x63, 0xcd, 0xb3, 0x9f, 0x91, 0x75, 0x52, 0x65, 0xfd, 0x3a, 0xb5, 0x7e, + 0xcd, 0x0f, 0x87, 0xc6, 0xda, 0x3d, 0xfa, 0xfc, 0x50, 0xf3, 0xd0, 0xc0, + 0xc4, 0xd4, 0xe6, 0xc2, 0xfe, 0x79, 0x6a, 0xff, 0x9c, 0x4f, 0x63, 0x19, + 0xd9, 0xa9, 0x61, 0xa4, 0x89, 0x93, 0x1d, 0x9b, 0x13, 0xfb, 0xe7, 0xa9, + 0xfd, 0x73, 0xbe, 0x63, 0x71, 0x72, 0x43, 0x9f, 0xf2, 0xca, 0x9f, 0x99, + 0xf7, 0xeb, 0x91, 0xba, 0xf4, 0xc7, 0xae, 0x79, 0xb3, 0xd5, 0x4f, 0xb3, + 0xa6, 0x2b, 0xbb, 0x1b, 0x66, 0x72, 0x35, 0x01, 0xbd, 0x81, 0x42, 0x18, + 0x99, 0x1d, 0x70, 0x39, 0x51, 0xbd, 0x78, 0x41, 0xb8, 0x8f, 0xc4, 0xb3, + 0x74, 0x63, 0x7a, 0xcc, 0x70, 0xd6, 0xd5, 0xae, 0xf3, 0x8b, 0xf5, 0x0a, + 0x84, 0x45, 0x3d, 0x8f, 0x2a, 0x71, 0xe4, 0x59, 0x79, 0x99, 0xaf, 0x92, + 0x74, 0xb0, 0x4d, 0x82, 0x10, 0x63, 0x10, 0x5e, 0x6f, 0x96, 0xeb, 0x67, + 0x22, 0x09, 0x28, 0xc2, 0x45, 0xc1, 0x2a, 0xe1, 0x5c, 0x8b, 0xe3, 0x29, + 0x3d, 0xff, 0xea, 0xe2, 0x02, 0xdb, 0xc8, 0xb3, 0x22, 0x4b, 0xbd, 0x51, + 0x53, 0x0b, 0x12, 0x5f, 0xbc, 0x22, 0x34, 0x0f, 0x0a, 0x04, 0x67, 0x05, + 0x43, 0x94, 0x1a, 0x78, 0x31, 0xa9, 0x7b, 0x31, 0xad, 0x7b, 0x21, 0x1b, + 0xe0, 0xa6, 0x2e, 0xa7, 0xde, 0x3a, 0x97, 0xd1, 0x2b, 0xcc, 0x6e, 0xf3, + 0x4a, 0x60, 0x13, 0x09, 0x00, 0x56, 0x4e, 0x4b, 0xd9, 0xaa, 0x8c, 0xbc, + 0x79, 0x91, 0xf3, 0xe7, 0x63, 0x91, 0x13, 0x9b, 0x25, 0xa0, 0xa9, 0x09, + 0x10, 0x1d, 0xd7, 0xb7, 0x5c, 0x5f, 0x1e, 0x9d, 0x9d, 0xaf, 0x71, 0xad, + 0xdb, 0x0b, 0x5a, 0xcd, 0xf1, 0x46, 0x24, 0xfc, 0x2c, 0x47, 0xdb, 0xe9, + 0x21, 0x4b, 0xa4, 0xaa, 0x74, 0x6d, 0xc8, 0xab, 0x87, 0xc9, 0x67, 0xb3, + 0xf2, 0x6c, 0x93, 0x8d, 0xc2, 0xd4, 0xc4, 0x7c, 0x4e, 0xa5, 0xf0, 0xb9, + 0x0b, 0x3c, 0x05, 0x4f, 0xb3, 0x6f, 0x93, 0x31, 0xa8, 0x6f, 0x62, 0xb8, + 0xc6, 0x50, 0xf1, 0x69, 0x76, 0x52, 0x0e, 0x47, 0x36, 0xa5, 0xeb, 0x58, + 0x4a, 0xdf, 0x69, 0x4a, 0xf4, 0xee, 0x62, 0x68, 0x8c, 0xaa, 0x4a, 0xd5, + 0xeb, 0x2b, 0xcf, 0xb7, 0xd6, 0xa9, 0xe2, 0x3d, 0x2a, 0x26, 0x8a, 0xfc, + 0x36, 0x86, 0x73, 0x01, 0xfa, 0x5d, 0x98, 0x37, 0xdd, 0x8e, 0x3a, 0xda, + 0x29, 0x75, 0x11, 0xee, 0x69, 0x4f, 0xce, 0x51, 0x47, 0xce, 0xff, 0x0b, + 0xbe, 0x36, 0xaf, 0x46, 0x09, 0x7d, 0x5c, 0xc3, 0x85, 0x14, 0xff, 0x0d, + 0xd9, 0xd9, 0x12, 0x84, 0x8c, 0xb8, 0x6e, 0x2f, 0x24, 0x0d, 0xad, 0xe4, + 0xfc, 0xc0, 0x09, 0x77, 0xc3, 0x03, 0x4e, 0x78, 0x3c, 0xe6, 0xdb, 0xcd, + 0x74, 0xad, 0xd9, 0x7e, 0x29, 0xf1, 0xcd, 0x0c, 0x79, 0x28, 0x4d, 0x67, + 0x24, 0x44, 0xd6, 0x69, 0x5d, 0x7c, 0x00, 0x38, 0xb7, 0x41, 0xb5, 0x83, + 0x9a, 0x07, 0x79, 0x1a, 0x82, 0x9c, 0x84, 0x20, 0xe7, 0x21, 0xc8, 0x69, + 0x08, 0xf2, 0xa5, 0x01, 0xa9, 0xcd, 0x00, 0xed, 0xfe, 0xe0, 0x71, 0x64, + 0x7a, 0x39, 0xf8, 0x4c, 0x68, 0x67, 0x06, 0xaf, 0x58, 0xd3, 0x69, 0x41, + 0x96, 0xe4, 0x9f, 0xf9, 0x0c, 0x6f, 0x39, 0x79, 0xa0, 0x39, 0xf5, 0xfa, + 0xd1, 0xad, 0xad, 0xb1, 0x44, 0xaa, 0x96, 0xa9, 0xf1, 0x95, 0xba, 0xb1, + 0xd7, 0xfd, 0x53, 0xba, 0x16, 0x85, 0xcb, 0xcc, 0xf8, 0x4f, 0x8e, 0xd9, + 0x2f, 0x17, 0xc7, 0xe5, 0x59, 0xf5, 0xeb, 0x2c, 0xa3, 0x49, 0xdf, 0x98, + 0x45, 0x14, 0xed, 0x98, 0xd8, 0xe1, 0x66, 0xa9, 0xcc, 0x26, 0x3f, 0x4f, + 0xfd, 0x3d, 0x2b, 0x13, 0xe8, 0x1b, 0x9a, 0x59, 0x52, 0xa3, 0xc4, 0xaa, + 0xd0, 0xad, 0x37, 0xde, 0x90, 0xa0, 0x6f, 0x24, 0x8f, 0x01, 0x59, 0xc8, + 0x1e, 0x44, 0x53, 0x82, 0x7a, 0xb1, 0xa5, 0x65, 0x63, 0x52, 0x33, 0x87, + 0xcf, 0xa3, 0x0c, 0xf5, 0xcf, 0xbf, 0x4d, 0xf6, 0xad, 0x1a, 0x27, 0x5b, + 0xb0, 0xf4, 0x5c, 0xa0, 0xef, 0x00, 0x64, 0x09, 0x42, 0x41, 0xf9, 0xce, + 0xc9, 0x92, 0xea, 0x48, 0x61, 0x46, 0xc9, 0x93, 0x4a, 0xe2, 0xbb, 0x2a, + 0x4f, 0x71, 0xf4, 0x75, 0x59, 0xf8, 0x2c, 0xdd, 0xdf, 0xdc, 0x35, 0x40, + 0x71, 0xf6, 0x65, 0x80, 0xa6, 0x16, 0xec, 0x18, 0x77, 0x92, 0x86, 0x36, + 0x7b, 0x0c, 0x9e, 0xcc, 0xd7, 0x39, 0x34, 0x0e, 0x0f, 0x8d, 0xa6, 0x9f, + 0x67, 0xa7, 0x8b, 0xd5, 0x97, 0x18, 0xb6, 0xd2, 0xa1, 0x0b, 0x2e, 0xda, + 0xce, 0x06, 0x9f, 0xe5, 0x47, 0x7e, 0xfd, 0x4c, 0x6e, 0x58, 0x7f, 0xa6, + 0x68, 0x16, 0x1e, 0x0a, 0xbf, 0x7c, 0x32, 0x12, 0x7b, 0xb7, 0x9a, 0x38, + 0xb7, 0x05, 0x7b, 0xb4, 0x9b, 0x4c, 0x3d, 0x4c, 0x52, 0x8c, 0x79, 0x05, + 0xbf, 0x5c, 0x25, 0x33, 0x1e, 0x42, 0x09, 0x48, 0x32, 0xf1, 0xca, 0xd0, + 0x66, 0x83, 0xf2, 0x3d, 0x7f, 0xc3, 0x95, 0xdd, 0x4f, 0xee, 0xef, 0xd9, + 0xef, 0xc4, 0x15, 0xa2, 0x67, 0xb4, 0x51, 0x81, 0xb7, 0x83, 0x57, 0xb7, + 0xf9, 0x6f, 0x10, 0x84, 0x4a, 0x87, 0xce, 0x63, 0xbe, 0xb6, 0x52, 0x89, + 0xa3, 0xe2, 0xf9, 0x64, 0xb1, 0x5c, 0x8a, 0x40, 0x0e, 0xf3, 0x0c, 0x8b, + 0xa8, 0xc5, 0xc9, 0xe5, 0x52, 0xc5, 0xcf, 0x52, 0x20, 0xe5, 0xec, 0x87, + 0x6c, 0xc5, 0xfe, 0xf4, 0xec, 0x87, 0xf0, 0x30, 0x91, 0xf9, 0xce, 0x8b, + 0x12, 0x9b, 0x25, 0x98, 0x64, 0xf3, 0x93, 0xe5, 0xfa, 0x25, 0x86, 0xa5, + 0xf3, 0xad, 0x1f, 0x2f, 0xb3, 0x82, 0xcf, 0xb7, 0xb6, 0x26, 0x6f, 0x4d, + 0x1f, 0xec, 0xbe, 0xb5, 0x7d, 0x7f, 0x6b, 0x7e, 0xb9, 0x58, 0xd2, 0x89, + 0xe7, 0x78, 0x36, 0x66, 0xb2, 0x63, 0x36, 0xaa, 0xc6, 0x8b, 0xd5, 0xf8, + 0xac, 0x3c, 0x5f, 0xee, 0x3a, 0x89, 0x27, 0x30, 0x3a, 0x2c, 0xc5, 0x18, + 0x23, 0xbf, 0xbe, 0x03, 0x0b, 0xf2, 0x41, 0xf5, 0xeb, 0x9e, 0x6b, 0x5c, + 0x03, 0x47, 0xb8, 0x48, 0xbc, 0x2f, 0x11, 0x53, 0x01, 0x38, 0x86, 0x01, + 0xac, 0x5b, 0x0a, 0x1a, 0x33, 0x79, 0xcb, 0x0d, 0xb8, 0x09, 0x33, 0x54, + 0x21, 0x31, 0x4e, 0x2d, 0x78, 0x58, 0xa3, 0xfc, 0xb7, 0x64, 0x6f, 0x3c, + 0x5f, 0x7b, 0x3a, 0xa4, 0x40, 0x5d, 0x5d, 0xb3, 0x67, 0x58, 0x85, 0xe5, + 0x3f, 0x05, 0x09, 0xfb, 0xa9, 0xa9, 0x93, 0xce, 0x1b, 0x2d, 0x0a, 0xe7, + 0x05, 0x2a, 0x1b, 0x7a, 0xcc, 0x0a, 0xac, 0x1f, 0x69, 0x56, 0xc3, 0x6a, + 0xe3, 0xbf, 0x25, 0xed, 0xa9, 0xf4, 0xf1, 0xac, 0x58, 0xa6, 0x98, 0x94, + 0x54, 0x5b, 0xd1, 0xf1, 0x24, 0xdd, 0x9e, 0xa3, 0x23, 0xe1, 0xd7, 0x87, + 0x83, 0x1a, 0xec, 0x34, 0xae, 0xd0, 0x1b, 0xad, 0xb2, 0x34, 0x98, 0x74, + 0xe9, 0xf2, 0xe5, 0xd9, 0xa2, 0xd8, 0x6c, 0xee, 0xe5, 0xb9, 0x10, 0xa6, + 0x29, 0x3f, 0x2d, 0x32, 0x50, 0xbf, 0x24, 0x38, 0x1c, 0xe0, 0x1f, 0xfd, + 0xf0, 0x72, 0x41, 0x3d, 0x3e, 0x66, 0xe4, 0x00, 0x97, 0xf1, 0x23, 0x07, + 0x49, 0x82, 0x06, 0x05, 0x89, 0x6e, 0x64, 0x41, 0xbc, 0x7e, 0x71, 0x4a, + 0xdc, 0xe1, 0xb1, 0x36, 0xa2, 0x64, 0x9e, 0x95, 0x4f, 0x31, 0x54, 0xcc, + 0xf2, 0x8f, 0xc5, 0x6b, 0x35, 0xc1, 0x4d, 0xde, 0xa4, 0x4f, 0x49, 0xda, + 0x44, 0xa7, 0x93, 0x68, 0xe1, 0xaa, 0x8b, 0x7d, 0x10, 0x02, 0xc6, 0xb1, + 0x21, 0x05, 0xa7, 0x6e, 0x05, 0x85, 0x59, 0xa6, 0x8e, 0x09, 0x79, 0xe0, + 0xa8, 0x69, 0x7f, 0x93, 0xc0, 0x5e, 0x2d, 0x94, 0x22, 0x05, 0x88, 0xa0, + 0x26, 0x78, 0x63, 0xa9, 0x6c, 0x6d, 0x1a, 0x16, 0xeb, 0x07, 0xca, 0xe9, + 0xdd, 0x0d, 0x94, 0xad, 0x13, 0xb3, 0x18, 0xc6, 0xc3, 0x53, 0xb3, 0xb6, + 0x06, 0xd4, 0xa0, 0xb5, 0xcc, 0x4a, 0xa9, 0x6d, 0xa1, 0xa9, 0x59, 0xc3, + 0x2c, 0xc8, 0x46, 0xf6, 0x5a, 0x5c, 0x5b, 0xce, 0xd0, 0xa6, 0x4a, 0x6b, + 0xf5, 0xf7, 0xa1, 0xa6, 0x20, 0x6e, 0x41, 0xee, 0x0b, 0x42, 0xca, 0xa8, + 0x36, 0x46, 0x5b, 0x02, 0xb9, 0xc2, 0xfb, 0xb1, 0xc0, 0xdc, 0xc3, 0x8f, + 0x77, 0x92, 0xea, 0xbb, 0x79, 0x4c, 0x6a, 0x62, 0x5c, 0x9b, 0x18, 0xd7, + 0x06, 0xc6, 0xb5, 0x83, 0xa1, 0xb8, 0x38, 0xc8, 0x61, 0xde, 0x9f, 0x2d, + 0xc8, 0x42, 0xbd, 0xba, 0x9e, 0x5e, 0xac, 0x97, 0xb3, 0x3c, 0x85, 0xc5, + 0x7f, 0x4d, 0x9c, 0x06, 0xae, 0x37, 0x25, 0xef, 0x4a, 0x8a, 0x75, 0x0e, + 0x3e, 0xc5, 0x0f, 0x8b, 0x0b, 0x0e, 0xdd, 0x06, 0x2a, 0xd7, 0xe4, 0x58, + 0x87, 0x51, 0x60, 0xb1, 0x82, 0x68, 0x0a, 0x28, 0xcb, 0xac, 0xc4, 0xfc, + 0xca, 0xb3, 0x6f, 0xb1, 0x38, 0xc6, 0xe7, 0x89, 0x31, 0xcf, 0x7a, 0xd4, + 0x42, 0x79, 0x9d, 0xe5, 0x48, 0xe3, 0x57, 0xe3, 0x38, 0xc3, 0x15, 0x11, + 0x62, 0x6d, 0x8a, 0x6f, 0x29, 0x2a, 0xa4, 0xf9, 0x37, 0xb7, 0xf4, 0x16, + 0xa7, 0x97, 0xa2, 0x7c, 0x2e, 0x98, 0x47, 0x13, 0x72, 0xf6, 0xe1, 0x0d, + 0x54, 0xc1, 0xce, 0xa2, 0x48, 0x2e, 0x16, 0x57, 0xd9, 0x12, 0xcf, 0x18, + 0x86, 0x9b, 0x47, 0xb4, 0x15, 0xdf, 0x0a, 0xde, 0xf4, 0xcb, 0xce, 0xd7, + 0x2f, 0x3f, 0x15, 0x3e, 0x76, 0xfb, 0x46, 0x53, 0xef, 0xf9, 0x80, 0xb3, + 0xe3, 0xef, 0x2f, 0x8b, 0x32, 0x3b, 0x86, 0xd5, 0x87, 0xd6, 0xbc, 0xa7, + 0x00, 0xa5, 0x11, 0x87, 0x79, 0x1a, 0x2d, 0x2e, 0xa6, 0xf1, 0x83, 0xf1, + 0x2e, 0x07, 0x6a, 0x3a, 0xa4, 0x6b, 0xb2, 0x07, 0xdb, 0x34, 0x4e, 0xe3, + 0x7b, 0x0a, 0x86, 0x4c, 0x89, 0x82, 0xe3, 0x20, 0x8f, 0xc3, 0xfa, 0xa2, + 0xc9, 0x96, 0xbc, 0x0e, 0x17, 0x7d, 0x7d, 0x47, 0x45, 0xb3, 0x38, 0xb5, + 0xc5, 0x44, 0x45, 0x66, 0xd8, 0xe2, 0x96, 0x62, 0xce, 0xb3, 0x1f, 0x2f, + 0x17, 0x39, 0x08, 0xde, 0x4f, 0x8a, 0xe5, 0xba, 0x2c, 0x94, 0xdc, 0x35, + 0x49, 0x9f, 0x22, 0x37, 0x17, 0xdb, 0x12, 0x4a, 0xa0, 0xa8, 0x51, 0xaa, + 0xab, 0xf8, 0x86, 0x6e, 0x92, 0x21, 0xac, 0x0c, 0x83, 0x83, 0xbd, 0x90, + 0xee, 0x9c, 0x09, 0x57, 0xef, 0xec, 0x34, 0xd0, 0x64, 0xc5, 0x0c, 0x3b, + 0x34, 0x33, 0x19, 0x9d, 0x21, 0x4f, 0xb6, 0xea, 0x1b, 0x57, 0xad, 0xbe, + 0x26, 0x9b, 0xdb, 0xc1, 0x52, 0x0e, 0xb0, 0x48, 0x1a, 0x89, 0x25, 0xde, + 0x88, 0x17, 0x73, 0xbc, 0x7a, 0x2d, 0x7e, 0x9a, 0x62, 0xd1, 0x9c, 0x82, + 0x85, 0x91, 0x51, 0xd6, 0x48, 0x50, 0x1b, 0x86, 0x74, 0x68, 0x79, 0x71, + 0x36, 0x23, 0x45, 0xdb, 0xdd, 0x75, 0x8b, 0x61, 0x99, 0x1d, 0xb0, 0x70, + 0x88, 0x36, 0xca, 0xdb, 0xab, 0x7b, 0x0f, 0x79, 0x4d, 0x00, 0x23, 0xd8, + 0x69, 0x82, 0x9a, 0x02, 0x8a, 0xb9, 0x6d, 0x02, 0xda, 0x01, 0x90, 0x60, + 0xac, 0x6e, 0x7b, 0xd9, 0x9e, 0xe3, 0x2f, 0x2e, 0x8d, 0x2d, 0x06, 0xd6, + 0x20, 0x9e, 0x19, 0xb7, 0x9d, 0x1d, 0x5d, 0x7b, 0x40, 0xb2, 0x47, 0x68, + 0x14, 0xc8, 0x73, 0x75, 0xf1, 0x63, 0x5e, 0xa6, 0x57, 0x68, 0x63, 0xe2, + 0xe3, 0x1a, 0x9f, 0xd7, 0xe6, 0x10, 0x8b, 0x71, 0x40, 0x01, 0xa2, 0xa8, + 0xd5, 0x34, 0xc5, 0x26, 0xc6, 0x15, 0x00, 0xcc, 0xcd, 0x37, 0x35, 0x00, + 0x3a, 0x65, 0xab, 0xa1, 0x04, 0x9f, 0x66, 0x80, 0x2f, 0xfc, 0x84, 0xfa, + 0xa1, 0x93, 0xfc, 0xfe, 0xdb, 0x28, 0xf9, 0xfd, 0xb7, 0x43, 0x3c, 0xc0, + 0x7a, 0x59, 0xbd, 0x56, 0x34, 0x81, 0x08, 0xc1, 0x32, 0x20, 0xea, 0x05, + 0xfb, 0x58, 0xc3, 0xe9, 0x82, 0x53, 0xa2, 0x0d, 0xae, 0xa5, 0xcd, 0x41, + 0xcb, 0xa6, 0xd4, 0xb0, 0x41, 0x58, 0x73, 0x81, 0xea, 0xf0, 0xd5, 0xac, + 0x31, 0x96, 0x90, 0x8e, 0xce, 0xd0, 0x9f, 0xa1, 0x2b, 0xe2, 0x15, 0xa8, + 0x69, 0x70, 0x43, 0x46, 0x20, 0x34, 0x01, 0x0c, 0x3e, 0xc0, 0x00, 0x8a, + 0xd3, 0x6f, 0xd0, 0xc5, 0x24, 0x0d, 0xe0, 0xa6, 0x93, 0x64, 0x2c, 0x25, + 0x39, 0x2f, 0xd2, 0x94, 0xb1, 0x5e, 0x27, 0x23, 0x7e, 0x0c, 0x8b, 0xdf, + 0x94, 0x79, 0x3e, 0x81, 0x96, 0xe3, 0xff, 0xf9, 0xc4, 0xdc, 0x01, 0x14, + 0x08, 0xef, 0x62, 0xe1, 0x00, 0xe7, 0x64, 0x2e, 0xd3, 0x8f, 0x59, 0x93, + 0x1e, 0x68, 0x5c, 0xd2, 0xa8, 0x03, 0x51, 0x38, 0x9a, 0x0c, 0xba, 0x71, + 0xe8, 0xac, 0xd7, 0x4d, 0x9a, 0x13, 0x93, 0xe6, 0xb4, 0x99, 0x26, 0x68, + 0x49, 0xb2, 0xcd, 0x34, 0xa7, 0x26, 0xcd, 0x9d, 0x66, 0x9a, 0xdb, 0x9a, + 0xe6, 0x55, 0x13, 0xcd, 0x1d, 0x93, 0xe6, 0xfd, 0x56, 0x9a, 0x15, 0xab, + 0x4d, 0x34, 0xef, 0x9b, 0x34, 0x77, 0x5b, 0xeb, 0xbe, 0x1d, 0x43, 0x73, + 0xd7, 0xa4, 0xf9, 0x20, 0xae, 0x8d, 0xb6, 0xcd, 0xba, 0x43, 0x61, 0xb5, + 0x42, 0x9c, 0x57, 0x1a, 0x38, 0x96, 0x65, 0x03, 0xca, 0x34, 0x3f, 0x4e, + 0x41, 0x8c, 0x69, 0xf1, 0x7d, 0xf7, 0x73, 0x3c, 0x90, 0x9f, 0x73, 0xfe, + 0x3c, 0x34, 0xac, 0x4e, 0xe5, 0x81, 0x9d, 0x8f, 0x4e, 0x47, 0x73, 0xa6, + 0xaa, 0xee, 0xa9, 0x43, 0x60, 0x13, 0x35, 0x65, 0x61, 0x6c, 0x3c, 0xb4, + 0xfb, 0x38, 0x9e, 0x40, 0x87, 0x51, 0x96, 0xf8, 0x72, 0x2a, 0xbf, 0xa0, + 0x5c, 0x6f, 0x63, 0xbc, 0x44, 0x4f, 0x2d, 0x96, 0x98, 0xe3, 0x52, 0x0a, + 0x52, 0x64, 0xee, 0x63, 0xf1, 0x83, 0x4d, 0xfa, 0xe7, 0xb9, 0xda, 0x64, + 0xe2, 0x16, 0xe5, 0xc7, 0x3c, 0x5f, 0x2d, 0x56, 0xd5, 0xb5, 0xfc, 0x4d, + 0x3b, 0x4e, 0xa7, 0x06, 0xaa, 0x0f, 0x06, 0x72, 0x50, 0xc1, 0x1c, 0x2a, + 0x39, 0x36, 0x95, 0xcd, 0x5a, 0x5f, 0x3d, 0x86, 0x9f, 0x9d, 0xbc, 0xd5, + 0xfd, 0xec, 0xd1, 0xd3, 0x27, 0x5f, 0x3e, 0x1f, 0xa0, 0xf4, 0xe6, 0xa0, + 0x9d, 0x8c, 0x7a, 0x44, 0x29, 0x18, 0x3f, 0xc7, 0xb7, 0xe6, 0xf0, 0x9d, + 0x5a, 0x28, 0x0e, 0xd6, 0xc1, 0x02, 0x8d, 0x5e, 0xe3, 0x53, 0xa0, 0x0e, + 0x6f, 0xfc, 0xc0, 0xad, 0x83, 0xc7, 0x5f, 0x7c, 0xc6, 0x47, 0x32, 0x78, + 0x06, 0x7f, 0xeb, 0xec, 0x18, 0x2b, 0x51, 0xd5, 0x00, 0xd5, 0x59, 0x84, + 0x6e, 0x73, 0x14, 0x44, 0x2d, 0x9b, 0x5f, 0xae, 0x92, 0x62, 0xb1, 0x3a, + 0xca, 0x12, 0xa0, 0x53, 0x5c, 0x91, 0x25, 0xe3, 0x72, 0xb0, 0xe0, 0x9c, + 0x62, 0xa8, 0xc8, 0x5d, 0xd4, 0xac, 0xe4, 0xab, 0x19, 0x6a, 0xdd, 0xc0, + 0xef, 0x94, 0x67, 0x73, 0x53, 0x20, 0x28, 0x33, 0xba, 0xca, 0x2d, 0x44, + 0x2d, 0x82, 0x06, 0x6c, 0x12, 0x87, 0xcc, 0x4c, 0xb5, 0x92, 0x0c, 0xa4, + 0x7d, 0x04, 0x71, 0x71, 0x35, 0x4c, 0x71, 0x62, 0xaf, 0x3b, 0xd0, 0xc7, + 0x55, 0x32, 0x12, 0x67, 0x1b, 0x50, 0xbd, 0xa9, 0x4f, 0x8e, 0x88, 0x76, + 0x30, 0x9b, 0xe7, 0x9d, 0xad, 0xe2, 0x28, 0x5f, 0x5c, 0x94, 0xef, 0xe2, + 0x11, 0xff, 0x9c, 0xaf, 0x8f, 0xaf, 0xf1, 0xe3, 0x9d, 0x2d, 0xda, 0xeb, + 0xc1, 0x97, 0x3f, 0x00, 0x44, 0xc6, 0x8f, 0x63, 0x02, 0x8c, 0x01, 0x00 +}; diff --git a/Arduino/McLighting/mode_custom_ws2812fx_animations.h b/Arduino/McLighting/mode_custom_ws2812fx_animations.h new file mode 100644 index 0000000..66db560 --- /dev/null +++ b/Arduino/McLighting/mode_custom_ws2812fx_animations.h @@ -0,0 +1,94 @@ +/* + +Example of adding the example: https://github.com/kitesurfer1404/WS2812FX/blob/master/examples/ws2812fx_custom_FastLED/ws2812fx_custom_FastLED.ino +as a custom effect + +More info on how to create custom aniamtions for WS2812FX: https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md#custom-effects + +*/ + +#include //https://github.com/FastLED/FastLED + +byte* heat; + +/* + * paste in the Fire2012 code with a small edit at the end which uses the + * setPixelColor() function to copy the color data to the ws2812fx instance. +*/ + + // Fire2012 by Mark Kriegsman, July 2012 +// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY +//// +// This basic one-dimensional 'fire' simulation works roughly as follows: +// There's a underlying array of 'heat' cells, that model the temperature +// at each point along the line. Every cycle through the simulation, +// four steps are performed: +// 1) All cells cool down a little bit, losing heat to the air +// 2) The heat from each cell drifts 'up' and diffuses a little +// 3) Sometimes randomly new 'sparks' of heat are added at the bottom +// 4) The heat from each cell is rendered as a color into the leds array +// The heat-to-color mapping uses a black-body radiation approximation. +// +// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). +// +// This simulation scales it self a bit depending on NUM_LEDS; it should look +// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. +// +// I recommend running this simulation at anywhere from 30-100 frames per second, +// meaning an interframe delay of about 10-35 milliseconds. +// +// Looks best on a high-density LED setup (60+ pixels/meter). +// +// +// There are two main parameters you can play with to control the look and +// feel of your fire: COOLING (used in step 1 above), and SPARKING (used +// in step 3 above). +// +// COOLING: How much does the air cool as it rises? +// Less cooling = taller flames. More cooling = shorter flames. +// Default 50, suggested range 20-100 +#define COOLING 70 + +// SPARKING: What chance (out of 255) is there that a new spark will be lit? +// Higher chance = more roaring fire. Lower chance = more flickery fire. +// Default 120, suggested range 50-200. +#define SPARKING 120 + +bool gReverseDirection = false; + +void Fire2012() { +// Array of temperature readings at each simulation cell + + // Step 1. Cool down every cell a little + for( int i = 0; i < WS2812FXStripSettings.stripSize; i++) { + heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / WS2812FXStripSettings.stripSize) + 2)); + } + + // Step 2. Heat from each cell drifts 'up' and diffuses a little + for( int k= WS2812FXStripSettings.stripSize - 1; k >= 2; k--) { + heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3; + } + + // Step 3. Randomly ignite new 'sparks' of heat near the bottom + if( random8() < SPARKING ) { + int y = random8(7); + heat[y] = qadd8( heat[y], random8(160,255) ); + } + + // Step 4. Map from heat cells to LED colors + for( int j = 0; j < WS2812FXStripSettings.stripSize; j++) { + CRGB color = HeatColor( heat[j]); + int pixelnumber; + if( gReverseDirection ) { + pixelnumber = (WS2812FXStripSettings.stripSize - 1) - j; + } else { + pixelnumber = j; + } + strip->setPixelColor(pixelnumber, color.red, color.green, color.blue); + } +} + +uint16_t myCustomEffect0() { + Fire2012(); + return (strip->getSpeed() / WS2812FXStripSettings.stripSize); +} diff --git a/Arduino/McLighting/mode_tv.h b/Arduino/McLighting/mode_tv.h index 7871484..a069b42 100644 --- a/Arduino/McLighting/mode_tv.h +++ b/Arduino/McLighting/mode_tv.h @@ -2,20 +2,20 @@ // TV mode // *************************************************************************** -int dipInterval = 10; -int darkTime = 250; +uint8_t dipInterval = 10; +uint16_t darkTime = 250; unsigned long currentDipTime; unsigned long dipStartTime; unsigned long currentMillis; -int ledState = LOW; -long previousMillis = 0; -int led = 5; -int interval = 2000; -int twitch = 50; -int dipCount = 0; -int analogLevel = 100; -boolean timeToDip = false; -int ledStates[NUMLEDS]; +uint8_t ledState = LOW; +long previousMillis = 0; +uint16_t led = 5; +uint16_t interv = 2000; +uint8_t twitch = 50; +uint8_t dipCount = 0; +uint8_t analogLevel = 100; +boolean timeToDip = false; +uint8_t* ledStates; void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) { @@ -24,17 +24,17 @@ void hsb2rgbAN1(uint16_t index, uint8_t sat, uint8_t bright, uint8_t myled) { temp[0] = temp[3] = (uint8_t)(( (sat ^ 255) * bright) / 255); temp[1] = temp[4] = (uint8_t)((((( (index & 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); temp[2] = (uint8_t)(((((((index & 255) ^ 255) * sat) / 255) + (sat ^ 255)) * bright) / 255); - strip.setPixelColor(myled, temp[n + 2], temp[n + 1], temp[n], 0); + strip->setPixelColor(myled, temp[n + 2], temp[n + 1], temp[n], 0); } -void updateLed (int led, int brightness) { +void updateLed (uint16_t led, uint8_t brightness) { ledStates[led] = brightness; - for (int i=0; ishow(); } @@ -42,15 +42,15 @@ void updateLed (int led, int brightness) { void handleTV() { if (timeToDip == false) { currentMillis = millis(); - if(currentMillis-previousMillis > interval) { + if(currentMillis-previousMillis > interv) { previousMillis = currentMillis; - //interval = random(750,4001);//Adjusts the interval for more/less frequent random light changes - interval = random(1000-(ws2812fx_speed*2),5001-(ws2812fx_speed*8)); + //interv = random(750,4001);//Adjusts the interval for more/less frequent random light changes + interv = random(1000-(ws2812fx_speed*2),5001-(ws2812fx_speed*8)); twitch = random(40,100);// Twitch provides motion effect but can be a bit much if too high dipCount = dipCount++; } if(currentMillis-previousMillisnumPixels()-1)); analogLevel=random(50,255);// set the range of the 3 pwm leds ledState = ledState == LOW ? HIGH: LOW; // if the LED is off turn it on and vice-versa: updateLed(led, (ledState) ? 255 : 0); @@ -67,12 +67,12 @@ void handleTV() { DBG_OUTPUT_PORT.println("Dip Time"); currentDipTime = millis(); if (currentDipTime - dipStartTime < darkTime) { - for (int i=3; inumPixels(); i++) { updateLed(i, 0); } } else { timeToDip = false; } - strip.show(); + strip->show(); } } diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h index d1c6d2b..9fc8a8b 100644 --- a/Arduino/McLighting/request_handlers.h +++ b/Arduino/McLighting/request_handlers.h @@ -3,15 +3,16 @@ // *************************************************************************** // Prototypes -void handleAutoStart(void); -String listStatusJSON(void); +void handleAutoStart(); +String listStatusJSON(); +bool writeConfigFS(bool); #if defined(ENABLE_E131) void handleE131(){ - if (!e131.isEmpty()) + if (!e131->isEmpty()) { e131_packet_t packet; - e131.pull(&packet); // Pull packet from ring buffer + e131->pull(&packet); // Pull packet from ring buffer uint16_t universe = htons(packet.universe); uint8_t *data = packet.property_values + 1; @@ -36,12 +37,12 @@ void handleE131(){ for (uint16_t i = 0; i < len; i++){ uint16_t j = i * 3; /* #if defined(RGBW) - strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], data[j + 3]); + strip->setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], data[j + 3]); #else */ - strip.setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], 0); + strip->setPixelColor(i + multipacketOffset, data[j], data[j + 1], data[j + 2], 0); /* #endif */ } - strip.show(); + strip->show(); } } #endif @@ -82,7 +83,7 @@ void getArgs() { 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(); + back_color.red = constrain(server.arg("r2").toInt(), 0, 255); } if ((server.arg("g2") != "") && (server.arg("g2").toInt() >= 0) && (server.arg("g2").toInt() <= 255)) { back_color.green = server.arg("g2").toInt(); @@ -118,8 +119,8 @@ void getArgs() { ws2812fx_speed = constrain(server.arg("s").toInt(), 0, 255); } - 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 ((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 ((server.arg("c") != "") && (server.arg("c").toInt() >= 0) && (server.arg("c").toInt() <= 100)) { @@ -198,7 +199,7 @@ void handleSetAllMode(uint8_t * mypayload) { main_color.red = ((rgb >> 16) & 0xFF); main_color.green = ((rgb >> 8) & 0xFF); main_color.blue = ((rgb >> 0) & 0xFF); - DBG_OUTPUT_PORT.printf("WS: Set all leds to main color: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white); + DBG_OUTPUT_PORT.printf("WS: Set all leds to main color: R: [%u] G: [%u] B: [%u] W: [%u]\r\n", main_color.red, main_color.green, main_color.blue, main_color.white); ws2812fx_mode = FX_MODE_STATIC; mode = SET_ALL; } @@ -209,8 +210,8 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { strncpy (templed, (const char *) &mypayload[firstChar], 2 ); uint8_t led = atoi(templed); - DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\n", led, strip.numPixels(), mypayload ); - if (led <= strip.numPixels()) { + DBG_OUTPUT_PORT.printf("led value: [%i]. Entry threshold: <= [%i] (=> %s)\r\n", led, strip->numPixels(), mypayload ); + if (led <= strip->numPixels()) { char redhex[3]; char greenhex[3]; char bluehex[3]; @@ -219,15 +220,18 @@ void handleSetSingleLED(uint8_t * mypayload, uint8_t firstChar = 0) { strncpy (greenhex, (const char *) &mypayload[4 + firstChar], 2 ); strncpy (bluehex, (const char *) &mypayload[6 + firstChar], 2 ); strncpy (whitehex, (const char *) &mypayload[8 + firstChar], 2 ); + redhex[2] = 0x00; + greenhex[2] = 0x00; + bluehex[2] = 0x00; ledstates[led].red = strtol(redhex, NULL, 16); ledstates[led].green = strtol(greenhex, NULL, 16); ledstates[led].blue = strtol(bluehex, NULL, 16); ledstates[led].white = strtol(whitehex, NULL, 16); - DBG_OUTPUT_PORT.printf("rgb.red: [%s] rgb.green: [%s] rgb.blue: [%s] rgb.white: [%s]\n", redhex, greenhex, bluehex, whitehex); - DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i] rgb.white: [%i]\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16), strtol(whitehex, NULL, 16)); - DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\n", led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white, mypayload); - strip.setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white); - strip.show(); + DBG_OUTPUT_PORT.printf("rgb.red: [%s] rgb.green: [%s] rgb.blue: [%s] rgb.white: [%s]\r\n", redhex, greenhex, bluehex, whitehex); + DBG_OUTPUT_PORT.printf("rgb.red: [%i] rgb.green: [%i] rgb.blue: [%i] rgb.white: [%i]\r\n", strtol(redhex, NULL, 16), strtol(greenhex, NULL, 16), strtol(bluehex, NULL, 16), strtol(whitehex, NULL, 16)); + DBG_OUTPUT_PORT.printf("WS: Set single led [%i] to [%i] [%i] [%i] [%i] (%s)!\r\n", led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white, mypayload); + strip->setPixelColor(led, ledstates[led].red, ledstates[led].green, ledstates[led].blue, ledstates[led].white); + strip->show(); } mode = CUSTOM; } @@ -248,25 +252,25 @@ void handleRangeDifferentColors(uint8_t * mypayload) { while (nextCommand) { // Loop for each LED. - char startled[3] = { 0, 0, 0 }; - char endled[3] = { 0, 0, 0 }; - char colorval[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + char startled[4] = { 0, 0, 0 }; + char endled[4] = { 0, 0, 0 }; + char colorval[9] = { 0, 0, 0, 0, 0, 0, 0, 0 }; strncpy ( startled, (const char *) &nextCommand[0], 2 ); strncpy ( endled, (const char *) &nextCommand[2], 2 ); strncpy ( colorval, (const char *) &nextCommand[4], 8 ); int rangebegin = atoi(startled); int rangeend = atoi(endled); - DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s] \n", rangebegin, rangeend, colorval); + DBG_OUTPUT_PORT.printf("Setting RANGE from [%i] to [%i] as color [%s] \r\n", rangebegin, rangeend, colorval); while ( rangebegin <= rangeend ) { - char rangeData[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char rangeData[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if ( rangebegin < 10 ) { // Create the valid 'nextCommand' structure - sprintf(rangeData, "0%d%s", rangebegin, colorval); + snprintf(rangeData, sizeof(rangeData), "0%d%s", rangebegin, colorval); } if ( rangebegin >= 10 ) { // Create the valid 'nextCommand' structure - sprintf(rangeData, "%d%s", rangebegin, colorval); + snprintf(rangeData, sizeof(rangeData), "%d%s", rangebegin, colorval); } // Set one LED handleSetSingleLED((uint8_t*) rangeData, 0); @@ -278,44 +282,158 @@ void handleRangeDifferentColors(uint8_t * mypayload) { } } -void setModeByStateString(String saved_state_string) { - String str_mode = getValue(saved_state_string, '|', 1); - mode = static_cast(str_mode.toInt()); - DBG_OUTPUT_PORT.print("mode: "); - DBG_OUTPUT_PORT.println(mode); - String str_ws2812fx_mode = getValue(saved_state_string, '|', 2); - ws2812fx_mode = str_ws2812fx_mode.toInt(); - String str_ws2812fx_speed = getValue(saved_state_string, '|', 3); - ws2812fx_speed = str_ws2812fx_speed.toInt(); - String str_brightness = getValue(saved_state_string, '|', 4); - brightness = str_brightness.toInt(); - String str_red = getValue(saved_state_string, '|', 5); - main_color.red = str_red.toInt(); - String str_green = getValue(saved_state_string, '|', 6); - main_color.green = str_green.toInt(); - String str_blue = getValue(saved_state_string, '|', 7); - main_color.blue = str_blue.toInt(); - String str_white = getValue(saved_state_string, '|', 8); - main_color.white = str_white.toInt(); - str_red = getValue(saved_state_string, '|', 9); - back_color.red = str_red.toInt(); - str_green = getValue(saved_state_string, '|', 10); - back_color.green = str_green.toInt(); - str_blue = getValue(saved_state_string, '|', 11); - back_color.blue = str_blue.toInt(); - str_white = getValue(saved_state_string, '|', 12); - back_color.white = str_white.toInt(); - str_red = getValue(saved_state_string, '|', 13); - xtra_color.red = str_red.toInt(); - str_green = getValue(saved_state_string, '|', 14); - xtra_color.green = str_green.toInt(); - str_blue = getValue(saved_state_string, '|', 15); - xtra_color.blue = str_blue.toInt(); - str_white = getValue(saved_state_string, '|', 16); - xtra_color.white = str_white.toInt(); - convertColors(); - DBG_OUTPUT_PORT.print("Set to state: "); - DBG_OUTPUT_PORT.println(listStatusJSON()); +bool checkPin(uint8_t pin) { + 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( int i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ; + DBG_OUTPUT_PORT.printf("Checking RGB Order: %s ...", rgbOrder); + neoPixelType returnOrder; + 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!"); + returnOrder = static_cast(checkRGBOrder(WS2812FXStripSettings.RGBOrder)); + } + DBG_OUTPUT_PORT.println("success!"); + strcpy(WS2812FXStripSettings.RGBOrder, rgbOrder); + return returnOrder; +} + +bool setConfByConfString(String saved_conf_string) { + if (getValue(saved_conf_string, '|', 0) == "CNF") { + DBG_OUTPUT_PORT.printf("Parsed conf: %s\r\n", saved_conf_string.c_str()); + getValue(saved_conf_string, '|', 1).toCharArray(HOSTNAME, 64); + #if defined(ENABLE_MQTT) + getValue(saved_conf_string, '|', 2).toCharArray(mqtt_host, 64); + mqtt_port = getValue(saved_conf_string, '|', 3).toInt(); + getValue(saved_conf_string, '|', 4).toCharArray(mqtt_user, 32); + getValue(saved_conf_string, '|', 5).toCharArray(mqtt_pass, 32); + #endif + WS2812FXStripSettings.stripSize = getValue(saved_conf_string, '|', 6).toInt(); + checkPin(getValue(saved_conf_string, '|', 7).toInt()); + char tmp_rgbOrder[5]; + getValue(saved_conf_string, '|', 8).toCharArray(tmp_rgbOrder, 4); + checkRGBOrder(tmp_rgbOrder); + WS2812FXStripSettings.fxoptions = getValue(saved_conf_string, '|', 9).toInt(); + return true; + } else { + DBG_OUTPUT_PORT.println("Saved conf not found!"); + return false; + } + return false; +} + + + +bool setModeByStateString(String saved_state_string) { + if (getValue(saved_state_string, '|', 0) == "STA") { + DBG_OUTPUT_PORT.printf("Parsed state: %s\r\n", saved_state_string.c_str()); + String str_mode = getValue(saved_state_string, '|', 1); + mode = static_cast(str_mode.toInt()); + String str_ws2812fx_mode = getValue(saved_state_string, '|', 2); + ws2812fx_mode = str_ws2812fx_mode.toInt(); + String str_ws2812fx_speed = getValue(saved_state_string, '|', 3); + ws2812fx_speed = str_ws2812fx_speed.toInt(); + String str_brightness = getValue(saved_state_string, '|', 4); + brightness = str_brightness.toInt(); + String str_red = getValue(saved_state_string, '|', 5); + main_color.red = str_red.toInt(); + String str_green = getValue(saved_state_string, '|', 6); + main_color.green = str_green.toInt(); + String str_blue = getValue(saved_state_string, '|', 7); + main_color.blue = str_blue.toInt(); + String str_white = getValue(saved_state_string, '|', 8); + main_color.white = str_white.toInt(); + str_red = getValue(saved_state_string, '|', 9); + back_color.red = str_red.toInt(); + str_green = getValue(saved_state_string, '|', 10); + back_color.green = str_green.toInt(); + str_blue = getValue(saved_state_string, '|', 11); + back_color.blue = str_blue.toInt(); + str_white = getValue(saved_state_string, '|', 12); + back_color.white = str_white.toInt(); + str_red = getValue(saved_state_string, '|', 13); + xtra_color.red = str_red.toInt(); + str_green = getValue(saved_state_string, '|', 14); + xtra_color.green = str_green.toInt(); + str_blue = getValue(saved_state_string, '|', 15); + xtra_color.blue = str_blue.toInt(); + str_white = getValue(saved_state_string, '|', 16); + xtra_color.white = str_white.toInt(); + convertColors(); + DBG_OUTPUT_PORT.print("Set to state: "); + DBG_OUTPUT_PORT.println(listStatusJSON()); + return true; + } else { + DBG_OUTPUT_PORT.println("Saved conf not found!"); + return false; + } + return false; } #if defined(ENABLE_LEGACY_ANIMATIONS) @@ -373,7 +491,7 @@ void handleSetNamedMode(uint8_t * mypayload) { void handleSetWS2812FXMode(uint8_t * mypayload) { if (isDigit(mypayload[1])) { ws2812fx_mode = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10); - ws2812fx_mode = constrain(ws2812fx_mode, 0, strip.getModeCount() - 1); + ws2812fx_mode = constrain(ws2812fx_mode, 0, strip->getModeCount() - 1); mode = SET_MODE; } else { if (strcmp((char *) &mypayload[1], "off") == 0) { @@ -398,16 +516,16 @@ void handleSetWS2812FXMode(uint8_t * mypayload) { } } -String listStatusJSON(void) { - //uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip.getMode(); - const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(6) + 150; +String listStatusJSON() { + //uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip->getMode(); + const size_t bufferSize = JSON_ARRAY_SIZE(12) + JSON_OBJECT_SIZE(6) + 500; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject root = jsonBuffer.to(); root["mode"] = (uint8_t) mode; root["ws2812fx_mode"] = ws2812fx_mode; - root["ws2812fx_mode_name"] = strip.getModeName(ws2812fx_mode); + root["ws2812fx_mode_name"] = strip->getModeName(ws2812fx_mode); //root["ws2812fx_mode"] = tmp_mode; - //root["ws2812fx_mode_name"] = strip.getModeName(tmp_mode); + //root["ws2812fx_mode_name"] = strip->getModeName(tmp_mode); root["speed"] = ws2812fx_speed; root["brightness"] = brightness; JsonArray color = root.createNestedArray("color"); @@ -422,20 +540,53 @@ String listStatusJSON(void) { color.add(xtra_color.white); color.add(xtra_color.red); color.add(xtra_color.green); - color.add(xtra_color.blue); + color.add(xtra_color.blue); String json; serializeJson(root, json); jsonBuffer.clear(); return json; } +String listConfigJSON() { + //uint8_t tmp_mode = (mode == SET_MODE) ? (uint8_t) ws2812fx_mode : strip->getMode(); + #if defined(ENABLE_MQTT) + const size_t bufferSize = JSON_OBJECT_SIZE(9) + 500; + #else + const size_t bufferSize = JSON_OBJECT_SIZE(5) + 150; + #endif + DynamicJsonDocument jsonBuffer(bufferSize); + JsonObject root = jsonBuffer.to(); + 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_cnt"] = WS2812FXStripSettings.stripSize; + root["ws_rgbo"] = WS2812FXStripSettings.RGBOrder; + root["ws_pin"] = WS2812FXStripSettings.pin; + root["ws_fxopt"] = WS2812FXStripSettings.fxoptions; + String json; + serializeJson(root, json); + jsonBuffer.clear(); + return json; +} + + void getStatusJSON() { server.sendHeader("Access-Control-Allow-Origin", "*"); server.send ( 200, "application/json", listStatusJSON() ); } -String listModesJSON(void) { - const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount() + 3) + (strip.getModeCount() + 3)*JSON_OBJECT_SIZE(2) + 2000; +void getConfigJSON() { + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send ( 200, "application/json", listConfigJSON() ); +} + + +String listModesJSON() { + const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount() + 3) + (strip->getModeCount() + 3)*JSON_OBJECT_SIZE(2) + 2000; DynamicJsonDocument jsonBuffer(bufferSize); JsonArray root = jsonBuffer.to(); JsonObject objectoff = root.createNestedObject(); @@ -451,10 +602,10 @@ String listModesJSON(void) { objecte131["mode"] = "e131"; objecte131["name"] = "E131"; #endif - for (uint8_t i = 0; i < strip.getModeCount(); i++) { + for (uint8_t i = 0; i < strip->getModeCount(); i++) { JsonObject object = root.createNestedObject(); object["mode"] = i; - object["name"] = strip.getModeName(i); + object["name"] = strip->getModeName(i); } String json; serializeJson(root, json); @@ -496,7 +647,7 @@ void handleMinimalUpload() { } void handleNotFound() { - String message = "File Not Found\n\n"; + String message = "File Not Found\r\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; @@ -518,12 +669,12 @@ int autoCount = 0; void autoTick() { uint32_t setcolors[] = {autoParams[autoCount][0],autoParams[autoCount][1],autoParams[autoCount][2]}; - strip.setColors(0, setcolors); - strip.setSpeed(convertSpeed((uint8_t)autoParams[autoCount][3])); - strip.setMode((uint8_t)autoParams[autoCount][4]); - autoTicker.once((float)autoParams[autoCount][5], autoTick); + strip->setColors(0, setcolors); + strip->setSpeed(convertSpeed((uint8_t)autoParams[autoCount][3])); + strip->setMode((uint8_t)autoParams[autoCount][4]); + autoTicker.once_ms((uint32_t)autoParams[autoCount][5], autoTick); DBG_OUTPUT_PORT.print("autoTick "); - DBG_OUTPUT_PORT.println(autoCount); + DBG_OUTPUT_PORT.printf("autoTick[%d]: {0x%06x, %d, %d, %d}\r\n", autoCount, autoParams[autoCount][0], (uint8_t)autoParams[autoCount][1], (uint8_t)autoParams[autoCount][2], (uint32_t)autoParams[autoCount][3], (uint32_t)autoParams[autoCount][4], (uint32_t)autoParams[autoCount][5]); autoCount++; if (autoCount >= (sizeof(autoParams) / sizeof(autoParams[0]))) autoCount = 0; @@ -556,17 +707,17 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { // # ==> Set main color - ## ==> Set 2nd color - ### ==> Set 3rd color if (payload[0] == '#') { #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK %s", payload); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %s", payload); #endif if (payload[2] == '#') { handleSetXtraColor(payload); - DBG_OUTPUT_PORT.printf("Set 3rd color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", xtra_color.red, xtra_color.green, xtra_color.blue, xtra_color.white); + DBG_OUTPUT_PORT.printf("Set 3rd color to: R: [%u] G: [%u] B: [%u] W: [%u]\r\n", xtra_color.red, xtra_color.green, xtra_color.blue, xtra_color.white); } else if (payload[1] == '#') { handleSetBackColor(payload); - DBG_OUTPUT_PORT.printf("Set 2nd color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", back_color.red, back_color.green, back_color.blue, back_color.white); + DBG_OUTPUT_PORT.printf("Set 2nd color to: R: [%u] G: [%u] B: [%u] W: [%u]\r\n", back_color.red, back_color.green, back_color.blue, back_color.white); } else { handleSetMainColor(payload); - DBG_OUTPUT_PORT.printf("Set main color to: R: [%u] G: [%u] B: [%u] W: [%u]\n", main_color.red, main_color.green, main_color.blue, main_color.white); + DBG_OUTPUT_PORT.printf("Set main color to: R: [%u] G: [%u] B: [%u] W: [%u]\r\n", main_color.red, main_color.green, main_color.blue, main_color.white); } } @@ -576,7 +727,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { ws2812fx_speed = constrain(d, 0, 255); mode = SET_SPEED; Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set speed to: [%u]\n", ws2812fx_speed); + DBG_OUTPUT_PORT.printf("Set speed to: [%u]\r\n", ws2812fx_speed); } // % ==> Set brightness @@ -585,14 +736,14 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { brightness = constrain(b, 0, 255); mode = SET_BRIGHTNESS; Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set brightness to: [%u]\n", brightness); + DBG_OUTPUT_PORT.printf("Set brightness to: [%u]\r\n", brightness); } // * ==> Set main color and light all LEDs (Shortcut) if (payload[0] == '*') { handleSetAllMode(payload); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set main color and light all LEDs [%s]\n", payload); + DBG_OUTPUT_PORT.printf("Set main color and light all LEDs [%s]\r\n", payload); } // ! ==> Set single LED in given color @@ -600,9 +751,9 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { handleSetSingleLED(payload, 1); Dbg_Prefix(mqtt, num); #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK %s", payload); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %s", payload); #endif - DBG_OUTPUT_PORT.printf("Set single LED in given color [%s]\n", payload); + DBG_OUTPUT_PORT.printf("Set single LED in given color [%s]\r\n", payload); } // + ==> Set multiple LED in the given colors @@ -610,18 +761,18 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { handleSetDifferentColors(payload); Dbg_Prefix(mqtt, num); #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK %s", payload); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %s", payload); #endif - DBG_OUTPUT_PORT.printf("Set multiple LEDs in given color [%s]\n", payload); + DBG_OUTPUT_PORT.printf("Set multiple LEDs in given color [%s]\r\n", payload); } // + ==> Set range of LEDs in the given color if (payload[0] == 'R') { handleRangeDifferentColors(payload); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set range of LEDs in given color [%s]\n", payload); + DBG_OUTPUT_PORT.printf("Set range of LEDs in given color [%s]\r\n", payload); #if defined(ENABLE_MQTT) - sprintf(mqtt_buf, "OK %s", payload); + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %s", payload); #endif } @@ -631,7 +782,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { // we get mode data handleSetNamedMode(payload); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Activated mode [%u]!\n", mode); + DBG_OUTPUT_PORT.printf("Activated mode [%u]!\r\n", mode); } #endif @@ -642,10 +793,110 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { DBG_OUTPUT_PORT.print("MQTT: "); #if defined(ENABLE_MQTT) #if ENABLE_MQTT == 0 - mqtt_client.publish(mqtt_outtopic, json.c_str()); + mqtt_client->publish(mqtt_outtopic, json.c_str()); #endif #if ENABLE_MQTT == 1 - amqttClient.publish(mqtt_outtopic, qospub, false, json.c_str()); + mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str()); + #endif + #endif + } else { + DBG_OUTPUT_PORT.print("WS: "); + webSocket.sendTXT(num, "OK"); + webSocket.sendTXT(num, json); + } + DBG_OUTPUT_PORT.println("Get status info: " + json); + } + + + // $ ==> Get config Info. + if (payload[0] == 'C') { + bool updateFSE = false; + if (payload[1] == 'h') { + snprintf(HOSTNAME, sizeof(HOSTNAME), "%s", &payload[2]); + updateFSE=true; + #if defined(ENABLE_MQTT) + initMqtt(); + #endif + } + #if defined(ENABLE_MQTT) + if (payload[1] == 'm') { + if (payload[2] == 'h') { + snprintf(mqtt_host, sizeof(mqtt_host), "%s", &payload[3]); + updateFSE=true; + } + if (payload[2] == 'p') { + char tmp_port[6]; + snprintf(tmp_port, sizeof(tmp_port), "%s", &payload[3]); + mqtt_port = constrain(atoi(tmp_port), 0, 65535); + updateFSE=true; + } + if (payload[2] == 'u') { + snprintf(mqtt_user, sizeof(mqtt_user), "%s", &payload[3]); + updateFSE=true; + } + if (payload[2] == 'w') { + snprintf(mqtt_pass, sizeof(mqtt_pass), "%s", &payload[3]); + updateFSE=true; + } + initMqtt(); + } + #endif + if (payload[1] == 's') { + if (payload[2] == 'c') { + char tmp_count[6]; + snprintf(tmp_count, sizeof(tmp_count), "%s", &payload[3]); + WS2812FXStripSettings.stripSize = constrain(atoi(tmp_count), 0, 65535); + updateFSE=true; + } + if (payload[2] == 'r') { + char tmp_rgbOrder[5]; + snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", &payload[3]); + checkRGBOrder(tmp_rgbOrder); + updateFSE=true; + } + #if !defined(USE_WS2812FX_DMA) + if (payload[2] == 'p') { + char tmp_pin[3]; + snprintf(tmp_pin, sizeof(tmp_pin), "%s", &payload[3]); + checkPin(atoi(tmp_pin)); + updateFSE=true; + } + #endif + if (payload[2] == 'o') { + char tmp_fxoptions[4]; + snprintf(tmp_fxoptions, sizeof(tmp_fxoptions), "%s", &payload[3]); + WS2812FXStripSettings.fxoptions = constrain(atoi(tmp_fxoptions), 0, 255); + updateFSE=true; + } + mode = INIT_STRIP; + } + + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + (writeConfigFS(updateFSE)) ? DBG_OUTPUT_PORT.println("Config FS Save success!"): DBG_OUTPUT_PORT.println("Config FS Save failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + if (updateFSE) { + char last_conf[223]; + #if defined(ENABLE_MQTT) + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, mqtt_host, mqtt_port, mqtt_user, mqtt_pass, WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #else + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, "", "", "", "", WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #endif + writeEEPROM(0, 222, last_conf); + EEPROM.commit(); + } + #endif + #endif + String json = listConfigJSON(); + if (mqtt == true) { + DBG_OUTPUT_PORT.print("MQTT: "); + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + mqtt_client->publish(mqtt_outtopic, json.c_str()); + #endif + #if ENABLE_MQTT == 1 + mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str()); #endif #endif } else { @@ -663,18 +914,16 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { DBG_OUTPUT_PORT.print("MQTT: "); #if defined(ENABLE_MQTT) #if ENABLE_MQTT == 0 - // TODO: Fix this, doesn't return anything. Too long? - // Hint: https://github.com/knolleary/pubsubclient/issues/110 - DBG_OUTPUT_PORT.printf("Error: Not implemented. Message too large for pubsubclient."); - mqtt_client.publish(mqtt_outtopic, "ERROR: Not implemented. Message too large for pubsubclient."); - //String json_modes = listModesJSON(); - //DBG_OUTPUT_PORT.printf(json_modes.c_str()); - - //int res = mqtt_client.publish(mqtt_outtopic, json_modes.c_str(), json_modes.length()); - //DBG_OUTPUT_PORT.printf("Result: %d / %d", res, json_modes.length()); + String json = listModesJSON(); + unsigned int msg_len = measureJson(json) + 1; + char buffer[msg_len]; + serializeJson(json, buffer, sizeof(buffer)); + mqtt_client->beginPublish(mqtt_outtopic, msg_len, true); + mqtt_client->write((const uint8_t*)buffer, msg_len); + mqtt_client->endPublish(); #endif #if ENABLE_MQTT == 1 - amqttClient.publish(mqtt_outtopic, qospub, false, json.c_str()); + mqtt_client->publish(mqtt_outtopic, qospub, false, json.c_str()); #endif #endif } else { @@ -690,7 +939,7 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { if (payload[0] == '/') { handleSetWS2812FXMode(payload); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set WS2812 mode: [%s]\n", payload); + DBG_OUTPUT_PORT.printf("Set WS2812 mode: [%s]\r\n", payload); } } @@ -700,12 +949,12 @@ void checkpayload(uint8_t * payload, bool mqtt = false, uint8_t num = 0) { void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) { switch (type) { case WStype_DISCONNECTED: - DBG_OUTPUT_PORT.printf("WS: [%u] Disconnected!\n", num); + DBG_OUTPUT_PORT.printf("WS: [%u] Disconnected!\r\n", num); break; case WStype_CONNECTED: { IPAddress ip = webSocket.remoteIP(num); - DBG_OUTPUT_PORT.printf("WS: [%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); + DBG_OUTPUT_PORT.printf("WS: [%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload); // send message to client webSocket.sendTXT(num, "Connected"); @@ -713,7 +962,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght break; case WStype_TEXT: - DBG_OUTPUT_PORT.printf("WS: [%u] get Text: %s\n", num, payload); + DBG_OUTPUT_PORT.printf("WS: [%u] get Text: %s\r\n", num, payload); checkpayload(payload, false, num); @@ -821,7 +1070,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght root["color_temp"] = color_temp; root["speed"] = ws2812fx_speed; //char modeName[30]; - //strncpy_P(modeName, (PGM_P)strip.getModeName(strip.getMode()), sizeof(modeName)); // copy from progmem + //strncpy_P(modeName, (PGM_P)strip->getModeName(strip->getMode()), sizeof(modeName)); // copy from progmem #if defined(ENABLE_HOMEASSISTANT) if (mode == OFF){ root["effect"] = "OFF"; @@ -835,7 +1084,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght if (mode == E131){ root["effect"] = "E131"; } else { - root["effect"] = strip.getModeName(strip.getMode()); + root["effect"] = strip->getModeName(strip->getMode()); } } } @@ -845,16 +1094,16 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght serializeJson(root, buffer, sizeof(buffer)); jsonBuffer.clear(); #if ENABLE_MQTT == 0 - mqtt_client.publish(mqtt_ha_state_out, buffer, true); - DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out, buffer); + mqtt_client->publish(mqtt_ha_state_out, buffer, true); + DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\r\n", mqtt_ha_state_out, buffer); #endif #if ENABLE_MQTT == 1 - amqttClient.publish(mqtt_ha_state_out, 1, true, buffer); - DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\n", mqtt_ha_state_out, buffer); + mqtt_client->publish(mqtt_ha_state_out, 1, true, buffer); + DBG_OUTPUT_PORT.printf("MQTT: Send [%s]: %s\r\n", mqtt_ha_state_out, buffer); #endif new_ha_mqtt_msg = false; ha_send_data.detach(); - DBG_OUTPUT_PORT.printf("Heap size: %u\n", ESP.getFreeHeap()); + DBG_OUTPUT_PORT.printf("Heap size: %u\r\n", ESP.getFreeHeap()); } bool processJson(char* message) { @@ -942,8 +1191,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght mode = E131; } #endif - for (uint8_t i = 0; i < strip.getModeCount(); i++) { - if(String(strip.getModeName(i)) == effectString) { + for (uint8_t i = 0; i < strip->getModeCount(); i++) { + if(String(strip->getModeName(i)) == effectString) { mode = SET_MODE; ws2812fx_mode = i; break; @@ -962,7 +1211,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght uint8_t * payload = (uint8_t *) malloc(length + 1); memcpy(payload, payload_in, length); payload[length] = 0; - DBG_OUTPUT_PORT.printf("]: %s\n", payload); + DBG_OUTPUT_PORT.printf("]: %s\r\n", payload); #endif #if ENABLE_MQTT == 0 @@ -970,7 +1219,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght uint8_t * payload = (uint8_t *)malloc(length + 1); memcpy(payload, payload_in, length); payload[length] = 0; - DBG_OUTPUT_PORT.printf("MQTT: Message arrived [%s]\n", payload); + DBG_OUTPUT_PORT.printf("MQTT: Message arrived [%s]\r\n", payload); #endif #if defined(ENABLE_HOMEASSISTANT) @@ -978,13 +1227,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght if (!processJson((char*)payload)) { return; } - if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState); - #if ENABLE_MQTT == 0 - } else if (strcmp(topic, (char *)mqtt_intopic) == 0) { - #endif - #if ENABLE_MQTT == 1 + if(!ha_send_data.active()) ha_send_data.once(5, tickerSendState); } else if (strcmp(topic, mqtt_intopic) == 0) { - #endif #endif checkpayload(payload, true); @@ -998,35 +1242,37 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght #if ENABLE_MQTT == 0 void mqtt_reconnect() { // Loop until we're reconnected - while (!mqtt_client.connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { + while (!mqtt_client->connected() && mqtt_reconnect_retries < MQTT_MAX_RECONNECT_TRIES) { mqtt_reconnect_retries++; - DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES); + DBG_OUTPUT_PORT.printf("Attempting MQTT connection %d / %d ...\r\n", mqtt_reconnect_retries, MQTT_MAX_RECONNECT_TRIES); // Attempt to connect - if (mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_pass)) { + if (mqtt_client->connect(mqtt_clientid, mqtt_user, mqtt_pass)) { DBG_OUTPUT_PORT.println("MQTT connected!"); // Once connected, publish an announcement... char * message = new char[18 + strlen(HOSTNAME) + 1]; strcpy(message, "McLighting ready: "); strcat(message, HOSTNAME); - mqtt_client.publish(mqtt_outtopic, message); + mqtt_client->publish(mqtt_outtopic, message); // ... and resubscribe - mqtt_client.subscribe(mqtt_intopic, qossub); + mqtt_client->subscribe(mqtt_intopic, qossub); #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); - mqtt_client.subscribe(mqtt_ha_state_in, qossub); + mqtt_client->subscribe(mqtt_ha_state_in, qossub); #if defined(MQTT_HOME_ASSISTANT_SUPPORT) - const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; + const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject json = jsonBuffer.to(); json["name"] = HOSTNAME; - #if defined(MQTT_HOME_ASSISTANT_0_84_SUPPORT) + #if defined(MQTT_HOME_ASSISTANT_0_87_SUPPORT) json["schema"] = "json"; #else json["platform"] = "mqtt_json"; #endif json["state_topic"] = mqtt_ha_state_out; json["command_topic"] = mqtt_ha_state_in; + #if !defined(MQTT_HOME_ASSISTANT_0_87_SUPPORT) json["on_command_type"] = "first"; + #endif json["brightness"] = "true"; json["rgb"] = "true"; json["optimistic"] = "false"; @@ -1041,28 +1287,37 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght #if defined(ENABLE_E131) effect_list.add("E131"); #endif - for (uint8_t i = 0; i < strip.getModeCount(); i++) { - effect_list.add(strip.getModeName(i)); + for (uint8_t i = 0; i < strip->getModeCount(); i++) { + effect_list.add(strip->getModeName(i)); } - char buffer[measureJson(json) + 1]; + // Following will never work for PubSubClient as message size > 1.6kB + // char buffer[measureJson(json) + 1]; + // serializeJson(json, buffer, sizeof(buffer)); + // mqtt_client->publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true); + + // Alternate way to publish large messages using PubSubClient + unsigned int msg_len = measureJson(json) + 1; + char buffer[msg_len]; serializeJson(json, buffer, sizeof(buffer)); - jsonBuffer.clear(); - mqtt_client.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), buffer, true); + + mqtt_client->beginPublish(mqtt_ha_config, msg_len, true); + mqtt_client->write((const uint8_t*)buffer, msg_len); + mqtt_client->endPublish(); #endif #endif - DBG_OUTPUT_PORT.printf("MQTT topic in: %s\n", mqtt_intopic); - DBG_OUTPUT_PORT.printf("MQTT topic out: %s\n", mqtt_outtopic); + DBG_OUTPUT_PORT.printf("MQTT topic in: %s\r\n", mqtt_intopic); + DBG_OUTPUT_PORT.printf("MQTT topic out: %s\r\n", mqtt_outtopic); } else { DBG_OUTPUT_PORT.print("failed, rc="); - DBG_OUTPUT_PORT.print(mqtt_client.state()); + DBG_OUTPUT_PORT.print(mqtt_client->state()); DBG_OUTPUT_PORT.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } if (mqtt_reconnect_retries >= MQTT_MAX_RECONNECT_TRIES) { - DBG_OUTPUT_PORT.printf("MQTT connection failed, giving up after %d tries ...\n", mqtt_reconnect_retries); + DBG_OUTPUT_PORT.printf("MQTT connection failed, giving up after %d tries ...\r\n", mqtt_reconnect_retries); } } #endif @@ -1076,7 +1331,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght void connectToMqtt() { DBG_OUTPUT_PORT.println("Connecting to MQTT..."); - amqttClient.connect(); + mqtt_client->connect(); } void onWifiConnect(const WiFiEventStationModeGotIP& event) { @@ -1100,27 +1355,29 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght char * message = new char[18 + strlen(HOSTNAME) + 1]; strcpy(message, "McLighting ready: "); strcat(message, HOSTNAME); - amqttClient.publish(mqtt_outtopic, qospub, false, message); + mqtt_client->publish(mqtt_outtopic, qospub, false, message); //Subscribe - uint16_t packetIdSub1 = amqttClient.subscribe((char *)mqtt_intopic, qossub); + uint16_t packetIdSub1 = mqtt_client->subscribe((char *)mqtt_intopic, qossub); DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub1); #if defined(ENABLE_HOMEASSISTANT) ha_send_data.detach(); - uint16_t packetIdSub2 = amqttClient.subscribe((char *)mqtt_ha_state_in, qossub); + uint16_t packetIdSub2 = mqtt_client->subscribe((char *)mqtt_ha_state_in, qossub); DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub2); #if defined(MQTT_HOME_ASSISTANT_SUPPORT) - const size_t bufferSize = JSON_ARRAY_SIZE(strip.getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; + const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject json = jsonBuffer.to(); json["name"] = HOSTNAME; - #if defined(MQTT_HOME_ASSISTANT_0_84_SUPPORT) + #if defined(MQTT_HOME_ASSISTANT_0_87_SUPPORT) json["schema"] = "json"; #else json["platform"] = "mqtt_json"; #endif json["state_topic"] = mqtt_ha_state_out; json["command_topic"] = mqtt_ha_state_in; + #if !defined(MQTT_HOME_ASSISTANT_0_87_SUPPORT) json["on_command_type"] = "first"; + #endif json["brightness"] = "true"; json["rgb"] = "true"; json["optimistic"] = "false"; @@ -1135,13 +1392,13 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght #if defined(ENABLE_E131) effect_list.add("E131"); #endif - for (uint8_t i = 0; i < strip.getModeCount(); i++) { - effect_list.add(strip.getModeName(i)); + for (uint8_t i = 0; i < strip->getModeCount(); i++) { + effect_list.add(strip->getModeName(i)); } char buffer[measureJson(json) + 1]; serializeJson(json, buffer, sizeof(buffer)); jsonBuffer.clear(); - amqttClient.publish(String("homeassistant/light/" + String(HOSTNAME) + "/config").c_str(), qospub, true, buffer); + mqtt_client->publish(mqtt_ha_config, qospub, true, buffer); #endif #endif } @@ -1178,7 +1435,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght // *************************************************************************** #if defined(ENABLE_BUTTON) void shortKeyPress() { - DBG_OUTPUT_PORT.printf("Short button press\n"); + DBG_OUTPUT_PORT.printf("Short button press\r\n"); if (mode == OFF) { setModeByStateString(BTN_MODE_SHORT); mode = SET_ALL; @@ -1189,14 +1446,14 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght // called when button is kept pressed for less than 2 seconds void mediumKeyPress() { - DBG_OUTPUT_PORT.printf("Medium button press\n"); + DBG_OUTPUT_PORT.printf("Medium button press\r\n"); setModeByStateString(BTN_MODE_MEDIUM); mode = SET_ALL; } // called when button is kept pressed for 2 seconds or more void longKeyPress() { - DBG_OUTPUT_PORT.printf("Long button press\n"); + DBG_OUTPUT_PORT.printf("Long button press\r\n"); setModeByStateString(BTN_MODE_LONG); mode = SET_ALL; } @@ -1231,18 +1488,18 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } } #endif - + #if defined(ENABLE_BUTTON_GY33) void shortKeyPress_gy33() { - DBG_OUTPUT_PORT.printf("Short GY-33 button press\n"); + DBG_OUTPUT_PORT.printf("Short GY-33 button press\r\n"); // tcs.setConfig(MCU_LED_04, MCU_WHITE_OFF); // delay(500); uint16_t red, green, blue, cl, ct, lux; tcs.getRawData(&red, &green, &blue, &cl, &lux, &ct); - DBG_OUTPUT_PORT.printf("Raw Colors: R: [%d] G: [%d] B: [%d] Clear: [%d] Lux: [%d] Colortemp: [%d]\n", (int)red, (int)green, (int)blue, (int)cl, (int)lux, (int)ct); + DBG_OUTPUT_PORT.printf("Raw Colors: R: [%d] G: [%d] B: [%d] Clear: [%d] Lux: [%d] Colortemp: [%d]\r\n", (int)red, (int)green, (int)blue, (int)cl, (int)lux, (int)ct); uint8_t r, g, b, col, conf; tcs.getData(&r, &g, &b, &col, &conf); - DBG_OUTPUT_PORT.printf("Colors: R: [%d] G: [%d] B: [%d] Color: [%d] Conf: [%d]\n", (int)r, (int)g, (int)b, (int)col, (int)conf); + DBG_OUTPUT_PORT.printf("Colors: R: [%d] G: [%d] B: [%d] Color: [%d] Conf: [%d]\r\n", (int)r, (int)g, (int)b, (int)col, (int)conf); main_color.red = (pow((r/255.0), 2.5)*255); main_color.green = (pow((g/255.0), 2.5)*255); main_color.blue = (pow((b/255.0), 2.5)*255);main_color.white = 0; ws2812fx_mode = 0; mode = SET_ALL; @@ -1294,128 +1551,132 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght void tickerSaveState(){ updateState = true; } - #if ENABLE_STATE_SAVE == 1 - bool updateFS = false; - - #if defined(ENABLE_MQTT) - // Write configuration to FS JSON - bool writeConfigFS(bool saveConfig){ - if (saveConfig) { - //FS save - updateFS = true; - DBG_OUTPUT_PORT.print("Saving config: "); - const size_t bufferSize = JSON_OBJECT_SIZE(4) + 150; - DynamicJsonDocument jsonBuffer(bufferSize); - JsonObject json = jsonBuffer.to(); - json["mqtt_host"] = mqtt_host; - json["mqtt_port"] = mqtt_port; - json["mqtt_user"] = mqtt_user; - json["mqtt_pass"] = mqtt_pass; - - //SPIFFS.remove("/config.json") ? DBG_OUTPUT_PORT.println("removed file") : DBG_OUTPUT_PORT.println("failed removing file"); - File configFile = SPIFFS.open("/config.json", "w"); - if (!configFile) DBG_OUTPUT_PORT.println("failed to open config file for writing"); - - serializeJson(json, DBG_OUTPUT_PORT); - serializeJson(json, configFile); - jsonBuffer.clear(); - configFile.close(); - updateFS = false; - return true; - //end save - } else { - DBG_OUTPUT_PORT.println("SaveConfig is False!"); - return false; - } + + #if ENABLE_STATE_SAVE == 1 + // Write configuration to FS JSON + bool writeConfigFS(bool saveConfig){ + if (saveConfig) { + //FS save + DBG_OUTPUT_PORT.println("Saving config: "); + File configFile = SPIFFS.open("/config.json", "w"); + if (!configFile) DBG_OUTPUT_PORT.println("failed to open config file for writing"); + DBG_OUTPUT_PORT.println(listConfigJSON()); + configFile.print(listConfigJSON()); + configFile.close(); + 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 - updateFS = true; - 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 buf(new char[size]); - configFile.readBytes(buf.get(), size); - const size_t bufferSize = JSON_OBJECT_SIZE(4) + 150; - DynamicJsonDocument jsonBuffer(bufferSize); - DeserializationError error = deserializeJson(jsonBuffer, buf.get()); - DBG_OUTPUT_PORT.print("Config: "); - if (!error) { - DBG_OUTPUT_PORT.println(" Parsed!"); - JsonObject json = jsonBuffer.as(); - serializeJson(json, DBG_OUTPUT_PORT); - strcpy(mqtt_host, json["mqtt_host"]); - strcpy(mqtt_port, json["mqtt_port"]); - strcpy(mqtt_user, json["mqtt_user"]); - strcpy(mqtt_pass, json["mqtt_pass"]); - updateFS = false; - jsonBuffer.clear(); - return true; - } else { - DBG_OUTPUT_PORT.print("Failed to load json config: "); - DBG_OUTPUT_PORT.println(error.c_str()); - jsonBuffer.clear(); - } + // 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 buf(new char[size]); + configFile.readBytes(buf.get(), size); + configFile.close(); + #if defined(ENABLE_MQTT) + const size_t bufferSize = JSON_OBJECT_SIZE(5) + 500; + #else + const size_t bufferSize = JSON_OBJECT_SIZE(1) + 150; + #endif + DynamicJsonDocument jsonBuffer(bufferSize); + DeserializationError error = deserializeJson(jsonBuffer, buf.get()); + DBG_OUTPUT_PORT.print("Config: "); + if (!error) { + DBG_OUTPUT_PORT.println("Parsed!"); + JsonObject json = jsonBuffer.as(); + serializeJson(json, DBG_OUTPUT_PORT); + DBG_OUTPUT_PORT.println(""); + strcpy(HOSTNAME, json["hostname"]); + #if defined(ENABLE_MQTT) + strcpy(mqtt_host, json["mqtt_host"]); + mqtt_port = (uint16_t) json["mqtt_port"]; + strcpy(mqtt_user, json["mqtt_user"]); + strcpy(mqtt_pass, json["mqtt_pass"]); + #endif + WS2812FXStripSettings.stripSize = (uint8_t) json["ws_cnt"]; + char tmp_rgbOrder[5]; + strcpy(tmp_rgbOrder, json["ws_rgbo"]); + checkRGBOrder(tmp_rgbOrder); + uint8_t temp_pin; + WS2812FXStripSettings.pin = (uint8_t) json["ws_pin"]; + WS2812FXStripSettings.fxoptions = (uint8_t) json["ws_fxopt"]; + jsonBuffer.clear(); + return true; } else { - DBG_OUTPUT_PORT.println("Failed to open /config.json"); + DBG_OUTPUT_PORT.print("Failed to load json config: "); + DBG_OUTPUT_PORT.println(error.c_str()); + jsonBuffer.clear(); } } else { - DBG_OUTPUT_PORT.println("Coudnt find config.json"); + DBG_OUTPUT_PORT.println("Failed to open /config.json"); } - //end read - updateFS = false; - return false; + } else { + DBG_OUTPUT_PORT.println("Coudnt find config.json"); + writeConfigFS(true); } - #endif + //end read + return false; + } - bool writeStateFS(){ - updateFS = true; - //save the strip state to FS JSON - DBG_OUTPUT_PORT.print("Saving cfg: "); - //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!"); - updateFS = false; + bool writeStateFS(bool saveConfig){ + if (saveConfig) { + //save the strip state to FS JSON + DBG_OUTPUT_PORT.print("Saving cfg: "); + //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!"); + settings_save_state.detach(); + updateState = false; + return false; + } + DBG_OUTPUT_PORT.println(listStatusJSON()); + configFile.print(listStatusJSON()); + configFile.close(); settings_save_state.detach(); updateState = false; + return true; + //end save + } else { + DBG_OUTPUT_PORT.println("SaveStateConfig is false!"); return false; } - DBG_OUTPUT_PORT.println(listStatusJSON()); - configFile.print(listStatusJSON()); - configFile.close(); - updateFS = false; - settings_save_state.detach(); - updateState = false; - return true; - //end save } bool readStateFS() { //read strip state from FS JSON - updateFS = true; //if (resetsettings) { SPIFFS.begin(); SPIFFS.remove("/config.json"); SPIFFS.format(); delay(1000);} if (SPIFFS.exists("/stripstate.json")) { //file exists, reading and loading - DBG_OUTPUT_PORT.print("Read cfg: "); + 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 buf(new char[size]); configFile.readBytes(buf.get(), size); + configFile.close(); const size_t bufferSize = JSON_OBJECT_SIZE(5) + JSON_ARRAY_SIZE(12) + 500; DynamicJsonDocument jsonBuffer(bufferSize); DeserializationError error = deserializeJson(jsonBuffer, buf.get()); + DBG_OUTPUT_PORT.print("Config: "); if (!error) { + DBG_OUTPUT_PORT.print("Parsed"); JsonObject json = jsonBuffer.as(); serializeJson(json, DBG_OUTPUT_PORT); + DBG_OUTPUT_PORT.println(""); mode = static_cast((int) json["mode"]); ws2812fx_mode = json["ws2812fx_mode"]; ws2812fx_speed = json["speed"]; @@ -1433,15 +1694,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght xtra_color.green = (uint8_t) json["color"][10]; xtra_color.blue = (uint8_t) json["color"][11]; convertColors(); - strip.setMode(ws2812fx_mode); - strip.setSpeed(convertSpeed(ws2812fx_speed)); - strip.setBrightness(brightness); - strip.setColors(0, hex_colors); - updateFS = false; jsonBuffer.clear(); return true; } else { - DBG_OUTPUT_PORT.println("Failed to parse JSON!"); + DBG_OUTPUT_PORT.print("Failed to load json config: "); + DBG_OUTPUT_PORT.println(error.c_str()); jsonBuffer.clear(); } } else { @@ -1449,9 +1706,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } } else { DBG_OUTPUT_PORT.println("Couldn't find \"/stripstate.json\""); + writeStateFS(true); } //end read - updateFS = false; return false; } #endif @@ -1467,12 +1724,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght res += char(EEPROM.read(i + offset)); //DBG_OUTPUT_PORT.println(char(EEPROM.read(i + offset))); } - DBG_OUTPUT_PORT.printf("readEEPROM(): %s\n", res.c_str()); + DBG_OUTPUT_PORT.printf("readEEPROM(): %s\r\n", res.c_str()); return res; } void writeEEPROM(int offset, int len, String value) { - DBG_OUTPUT_PORT.printf("writeEEPROM(): %s\n", value.c_str()); + DBG_OUTPUT_PORT.printf("writeEEPROM(): %s\r\n", value.c_str()); for (int i = 0; i < len; ++i) { if (i < value.length()) { @@ -1482,6 +1739,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght } } } + + + #endif #endif @@ -1724,7 +1984,7 @@ void handleRemote() { } // end of if HOLD if (results.value == rmt_commands[MODE_UP]) { //Mode Up last_remote_cmd = results.value; - if ((ws2812fx_mode < strip.getModeCount()-1) && (mode == HOLD)) { + if ((ws2812fx_mode < strip->getModeCount()-1) && (mode == HOLD)) { ws2812fx_mode = ws2812fx_mode + 1; } mode = SET_MODE; diff --git a/Arduino/McLighting/rest_api.h b/Arduino/McLighting/rest_api.h new file mode 100644 index 0000000..dbeb5a3 --- /dev/null +++ b/Arduino/McLighting/rest_api.h @@ -0,0 +1,448 @@ +// *************************************************************************** + // Setup: Webserver handler + // *************************************************************************** + //list directory + server.on("/list", HTTP_GET, handleFileList); + //create file + server.on("/edit", HTTP_PUT, handleFileCreate); + //delete file + server.on("/edit", HTTP_DELETE, handleFileDelete); + //first callback is called after the request has ended with all parsed arguments + //second callback handles file uploads at that location + server.on("/edit", HTTP_POST, []() { + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", ""); + }, handleFileUpload); + +// *************************************************************************** +// Setup: SPIFFS Webserver handler +// *************************************************************************** + + server.on("/", HTTP_GET, [&](){ +#if defined(USE_HTML_MIN_GZ) + server.sendHeader("Content-Encoding", "gzip", true); + server.send_P(200, PSTR("text/html"), index_htm_gz, index_htm_gz_len); +#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())) + handleNotFound(); + }); + + server.on("/upload", handleMinimalUpload); + + 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; + DynamicJsonDocument jsonBuffer(bufferSize); + JsonObject json = jsonBuffer.to(); + json["HOSTNAME"] = HOSTNAME; + json["version"] = SKETCH_VERSION; + json["heap"] = ESP.getFreeHeap(); + json["sketch_size"] = ESP.getSketchSize(); + json["free_sketch_space"] = ESP.getFreeSketchSpace(); + json["flash_chip_size"] = ESP.getFlashChipSize(); + json["flash_chip_real_size"] = ESP.getFlashChipRealSize(); + json["flash_chip_speed"] = ESP.getFlashChipSpeed(); + json["sdk_version"] = ESP.getSdkVersion(); + json["core_version"] = ESP.getCoreVersion(); + json["cpu_freq"] = ESP.getCpuFreqMHz(); + json["chip_id"] = ESP.getFlashChipId(); + #if defined(USE_WS2812FX_DMA) + #if USE_WS2812FX_DMA == 0 + json["animation_lib"] = "WS2812FX_DMA"; + #endif + #if USE_WS2812FX_DMA == 1 + json["animation_lib"] = "WS2812FX_UART1"; + #endif + #if USE_WS2812FX_DMA == 2 + json["animation_lib"] = "WS2812FX_UART2"; + #endif + #else + json["animation_lib"] = "WS2812FX"; + #endif + json["ws2812_pin"] = WS2812FXStripSettings.pin; + json["led_count"] = WS2812FXStripSettings.stripSize; + json["rgb_order"] = WS2812FXStripSettings.RGBOrder; + if (strstr(WS2812FXStripSettings.RGBOrder, "W") != NULL) { + json["rgbw_mode"] = "ON"; + } else { + json["rgbw_mode"] = "OFF"; + } + #if defined(ENABLE_BUTTON) + json["button_mode"] = "ON"; + json["button_pin"] = ENABLE_BUTTON; + #else + json["button_mode"] = "OFF"; + #endif + #if defined(ENABLE_BUTTON_GY33) + json["button_gy33"] = "ON"; + json["gy33_pin"] = ENABLE_BUTTON_GY33; + #else + json["button_gy33"] = "OFF"; + #endif + #if defined(ENABLE_REMOTE) + json["ir_remote"] = "ON"; + json["tsop_ir_pin"] = ENABLE_REMOTE; + #else + json["ir_remote"] = "OFF"; + #endif + #if defined(ENABLE_MQTT) + #if ENABLE_MQTT == 0 + json["mqtt"] = "MQTT"; + #endif + #if ENABLE_MQTT == 1 + json["mqtt"] = "AMQTT"; + #endif + #else + json["mqtt"] = "OFF"; + #endif + #if defined(ENABLE_HOMEASSISTANT) + json["home_assistant"] = "ON"; + #else + json["home_assistant"] = "OFF"; + #endif + #if defined(ENABLE_LEGACY_ANIMATIONS) + json["legacy_animations"] = "ON"; + #else + json["legacy_animations"] = "OFF"; + #endif + #if defined(ENABLE_TV) + json["tv_animation"] = "ON"; + #else + json["tv_animation"] = "OFF"; + #endif + #if defined(ENABLE_E131) + json["e131_animations"] = "ON"; + #else + json["e131_animations"] = "OFF"; + #endif + #if defined(ENABLE_OTA) + #if ENABLE_OTA == 0 + json["ota"] = "ARDUINO"; + #endif + #if ENABLE_OTA == 1 + json["ota"] = "HTTP"; + #endif + #else + json["ota"] = "OFF"; + #endif + #if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + json["state_save"] = "SPIFFS"; + #endif + #if ENABLE_STATE_SAVE == 0 + json["state_save"] = "EEPROM"; + #endif + #else + json["state_save"] = "OFF"; + #endif + + String json_str; + serializeJson(json, json_str); + jsonBuffer.clear(); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "application/json", json_str); + }); + + server.on("/restart", []() { + DBG_OUTPUT_PORT.printf("/restart\r\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", "restarting..." ); + ESP.restart(); + }); + + server.on("/reset_wlan", []() { + DBG_OUTPUT_PORT.printf("/reset_wlan\r\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", "Resetting WLAN and restarting..." ); + WiFiManager wifiManager; + wifiManager.resetSettings(); + ESP.restart(); + }); + + server.on("/start_config_ap", []() { + DBG_OUTPUT_PORT.printf("/start_config_ap\r\n"); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", "Starting config AP ..." ); + WiFiManager wifiManager; + wifiManager.startConfigPortal(HOSTNAME); + }); + + server.on("/format_spiffs", []() { + DBG_OUTPUT_PORT.printf("/format_spiffs\r\n"); + server.send(200, "text/plain", "Formatting SPIFFS ..." ); + SPIFFS.format(); + }); + + server.on("/set_brightness", []() { + getArgs(); + mode = SET_BRIGHTNESS; + getStatusJSON(); + }); + + server.on("/get_brightness", []() { + char str_brightness[4]; + snprintf(str_brightness, sizeof(str_brightness), "%i", (int) (brightness / 2.55)); + server.sendHeader("Access-Control-Allow-Origin", "*"); + server.send(200, "text/plain", str_brightness ); + DBG_OUTPUT_PORT.printf("/get_brightness: %i\r\n", (int) (brightness / 2.55)); + }); + + server.on("/set_speed", []() { + getArgs(); + mode = SET_SPEED; + getStatusJSON(); + }); + + server.on("/get_speed", []() { + char str_speed[4]; + snprintf(str_speed, sizeof(str_speed), "%i", ws2812fx_speed); + 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); + 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); + 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); + 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("/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 updateFSE = false; + if(server.hasArg("ws_cnt")){ + uint16_t pixelCt = server.arg("ws_cnt").toInt(); + if (pixelCt > 0) { + WS2812FXStripSettings.stripSize = pixelCt; + updateFSE = true; + } + } + if(server.hasArg("ws_rgbo")){ + char tmp_rgbOrder[5]; + snprintf(tmp_rgbOrder, sizeof(tmp_rgbOrder), "%s", server.arg("ws_rgbo").c_str()); + checkRGBOrder(tmp_rgbOrder); + updateFSE = true; + } + +#if !defined(USE_WS2812FX_DMA) + if(server.hasArg("wspin")){ + if (checkPin(server.arg("wspin").toInt()) { + updateFSE = true; + DBG_OUTPUT_PORT.println(WS2812FXStripSettings.pin); + } else { + DBG_OUTPUT_PORT.println("invalid input!"); + } + } +#endif + + if(server.hasArg("ws_fxopt")){ + WS2812FXStripSettings.fxoptions = server.arg("ws_fxopt").toInt(); + updateFSE = true; + } + + if(updateFSE) { + mode = INIT_STRIP; + } + + if(server.hasArg("hostname")){ + snprintf(HOSTNAME, sizeof(HOSTNAME), "%s", server.arg("hostname").c_str()); + updateFSE = true; + } + +#if defined(ENABLE_MQTT) + if(server.hasArg("mqtt_host")){ + snprintf(mqtt_host, sizeof(mqtt_host), "%s", server.arg("mqtt_host").c_str()); + updateFSE = true; + } + if(server.hasArg("mqtt_port")){ + if ((server.arg("mqtt_port").toInt() >= 0) && (server.arg("mqtt_port").toInt() <=65535)) { + mqtt_port = server.arg("mqttport").toInt(); + updateFSE = true; + } + } + if(server.hasArg("mqtt_user")){ + snprintf(mqtt_user, sizeof(mqtt_user), "%s", server.arg("mqtt_user").c_str()); + updateFSE = true; + } + if(server.hasArg("mqtt_pass")){ + snprintf(mqtt_pass, sizeof(mqtt_pass), "%s", server.arg("mqtt_pass").c_str()); + updateFSE = true; + } +#endif + +#if defined(ENABLE_STATE_SAVE) + #if ENABLE_STATE_SAVE == 1 + (writeConfigFS(updateFSE)) ? DBG_OUTPUT_PORT.println("Config FS Save success!"): DBG_OUTPUT_PORT.println("Config FS Save failure!"); + #endif + #if ENABLE_STATE_SAVE == 0 + if (updateFSE) { + char last_conf[223]; + #if defined(ENABLE_MQTT) + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, mqtt_host, mqtt_port, mqtt_user, mqtt_pass, WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #else + snprintf(last_conf, sizeof(last_conf), "CNF|%64s|%64s|%5d|%32s|%32s|%4d|%2d|%4s|%3d", HOSTNAME, "", "", "", "", WS2812FXStripSettings.stripSize, WS2812FXStripSettings.pin, WS2812FXStripSettings.RGBOrder, WS2812FXStripSettings.fxoptions); + #endif + writeEEPROM(0, 222, last_conf); + EEPROM.commit(); + } + #endif +#endif + getConfigJSON(); + delay(500); + +#if defined(ENABLE_MQTT) + if (updateFSE) { + initMqtt(); + } +#endif + + updateFSE = false; + }); + + server.on("/off", []() { + mode = OFF; + getStatusJSON(); + }); + + server.on("/auto", []() { + mode = AUTO; + getStatusJSON(); + }); + + server.on("/all", []() { + getArgs(); + ws2812fx_mode = FX_MODE_STATIC; + mode = SET_ALL; + getStatusJSON(); + }); + + #if defined(ENABLE_LEGACY_ANIMATIONS) + server.on("/wipe", []() { + getArgs(); + ws2812fx_mode = FX_MODE_COLOR_WIPE; + mode = SET_ALL; + getStatusJSON(); + }); + + server.on("/rainbow", []() { + getArgs(); + ws2812fx_mode = FX_MODE_RAINBOW; + mode = SET_ALL; + getStatusJSON(); + }); + + server.on("/rainbowcycle", []() { + getArgs(); + ws2812fx_mode = FX_MODE_RAINBOW_CYCLE; + mode = SET_ALL; + getStatusJSON(); + }); + + server.on("/theaterchase", []() { + getArgs(); + ws2812fx_mode = FX_MODE_THEATER_CHASE; + mode = SET_ALL; + getStatusJSON(); + }); + + server.on("/twinklerandom", []() { + getArgs(); + ws2812fx_mode = FX_MODE_TWINKLE_RANDOM; + mode = SET_ALL; + getStatusJSON(); + }); + + server.on("/theaterchaserainbow", []() { + getArgs(); + ws2812fx_mode = FX_MODE_THEATER_CHASE_RAINBOW; + mode = SET_ALL; + getStatusJSON(); + }); + #endif + + #if defined(ENABLE_E131) + server.on("/e131", []() { + mode = E131; + getStatusJSON(); + }); + #endif + + #if defined(ENABLE_TV) + server.on("/tv", []() { + mode = TV; + getStatusJSON(); + }); + #endif + + server.on("/get_modes", []() { + getModesJSON(); + }); + + server.on("/set_mode", []() { + getArgs(); + mode = SET_MODE; + getStatusJSON(); + }); diff --git a/Arduino/McLighting/version.h b/Arduino/McLighting/version.h index 827798a..d165c4f 100644 --- a/Arduino/McLighting/version.h +++ b/Arduino/McLighting/version.h @@ -1 +1 @@ -#define SKETCH_VERSION "2.2.0.rgbw.3c" +#define SKETCH_VERSION "2.2.2.rgbw.3c" diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino index b642a81..4ad988c 100644 --- a/Arduino/McLighting/version_info.ino +++ b/Arduino/McLighting/version_info.ino @@ -56,13 +56,74 @@ * 23 Dec 2018 v 2.2.0 * - Add E1.31 mode to getModes(), no need to change McLightingUI * - * 6 Jan 2018 v 2.2.0 + * 6 Jan 2019 v 2.2.0 * - fix webserver not responding when E1.31 is mode is acivated: do a webserver.loop() for every 1.31 packet * - HA E1.31 mode added - * - * 15 Feb 2018 v 2.2.0 rgbw 3colors + * + * 15 Feb 2019 v 2.2.0 rgbw 3colors * - Code cleanup * - Implemented support for back- and xtra-color * - Implemented IR remote control * - Remove some string data types (to be continued) + * + * 08 Mar 2018 v 2.2.1 rgbw 3colors + * - checkForRequests() is not needed + * - Minor fixes related to NeoPixelBus UART methods + * - Modify platformio.ini for future bump to esp8266-arduino v2.5.0 (shamelessly stolen settings from espurna project) + * - Gzipped index.htm & edit.htm, convereted to hex format using xxd -i abcd.gz > html_gz.h + * - Pointers added for WS2812FX & NeoPixelBus + * - new "REST API": /config?ws_cnt=xxx to change length of LED strip + * - new "REST API": /config?ws_rgbo=xxx to change RGB order + * - new "REST API": /config?ws_pin=GPIO_NO to change PIN# (Allowed GPIO values: 16/5/4/0/2/14/12/13/15/3/1) if not used DMA or UART. Otherwise it is ignored + * - added HA 0.87 version support https://github.com/toblum/McLighting/issues/327 + * - Added alternative way to send large messages using PubSubClient + * - Bump PIO core to 2.0.4 + * - Send HA state on MQTT connect, address https://github.com/toblum/McLighting/issues/349 + * - Add LWT for MQTT and AMQTT, address https://github.com/toblum/McLighting/issues/340 + * - Added file for custom WS2812FX animations in custom slots + * - Rename variables to be char instead of String + * - Added LED pixel count and PIN settings to WiFiManager + * - Gamma correction to LEDs via ws_fxopts + * + * 10 Mar 2019 v 2.2.2 rgbw 3colors + * - integraded neoconfig.json into config.json + * - Add compiler flag for WS2811 strips #define LED_TYPE_WS2811 + * - new "REST API": /config?hostname=xxx to change hostname + * - new "REST API": /config?mqtt_host=xxx to change mqtt hostname + * - new "REST API": /config?mqtt_port=xxx to change mqtt port + * - new "REST API": /config?mqtt_user=xxx to change mqtt username + * - new "REST API": /config?mqtt_pass=xxx to change mqtt password + * - new "REST API": /config?ws_fxopt=xxx to change ws2812fx options + * - Pointers added for PubSubClient & AMQTTCLient + * - RGBOrder is now stored human readable not as integer + * - Bugfix on Fire 2012 animation as one variable was destroyed + * + * 15 Mar 2019 v 2.2.2 rgbw 3colors + * websocket commands + * # Set Maincolor + * ## Set Back color + * ### Set xtra Color + * ? Set speed + * % Set brightness + * * Set all + * ! Set single LED + * + Set multiple LEDs + * R Set Range + * = Set named Mode (legacy) + * $ Get Status + * new from here + * C Get Config + * Ch Set hostname + * Cmh Set mqtt hostname + * Cmp Set mqtt port + * Cmu Set mqtt username + * Cmw Set mqtt password + * Csc Set Strip LED count + * Csr Set Strip RGB Order + * Csp Set Strip pin + * Cso Set Strip FX Options + * to here + * ~ Get Modes + * / Set modes + * */