diff --git a/tools/cdata.js b/tools/cdata.js index 201193f6..de6a98f8 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -333,6 +333,18 @@ const char PAGE_settings_dmx[] PROGMEM = R"=====()====="; "function GetV() {var d=document;\n" ), }, + { + file: "settings_um.htm", + name: "PAGE_settings_um", + prepend: "=====(", + append: ")=====", + method: "plaintext", + filter: "html-minify", + mangle: (str) => + str + .replace(/\/gms, "") + .replace(/\.*\<\/style\>/gms, "%CSS%%SCSS%") + } ], "wled00/html_settings.h" ); diff --git a/usermods/Animated_Staircase/Animated_Staircase.h b/usermods/Animated_Staircase/Animated_Staircase.h index 9717589d..cd43e7ec 100644 --- a/usermods/Animated_Staircase/Animated_Staircase.h +++ b/usermods/Animated_Staircase/Animated_Staircase.h @@ -9,25 +9,31 @@ */ #pragma once #include "wled.h" -#include "Animated_Staircase_config.h" + #define USERMOD_ID_ANIMATED_STAIRCASE 1011 -/* Initial configuration (available in API and stored in flash) */ -bool enabled = true; // Enable this usermod -unsigned long segment_delay_ms = 150; // Time between switching each segment -unsigned long on_time_ms = 5 * 1000; // The time for the light to stay on -#ifndef TOP_PIR_PIN -unsigned int topMaxTimeUs = 1749; // default echo timout, top -#endif -#ifndef BOTTOM_PIR_PIN -unsigned int bottomMaxTimeUs = 1749; // default echo timout, bottom -#endif - -// Time between checking of the sensors -const int scanDelay = 50; - class Animated_Staircase : public Usermod { private: + + /* configuration (available in API and stored in flash) */ + bool enabled = false; // Enable this usermod + unsigned long segment_delay_ms = 150; // Time between switching each segment + unsigned long on_time_ms = 5 * 1000; // The time for the light to stay on + int8_t topPIRorTriggerPin = -1; // disabled + int8_t bottomPIRorTriggerPin = -1; // disabled + int8_t topEchoPin = -1; // disabled + int8_t bottomEchoPin = -1; // disabled + bool useUSSensorTop = false; // using PIR or UltraSound sensor? + bool useUSSensorBottom = false; // using PIR or UltraSound sensor? + unsigned int topMaxTimeUs = 1749; // default echo timout, top + unsigned int bottomMaxTimeUs = 1749; // default echo timout, bottom + + /* runtime variables */ + bool initDone = false; + + // Time between checking of the sensors + const unsigned int scanDelay = 50; + // Lights on or off. // Flipping this will start a transition. bool on = false; @@ -63,8 +69,6 @@ class Animated_Staircase : public Usermod { byte maxSegmentId = 1; byte mainSegmentId = 0; - bool saveState = false; - // These values are used by the API to read the // last sensor state, or trigger a sensor // through the API @@ -73,9 +77,24 @@ class Animated_Staircase : public Usermod { bool bottomSensorRead = false; bool bottomSensorWrite = false; + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _segmentDelay[]; + static const char _onTime[]; + static const char _useTopUltrasoundSensor[]; + static const char _topPIRorTrigger_pin[]; + static const char _topEcho_pin[]; + static const char _useBottomUltrasoundSensor[]; + static const char _bottomPIRorTrigger_pin[]; + static const char _bottomEcho_pin[]; + static const char _topEchoTime[]; + static const char _bottomEchoTime[]; + static const char _[]; + void updateSegments() { - mainSegmentId = strip.getMainSegmentId(); - WS2812FX::Segment mainsegment = strip.getSegment(mainSegmentId); +// mainSegmentId = strip.getMainSegmentId(); +// WS2812FX::Segment mainsegment = strip.getSegment(mainSegmentId); WS2812FX::Segment* segments = strip.getSegments(); for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) { if (!segments->isActive()) { @@ -134,17 +153,15 @@ class Animated_Staircase : public Usermod { if ((millis() - lastScanTime) > scanDelay) { lastScanTime = millis(); -#ifdef BOTTOM_PIR_PIN - bottomSensorRead = bottomSensorWrite || (digitalRead(BOTTOM_PIR_PIN) == HIGH); -#else - bottomSensorRead = bottomSensorWrite || ultrasoundRead(BOTTOM_TRIGGER_PIN, BOTTOM_ECHO_PIN, bottomMaxTimeUs); -#endif + if (!useUSSensorBottom) + bottomSensorRead = bottomSensorWrite || (digitalRead(bottomPIRorTriggerPin) == HIGH); + else + bottomSensorRead = bottomSensorWrite || ultrasoundRead(bottomPIRorTriggerPin, bottomEchoPin, bottomMaxTimeUs); -#ifdef TOP_PIR_PIN - topSensorRead = topSensorWrite || (digitalRead(TOP_PIR_PIN) == HIGH); -#else - topSensorRead = topSensorWrite || ultrasoundRead(TOP_TRIGGER_PIN, TOP_ECHO_PIN, topMaxTimeUs); -#endif + if (!useUSSensorTop) + topSensorRead = topSensorWrite || (digitalRead(topPIRorTriggerPin) == HIGH); + else + topSensorRead = topSensorWrite || ultrasoundRead(topPIRorTriggerPin, topEchoPin, topMaxTimeUs); // Values read, reset the flags for next API call topSensorWrite = false; @@ -160,9 +177,9 @@ class Animated_Staircase : public Usermod { swipe = bottomSensorRead; if (swipe) { - Serial.println("ON -> Swipe up."); + DEBUG_PRINTLN(F("ON -> Swipe up.")); } else { - Serial.println("ON -> Swipe down."); + DEBUG_PRINTLN(F("ON -> Swipe down.")); } if (onIndex == offIndex) { @@ -181,15 +198,16 @@ class Animated_Staircase : public Usermod { } void autoPowerOff() { + // TODO: add logic to wait until PIR sensor deactivates if (on && ((millis() - lastSwitchTime) > on_time_ms)) { // Swipe OFF in the direction of the last sensor detection swipe = lastSensor; on = false; if (swipe) { - Serial.println("OFF -> Swipe up."); + DEBUG_PRINTLN(F("OFF -> Swipe up.")); } else { - Serial.println("OFF -> Swipe down."); + DEBUG_PRINTLN(F("OFF -> Swipe down.")); } } } @@ -198,8 +216,8 @@ class Animated_Staircase : public Usermod { if ((millis() - lastTime) > segment_delay_ms) { lastTime = millis(); - byte oldOnIndex = onIndex; - byte oldOffIndex = offIndex; +// byte oldOnIndex = onIndex; +// byte oldOffIndex = offIndex; if (on) { // Turn on all segments @@ -217,103 +235,44 @@ class Animated_Staircase : public Usermod { } } - void writeSettingsToJson(JsonObject& root) { - JsonObject staircase = root["staircase"]; - if (staircase.isNull()) { - staircase = root.createNestedObject("staircase"); - } - staircase["enabled"] = enabled; - staircase["segment-delay-ms"] = segment_delay_ms; - staircase["on-time-s"] = on_time_ms / 1000; - -#ifdef TOP_TRIGGER_PIN - staircase["top-echo-us"] = topMaxTimeUs; -#endif -#ifdef BOTTOM_TRIGGER_PIN - staircase["bottom-echo-us"] = bottomMaxTimeUs; -#endif + // send sesnor values to JSON API + void writeSensorsToJson(JsonObject& staircase) { + staircase[F("top-sensor")] = topSensorRead; + staircase[F("bottom-sensor")] = bottomSensorRead; } - void writeSensorsToJson(JsonObject& root) { - JsonObject staircase = root["staircase"]; - if (staircase.isNull()) { - staircase = root.createNestedObject("staircase"); - } - staircase["top-sensor"] = topSensorRead; - staircase["bottom-sensor"] = bottomSensorRead; - } - - bool readSettingsFromJson(JsonObject& root) { - JsonObject staircase = root["staircase"]; - bool changed = false; - - bool shouldEnable = staircase["enabled"] | enabled; - if (shouldEnable != enabled) { - enable(shouldEnable); - changed = true; - } - - unsigned long c_segment_delay_ms = staircase["segment-delay-ms"] | segment_delay_ms; - if (c_segment_delay_ms != segment_delay_ms) { - segment_delay_ms = c_segment_delay_ms; - changed = true; - } - - unsigned long c_on_time_ms = (staircase["on-time-s"] | (on_time_ms / 1000)) * 1000; - if (c_on_time_ms != on_time_ms) { - on_time_ms = c_on_time_ms; - changed = true; - } - -#ifdef TOP_TRIGGER_PIN - unsigned int c_topMaxTimeUs = staircase["top-echo-us"] | topMaxTimeUs; - if (c_topMaxTimeUs != topMaxTimeUs) { - topMaxTimeUs = c_topMaxTimeUs; - changed = true; - } -#endif -#ifdef BOTTOM_TRIGGER_PIN - unsigned int c_bottomMaxTimeUs = staircase["bottom-echo-us"] | bottomMaxTimeUs; - if (c_bottomMaxTimeUs != bottomMaxTimeUs) { - bottomMaxTimeUs = c_bottomMaxTimeUs; - changed = true; - } -#endif - - return changed; - } - - void readSensorsFromJson(JsonObject& root) { - JsonObject staircase = root["staircase"]; - bottomSensorWrite = bottomSensorRead || (staircase["bottom-sensor"].as()); - topSensorWrite = topSensorRead || (staircase["top-sensor"].as()); + // allow overrides from JSON API + void readSensorsFromJson(JsonObject& staircase) { + bottomSensorWrite = bottomSensorRead || (staircase[F("bottom-sensor")].as()); + topSensorWrite = topSensorRead || (staircase[F("top-sensor")].as()); } void enable(bool enable) { if (enable) { - Serial.println("Animated Staircase enabled."); - Serial.print("Delay between steps: "); - Serial.print(segment_delay_ms, DEC); - Serial.print(" milliseconds.\nStairs switch off after: "); - Serial.print(on_time_ms / 1000, DEC); - Serial.println(" seconds."); + DEBUG_PRINTLN(F("Animated Staircase enabled.")); + DEBUG_PRINT(F("Delay between steps: ")); + DEBUG_PRINT(segment_delay_ms); + DEBUG_PRINT(F(" milliseconds.\nStairs switch off after: ")); + DEBUG_PRINT(on_time_ms / 1000); + DEBUG_PRINTLN(F(" seconds.")); -#ifdef BOTTOM_PIR_PIN - pinMode(BOTTOM_PIR_PIN, INPUT); -#else - pinMode(BOTTOM_TRIGGER_PIN, OUTPUT); - pinMode(BOTTOM_ECHO_PIN, INPUT); -#endif + // TODO: attach interrupts + if (!useUSSensorBottom) + pinMode(bottomPIRorTriggerPin, INPUT); + else { + pinMode(bottomPIRorTriggerPin, OUTPUT); + pinMode(bottomEchoPin, INPUT); + } -#ifdef TOP_PIR_PIN - pinMode(TOP_PIR_PIN, INPUT); -#else - pinMode(TOP_TRIGGER_PIN, OUTPUT); - pinMode(TOP_ECHO_PIN, INPUT); -#endif + if (!useUSSensorTop) + pinMode(topPIRorTriggerPin, INPUT); + else { + pinMode(topPIRorTriggerPin, OUTPUT); + pinMode(topEchoPin, INPUT); + } } else { // Restore segment options - WS2812FX::Segment mainsegment = strip.getSegment(mainSegmentId); +// WS2812FX::Segment mainsegment = strip.getSegment(mainSegmentId); WS2812FX::Segment* segments = strip.getSegments(); for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) { if (!segments->isActive()) { @@ -323,47 +282,57 @@ class Animated_Staircase : public Usermod { segments->setOption(SEG_OPTION_ON, 1, 1); } colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE); - Serial.println("Animated Staircase disabled."); + DEBUG_PRINTLN(F("Animated Staircase disabled.")); } enabled = enable; } public: - void setup() { enable(enabled); } + void setup() { + // allocate pins + if (topPIRorTriggerPin >= 0) { + if (!pinManager.allocatePin(topPIRorTriggerPin,useUSSensorTop)) + topPIRorTriggerPin = -1; + } + if (topEchoPin >= 0) { + if (!pinManager.allocatePin(topEchoPin,false)) + topEchoPin = -1; + } + if (bottomPIRorTriggerPin >= 0) { + if (!pinManager.allocatePin(bottomPIRorTriggerPin,useUSSensorBottom)) + bottomPIRorTriggerPin = -1; + } + if (bottomEchoPin >= 0) { + if (!pinManager.allocatePin(bottomPIRorTriggerPin,false)) + bottomEchoPin = -1; + } + // TODO: attach interrupts in enable() + + // validate pins + if ( topPIRorTriggerPin < 0 || bottomPIRorTriggerPin < 0 || + (useUSSensorTop && topEchoPin < 0) || (useUSSensorBottom && bottomEchoPin < 0) ) + enabled = false; + + enable(enabled); + initDone = true; + } void loop() { - // Write changed settings from to flash (see readFromJsonState()) - if (saveState) { - serializeConfig(); - saveState = false; - } - - if (!enabled) { - return; - } - + if (!enabled) return; checkSensors(); autoPowerOff(); updateSwipe(); - } uint16_t getId() { return USERMOD_ID_ANIMATED_STAIRCASE; } - /* - * Shows configuration settings to the json API. This object looks like: - * - * "staircase" : { - * "enabled" : true - * "segment-delay-ms" : 150, - * "on-time-s" : 5 - * } - * - */ void addToJsonState(JsonObject& root) { - writeSettingsToJson(root); - writeSensorsToJson(root); - Serial.println("Staircase config exposed in API."); + JsonObject staircase = root[FPSTR(_name)]; + if (staircase.isNull()) { + staircase = root.createNestedObject(FPSTR(_name)); + } + writeSensorsToJson(staircase); + DEBUG_PRINTLN(F("Staircase sensor state exposed in API.")); } /* @@ -371,27 +340,107 @@ class Animated_Staircase : public Usermod { * See void addToJsonState(JsonObject& root) */ void readFromJsonState(JsonObject& root) { - // The call to serializeConfig() must be done in the main loop, - // so we set a flag to signal the main loop to save state. - saveState = readSettingsFromJson(root); - readSensorsFromJson(root); - Serial.println("Staircase config read from API."); + if (!initDone) return; // prevent crash on boot applyPreset() + JsonObject staircase = root[FPSTR(_name)]; + if (!staircase.isNull()) { + if (staircase[FPSTR(_enabled)].is()) { + enabled = staircase[FPSTR(_enabled)].as(); + } else { + String str = staircase[FPSTR(_enabled)]; // checkbox -> off or on + enabled = (bool)(str!="off"); // off is guaranteed to be present + } + readSensorsFromJson(root); + DEBUG_PRINTLN(F("Staircase sensor state read from API.")); + } } /* * Writes the configuration to internal flash memory. */ void addToConfig(JsonObject& root) { - writeSettingsToJson(root); - Serial.println("Staircase config saved."); + JsonObject staircase = root[FPSTR(_name)]; + if (staircase.isNull()) { + staircase = root.createNestedObject(FPSTR(_name)); + } + staircase[FPSTR(_enabled)] = enabled; + staircase[FPSTR(_segmentDelay)] = segment_delay_ms; + staircase[FPSTR(_onTime)] = on_time_ms / 1000; + staircase[FPSTR(_useTopUltrasoundSensor)] = useUSSensorTop; + staircase[FPSTR(_topPIRorTrigger_pin)] = topPIRorTriggerPin; + staircase[FPSTR(_topEcho_pin)] = useUSSensorTop ? topEchoPin : -1; + staircase[FPSTR(_useBottomUltrasoundSensor)] = useUSSensorBottom; + staircase[FPSTR(_bottomPIRorTrigger_pin)] = bottomPIRorTriggerPin; + staircase[FPSTR(_bottomEcho_pin)] = useUSSensorBottom ? bottomEchoPin : -1; + staircase[FPSTR(_topEchoTime)] = topMaxTimeUs; + staircase[FPSTR(_bottomEchoTime)] = bottomMaxTimeUs; + DEBUG_PRINTLN(F("Staircase config saved.")); } /* * Reads the configuration to internal flash memory before setup() is called. */ void readFromConfig(JsonObject& root) { - readSettingsFromJson(root); - Serial.println("Staircase config loaded."); + bool oldUseUSSensorTop = useUSSensorTop; + bool oldUseUSSensorBottom = useUSSensorBottom; + int8_t oldTopAPin = topPIRorTriggerPin; + int8_t oldTopBPin = topEchoPin; + int8_t oldBottomAPin = bottomPIRorTriggerPin; + int8_t oldBottomBPin = bottomEchoPin; + + JsonObject staircase = root[FPSTR(_name)]; + if (!staircase.isNull()) { + if (staircase[FPSTR(_enabled)].is()) { + enabled = staircase[FPSTR(_enabled)].as(); + } else { + String str = staircase[FPSTR(_enabled)]; // checkbox -> off or on + enabled = (bool)(str!="off"); // off is guaranteed to be present + } + segment_delay_ms = min(10000,max(10,staircase[FPSTR(_segmentDelay)].as())); // max delay 10s + on_time_ms = min(900,max(10,staircase[FPSTR(_onTime)].as())) * 1000; // min 10s, max 15min + + if (staircase[FPSTR(_useTopUltrasoundSensor)].is()) { + useUSSensorTop = staircase[FPSTR(_useTopUltrasoundSensor)].as(); + } else { + String str = staircase[FPSTR(_useTopUltrasoundSensor)]; // checkbox -> off or on + useUSSensorTop = (bool)(str!="off"); // off is guaranteed to be present + } + + topPIRorTriggerPin = min(39,max(-1,staircase[FPSTR(_topPIRorTrigger_pin)].as())); + topEchoPin = min(39,max(-1,staircase[FPSTR(_topEcho_pin)].as())); + + if (staircase[FPSTR(_useBottomUltrasoundSensor)].is()) { + useUSSensorBottom = staircase[FPSTR(_useBottomUltrasoundSensor)].as(); + } else { + String str = staircase[FPSTR(_useBottomUltrasoundSensor)]; // checkbox -> off or on + useUSSensorBottom = (bool)(str!="off"); // off is guaranteed to be present + } + bottomPIRorTriggerPin = min(39,max(-1,staircase[FPSTR(_bottomPIRorTrigger_pin)].as())); + bottomEchoPin = min(39,max(-1,staircase[FPSTR(_bottomEcho_pin)].as())); + topMaxTimeUs = min(18000,max(300,staircase[FPSTR(_topEchoTime)].as())); // max distnace ~3m (a noticable lag of 18ms may be expected) + bottomMaxTimeUs = min(18000,max(300,staircase[FPSTR(_bottomEchoTime)].as())); // max distance ~3m (a noticable lag of 18ms may be expected) + DEBUG_PRINTLN(F("Staircase config (re)loaded.")); + } else { + DEBUG_PRINTLN(F("No config found. (Using defaults.)")); + } + if (!initDone) { + // first run: reading from cfg.json + } else { + // changing paramters from settings page + bool changed = false; + if ((oldUseUSSensorTop != useUSSensorTop) || + (oldUseUSSensorBottom != useUSSensorBottom) || + (oldTopAPin != topPIRorTriggerPin) || + (oldTopBPin != topEchoPin) || + (oldBottomAPin != bottomPIRorTriggerPin) || + (oldBottomBPin != bottomEchoPin)) { + changed = true; + pinManager.deallocatePin(oldTopAPin); + pinManager.deallocatePin(oldTopBPin); + pinManager.deallocatePin(oldBottomAPin); + pinManager.deallocatePin(oldBottomBPin); + } + if (changed) setup(); + } } /* @@ -405,23 +454,33 @@ class Animated_Staircase : public Usermod { } if (enabled) { - JsonArray usermodEnabled = - staircase.createNestedArray("Staircase enabled"); // name + JsonArray usermodEnabled = staircase.createNestedArray(F("Staircase enabled")); // name usermodEnabled.add("yes"); // value - JsonArray segmentDelay = - staircase.createNestedArray("Delay between stairs"); // name + JsonArray segmentDelay = staircase.createNestedArray(F("Delay between stairs")); // name segmentDelay.add(segment_delay_ms); // value - segmentDelay.add(" milliseconds"); // unit + segmentDelay.add("ms"); // unit - JsonArray onTime = - staircase.createNestedArray("Power-off stairs after"); // name + JsonArray onTime = staircase.createNestedArray(F("Power-off stairs after")); // name onTime.add(on_time_ms / 1000); // value - onTime.add(" seconds"); // unit + onTime.add("s"); // unit } else { - JsonArray usermodEnabled = - staircase.createNestedArray("Staircase enabled"); // name + JsonArray usermodEnabled = staircase.createNestedArray(F("Staircase enabled")); // name usermodEnabled.add("no"); // value } } -}; \ No newline at end of file +}; + +// strings to reduce flash memory usage (used more than twice) +const char Animated_Staircase::_name[] PROGMEM = "staircase"; +const char Animated_Staircase::_enabled[] PROGMEM = "enabled"; +const char Animated_Staircase::_segmentDelay[] PROGMEM = "segment-delay-ms"; +const char Animated_Staircase::_onTime[] PROGMEM = "on-time-s"; +const char Animated_Staircase::_useTopUltrasoundSensor[] PROGMEM = "useTopUltrasoundSensor"; +const char Animated_Staircase::_topPIRorTrigger_pin[] PROGMEM = "topPIRorTrigger_pin"; +const char Animated_Staircase::_topEcho_pin[] PROGMEM = "topEcho_pin"; +const char Animated_Staircase::_useBottomUltrasoundSensor[] PROGMEM = "useBottomUltrasoundSensor"; +const char Animated_Staircase::_bottomPIRorTrigger_pin[] PROGMEM = "bottomPIRorTrigger_pin"; +const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin"; +const char Animated_Staircase::_topEchoTime[] PROGMEM = "top-echo-us"; +const char Animated_Staircase::_bottomEchoTime[] PROGMEM = "bottom-echo-us"; diff --git a/usermods/Animated_Staircase/Animated_Staircase_config.h b/usermods/Animated_Staircase/Animated_Staircase_config.h deleted file mode 100644 index 98050747..00000000 --- a/usermods/Animated_Staircase/Animated_Staircase_config.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Animated_Staircase compiletime confguration. - * - * Please see README.md on how to change this file. - */ - -// Please change the pin numbering below to match your board. -#define TOP_PIR_PIN D5 -#define BOTTOM_PIR_PIN D6 - -// Or uncumment and a pir and use an ultrasound HC-SR04 sensor, -// see README.md for details -#ifndef TOP_PIR_PIN -#define TOP_TRIGGER_PIN D2 -#define TOP_ECHO_PIN D3 -#endif - -#ifndef BOTTOM_PIR_PIN -#define BOTTOM_TRIGGER_PIN D4 -#define BOTTOM_ECHO_PIN D5 -#endif \ No newline at end of file diff --git a/usermods/Animated_Staircase/README.md b/usermods/Animated_Staircase/README.md index 1ee6c28c..fc755e00 100644 --- a/usermods/Animated_Staircase/README.md +++ b/usermods/Animated_Staircase/README.md @@ -20,44 +20,10 @@ Edit `usermods_list.cpp`: 2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file 3. add `usermods.add(new Animated_Staircase());` to the end of the `void registerUsermods()` function. -Edit `Animated_Staircase_config.h`: -1. Open `usermods/Animated_Staircase/Animated_Staircase_config.h` -2. To use PIR sensors, change these lines to match your setup: - Using D7 and D6 pin notation as used on several boards: - - ```cpp - #define TOP_PIR_PIN D7 - #define BOTTOM_PIR_PIN D6 - ``` - - Or using GPIO numbering for pins 25 and 26: - ```cpp - #define TOP_PIR_PIN 26 - #define BOTTOM_PIR_PIN 25 - ``` - - To use Ultrasonic HC-SR04 sensors instead of (one of the) PIR sensors, - uncomment one of the PIR sensor lines and adjust the pin numbers for the - connected Ultrasonic sensor. In the example below we use an Ultrasonic - sensor at the bottom of the stairs: - - ```cpp - #define TOP_PIR_PIN 32 - //#define BOTTOM_PIR_PIN D6 /* This PIR sensor is disabled */ - - #ifndef TOP_PIR_PIN - #define TOP_SIGNAL_PIN D2 - #define TOP_ECHO_PIN D3 - #endif - - #ifndef BOTTOM_PIR_PIN /* If the bottom PIR is disabled, */ - #define BOTTOM_SIGNAL_PIN 25 /* This Ultrasonic sensor is used */ - #define BOTTOM_ECHO_PIN 26 - #endif - ``` - -After these modifications, compile and upload your WLED binary to your board -and check the WLED info page to see if this usermod is enabled. +You can configure usermod using Usermods settings page. +Please enter GPIO pins for PIR sensors or ultrasonic sensor (trigger and echo). +If you use PIR sensor enter -1 for echo pin. +Maximum distance for ultrasonic sensor can be configured as a time needed for echo (see below). ## Hardware installation 1. Stick the LED strip under each step of the stairs. @@ -201,3 +167,7 @@ curl -X POST -H "Content-Type: application/json" \ Have fun with this usermod.
www.rolfje.com + +## Change log +2021-04 +* Adaptation for runtime configuration. \ No newline at end of file diff --git a/usermods/PIR_sensor_switch/readme.md b/usermods/PIR_sensor_switch/readme.md index 3d00b505..d6ea0fb0 100644 --- a/usermods/PIR_sensor_switch/readme.md +++ b/usermods/PIR_sensor_switch/readme.md @@ -10,27 +10,14 @@ The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wik ## Webinterface The info page in the web interface shows the items below - -- the state of the sensor. By clicking on the state the sensor can be deactivated/activated. Changes persist after a reboot. -**I recommend to deactivate the sensor before an OTA update and activate it again afterwards**. - the remaining time of the off timer. - -## JSON API - -The usermod supports the following state changes: - -| JSON key | Value range | Description | -|------------|-------------|---------------------------------| -| PIRenabled | bool | Deactivdate/activate the sensor | -| PIRoffSec | 60 to 43200 | Off timer seconds | - - Changes also persist after a reboot. +**I recommend to deactivate the sensor before an OTA update and activate it again afterwards**. ## Sensor connection My setup uses an HC-SR501 sensor, a HC-SR505 should also work. -The usermod uses GPIO13 (D1 mini pin D7) for the sensor signal. +The usermod uses GPIO13 (D1 mini pin D7) by default for the sensor signal but can be changed in the Usermod settings page. [This example page](http://www.esp8266learning.com/wemos-mini-pir-sensor-example.php) describes how to connect the sensor. Use the potentiometers on the sensor to set the time-delay to the minimum and the sensitivity to about half, or slightly above. @@ -76,8 +63,6 @@ void registerUsermods() ## API to enable/disable the PIR sensor from outside. For example from another usermod. -The class provides the static method `PIRsensorSwitch* PIRsensorSwitch::GetInstance()` to get a pointer to the usermod object. - To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` and `void EnablePIRsensor(bool enable)` are available. ### There are two options to get access to the usermod instance: @@ -98,12 +83,19 @@ class MyUsermod : public Usermod { //... void togglePIRSensor() { - if (PIRsensorSwitch::GetInstance() != nullptr) { - PIRsensorSwitch::GetInstance()->EnablePIRsensor(!PIRsensorSwitch::GetInstance()->PIRsensorEnabled()); + #ifdef USERMOD_PIR_SENSOR_SWITCH + PIRsensorSwitch *PIRsensor = (PIRsensorSwitch::*) usermods.lookup(USERMOD_ID_PIRSWITCH); + if (PIRsensor != nullptr) { + PIRsensor->EnablePIRsensor(!PIRsensor->PIRsensorEnabled()); } + #endif } //... }; ``` Have fun - @gegu + +## Change log +2021-04 +* Adaptation for runtime configuration. \ No newline at end of file diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h index 421528bf..19fcc2a9 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h @@ -2,6 +2,15 @@ #include "wled.h" +#ifndef PIR_SENSOR_PIN + // compatible with QuinLED-Dig-Uno + #ifdef ARDUINO_ARCH_ESP32 + #define PIR_SENSOR_PIN 23 // Q4 + #else //ESP8266 boards + #define PIR_SENSOR_PIN 13 // Q4 (D7 on D1 mini) + #endif +#endif + /* * This usermod handles PIR sensor states. * The strip will be switched on and the off timer will be resetted when the sensor goes HIGH. @@ -30,24 +39,11 @@ public: /** * constructor */ - PIRsensorSwitch() - { - // set static instance pointer - PIRsensorSwitchInstance(this); - } + PIRsensorSwitch() {} /** * desctructor */ - ~PIRsensorSwitch() - { - PIRsensorSwitchInstance(nullptr, true); - ; - } - - /** - * return the instance pointer of the class - */ - static PIRsensorSwitch *GetInstance() { return PIRsensorSwitchInstance(); } + ~PIRsensorSwitch() {} /** * Enable/Disable the PIR sensor @@ -60,19 +56,24 @@ public: private: // PIR sensor pin - const uint8_t PIRsensorPin = 13; // D7 on D1 mini + int8_t PIRsensorPin = PIR_SENSOR_PIN; // notification mode for colorUpdated() const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE // delay before switch off after the sensor state goes LOW - uint32_t m_switchOffDelay = 600000; + uint32_t m_switchOffDelay = 600000; // 10min // off timer start time uint32_t m_offTimerStart = 0; // current PIR sensor pin state byte m_PIRsensorPinState = LOW; // PIR sensor enabled - ISR attached bool m_PIRenabled = true; - // state if serializeConfig() should be called - bool m_updateConfig = false; + // status of initialisation + bool initDone = false; + + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _switchOffDelay[]; + static const char _enabled[]; /** * return or change if new PIR sensor state is available @@ -84,11 +85,6 @@ private: */ static void IRAM_ATTR ISR_PIRstateChange(); - /** - * Set/get instance pointer - */ - static PIRsensorSwitch *PIRsensorSwitchInstance(PIRsensorSwitch *pInstance = nullptr, bool bRemoveInstance = false); - /** * switch strip on/off */ @@ -107,6 +103,17 @@ private: } } + void publishMqtt(const char* state) + { + //Check if MQTT Connected, otherwise it will crash the 8266 + if (WLED_MQTT_CONNECTED){ + char subuf[64]; + strcpy(subuf, mqttDeviceTopic); + strcat_P(subuf, PSTR("/motion")); + mqtt->publish(subuf, 0, true, state); + } + } + /** * Read and update PIR sensor state. * Initilize/reset switch off timer @@ -121,6 +128,7 @@ private: { m_offTimerStart = 0; switchStrip(true); + publishMqtt("on"); } else if (bri != 0) { @@ -143,6 +151,7 @@ private: if (m_PIRenabled == true) { switchStrip(false); + publishMqtt("off"); } m_offTimerStart = 0; return true; @@ -159,13 +168,20 @@ public: */ void setup() { - // PIR Sensor mode INPUT_PULLUP - pinMode(PIRsensorPin, INPUT_PULLUP); - if (m_PIRenabled) - { - // assign interrupt function and set CHANGE mode - attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE); + // pin retrieved from cfg.json (readFromConfig()) prior to running setup() + if (!pinManager.allocatePin(PIRsensorPin,false)) { + PIRsensorPin = -1; // allocation failed + m_PIRenabled = false; + DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed.")); + } else { + // PIR Sensor mode INPUT_PULLUP + pinMode(PIRsensorPin, INPUT_PULLUP); + if (m_PIRenabled) { + // assign interrupt function and set CHANGE mode + attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE); + } } + initDone = true; } /** @@ -181,14 +197,8 @@ public: */ void loop() { - if (!updatePIRsensorState()) - { + if (!updatePIRsensorState()) { handleOffTimer(); - if (m_updateConfig) - { - serializeConfig(); - m_updateConfig = false; - } } } @@ -199,69 +209,70 @@ public: */ void addToJsonInfo(JsonObject &root) { - //this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object - // the value contains a button to toggle the sensor enabled/disabled JsonObject user = root["u"]; if (user.isNull()) user = root.createNestedObject("u"); - - JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name - String uiDomString = ""; + uiDomString += F(""); infoArr.add(uiDomString); //value - - //this code adds "u":{"⏲ switch off timer":uiDomString} to the info object - uiDomString = "⏲ switch off timer\ -after min"; - infoArr = user.createNestedArray(uiDomString); //name - - // off timer - if (m_offTimerStart > 0) +*/ + if (m_PIRenabled) { - uiDomString = ""; - unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000; - if (offSeconds >= 3600) +/* + JsonArray infoArr = user.createNestedArray(F("PIR switch-off timer after")); //name + String uiDomString = F("min"); + infoArr.add(uiDomString); +*/ + // off timer + String uiDomString = F("PIR "); + JsonArray infoArr = user.createNestedArray(uiDomString); // timer value + if (m_offTimerStart > 0) { - uiDomString += (offSeconds / 3600); - uiDomString += " hours "; - offSeconds %= 3600; + uiDomString = ""; + unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000; + if (offSeconds >= 3600) + { + uiDomString += (offSeconds / 3600); + uiDomString += F("h "); + offSeconds %= 3600; + } + if (offSeconds >= 60) + { + uiDomString += (offSeconds / 60); + offSeconds %= 60; + } + else if (uiDomString.length() > 0) + { + uiDomString += 0; + } + if (uiDomString.length() > 0) + { + uiDomString += F("min "); + } + uiDomString += (offSeconds); + infoArr.add(uiDomString + F("s")); + } else { + infoArr.add(F("inactive")); } - if (offSeconds >= 60) - { - uiDomString += (offSeconds / 60); - offSeconds %= 60; - } - else if (uiDomString.length() > 0) - { - uiDomString += 0; - } - if (uiDomString.length() > 0) - { - uiDomString += " min "; - } - uiDomString += (offSeconds); - infoArr.add(uiDomString + " sec"); - } - else - { - infoArr.add("inactive"); } } @@ -273,8 +284,8 @@ after ()))); - m_updateConfig = true; + if (root[FPSTR(_switchOffDelay)] != nullptr) { + m_switchOffDelay = (1000 * max(60UL, min(43200UL, root[FPSTR(_switchOffDelay)].as()))); + } +/* + if (root["pin"] != nullptr) { + int8_t pin = (int)root["pin"]; + // check if pin is OK + if (pin != PIRsensorPin && pin>=0 && pinManager.allocatePin(pin,false)) { + // deallocate old pin + pinManager.deallocatePin(PIRsensorPin); + // PIR Sensor mode INPUT_PULLUP + pinMode(pin, INPUT_PULLUP); + if (m_PIRenabled) + { + // remove old ISR + detachInterrupt(PIRsensorPin); + // assign interrupt function and set CHANGE mode + attachInterrupt(digitalPinToInterrupt(pin), ISR_PIRstateChange, CHANGE); + newPIRsensorState(true, true); + } + PIRsensorPin = pin; + } } - if (root["PIRenabled"] != nullptr) - { - if (root["PIRenabled"] && !m_PIRenabled) - { + if (root[FPSTR(_enabled)] != nullptr) { + if (root[FPSTR(_enabled)] && !m_PIRenabled && PIRsensorPin >= 0) { attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE); newPIRsensorState(true, true); - } - else if (m_PIRenabled) - { + } else if (m_PIRenabled && PIRsensorPin >= 0) { detachInterrupt(PIRsensorPin); } - m_PIRenabled = root["PIRenabled"]; - m_updateConfig = true; + m_PIRenabled = root[FPSTR(_enabled)]; } +*/ } /** @@ -312,19 +337,72 @@ after ())); // check bounds + } + + if (top[FPSTR(_enabled)] != nullptr) { + if (top[FPSTR(_enabled)].is()) { + m_PIRenabled = top[FPSTR(_enabled)].as(); // reading from cfg.json + } else { + // change from settings page + String str = top[FPSTR(_enabled)]; // checkbox -> off or on + m_PIRenabled = (bool)(str!="off"); // off is guaranteed to be present + } + } + + if (top[FPSTR(_switchOffDelay)] != nullptr) { + m_switchOffDelay = (top[FPSTR(_switchOffDelay)].as() * 1000); + } + + if (!initDone) { + // reading config prior to setup() + DEBUG_PRINTLN(F("PIR config loaded.")); + } else { + if (oldPin != PIRsensorPin || oldEnabled != m_PIRenabled) { + if (oldEnabled) { + // remove old ISR if disabling usermod + detachInterrupt(oldPin); + } + // check if pin is OK + if (oldPin != PIRsensorPin && oldPin >= 0) { + // if we are changing pin in settings page + // deallocate old pin + pinManager.deallocatePin(oldPin); + if (pinManager.allocatePin(PIRsensorPin,false)) { + pinMode(PIRsensorPin, INPUT_PULLUP); + } else { + // allocation failed + PIRsensorPin = -1; + m_PIRenabled = false; + } + } + if (m_PIRenabled) { + attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE); + newPIRsensorState(true, true); + } + DEBUG_PRINTLN(F("PIR config (re)loaded.")); + } + } } /** @@ -355,12 +433,7 @@ void IRAM_ATTR PIRsensorSwitch::ISR_PIRstateChange() newPIRsensorState(true, true); } -PIRsensorSwitch *PIRsensorSwitch::PIRsensorSwitchInstance(PIRsensorSwitch *pInstance, bool bRemoveInstance) -{ - static PIRsensorSwitch *s_pPIRsensorSwitch = nullptr; - if (pInstance != nullptr || bRemoveInstance) - { - s_pPIRsensorSwitch = pInstance; - } - return s_pPIRsensorSwitch; -} +// strings to reduce flash memory usage (used more than twice) +const char PIRsensorSwitch::_name[] PROGMEM = "PIRsensorSwitch"; +const char PIRsensorSwitch::_enabled[] PROGMEM = "PIRenabled"; +const char PIRsensorSwitch::_switchOffDelay[] PROGMEM = "PIRoffSec"; diff --git a/usermods/Temperature/readme.md b/usermods/Temperature/readme.md index 5b7f5b95..3cfc3a4c 100644 --- a/usermods/Temperature/readme.md +++ b/usermods/Temperature/readme.md @@ -14,10 +14,10 @@ Copy the example `platformio_override.ini` to the root directory. This file sho ### Define Your Options * `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp -* `USERMOD_DALLASTEMPERATURE_CELSIUS` - define this to report temperatures in degrees celsious, otherwise fahrenheit will be reported -* `USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL` - the number of milliseconds between measurements, defaults to 60 seconds * `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds +All parameters can be configured at runtime using Usermods settings page. + ## Project link * [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link @@ -41,10 +41,7 @@ default_envs = d1_mini ... lib_deps = ... - #For use SSD1306 OLED display uncomment following - U8g2@~2.27.3 - #For Dallas sensor uncomment following 2 lines - DallasTemperature@~3.8.0 + #For Dallas sensor uncomment following line OneWire@~2.3.5 ... ``` @@ -56,3 +53,5 @@ lib_deps = * Do not report low temperatures that indicate an error to mqtt * Disable plugin if temperature sensor not detected * Report the number of seconds until the first read in the info screen instead of sensor error +2021-04 +* Adaptation for runtime configuration. \ No newline at end of file diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index 9019fd17..8c639ae5 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -2,15 +2,16 @@ #include "wled.h" -#include //DS18B20 +//#include //DS18B20 +#include "OneWire.h" -//Pin defaults for QuinLed Dig-Uno +//Pin defaults for QuinLed Dig-Uno if not overriden #ifndef TEMPERATURE_PIN -#ifdef ARDUINO_ARCH_ESP32 -#define TEMPERATURE_PIN 18 -#else //ESP8266 boards -#define TEMPERATURE_PIN 14 -#endif + #ifdef ARDUINO_ARCH_ESP32 + #define TEMPERATURE_PIN 18 + #else //ESP8266 boards + #define TEMPERATURE_PIN 14 + #endif #endif // the frequency to check temperature, 1 minute @@ -20,19 +21,20 @@ // how many seconds after boot to take first measurement, 20 seconds #ifndef USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT -#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000 +#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000 #endif -OneWire oneWire(TEMPERATURE_PIN); -DallasTemperature sensor(&oneWire); - class UsermodTemperature : public Usermod { + private: - // The device's unique 64-bit serial code stored in on-board ROM. - // Reading directly from the sensor device address is faster than - // reading from index. When reading by index, DallasTemperature - // must first look up the device address at the specified index. - DeviceAddress sensorDeviceAddress; + + bool initDone = false; + OneWire *oneWire; + // GPIO pin used for sensor (with a default compile-time fallback) + int8_t temperaturePin = TEMPERATURE_PIN; + // measurement unit (true==°C, false==°F) + bool degC = true; + unsigned long readingInterval = USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL; // set last reading as "40 sec before boot", so first reading is taken after 20 sec unsigned long lastMeasurement = UINT32_MAX - (USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT); // last time requestTemperatures was called @@ -42,85 +44,120 @@ class UsermodTemperature : public Usermod { float temperature = -100; // default to -100, DS18B20 only goes down to -50C // indicates requestTemperatures has been called but the sensor measurement is not complete bool waitingForConversion = false; - // flag to indicate we have finished the first getTemperature call + // flag to indicate we have finished the first readTemperature call // allows this library to report to the user how long until the first // measurement - bool getTemperatureComplete = false; + bool readTemperatureComplete = false; // flag set at startup if DS18B20 sensor not found, avoids trying to keep getting // temperature if flashed to a board without a sensor attached bool disabled = false; - void requestTemperatures() { - // there is requestTemperaturesByAddress however it - // appears to do more work, - // TODO: measure exection time difference - sensor.requestTemperatures(); - lastTemperaturesRequest = millis(); - waitingForConversion = true; + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _readInterval[]; + + //Dallas sensor quick (& dirty) reading. Credit to - Author: Peter Scargill, August 17th, 2013 + int16_t readDallas() { + byte i; + byte data[2]; + int16_t result; // raw data from sensor + oneWire->reset(); + oneWire->write(0xCC); // skip ROM + oneWire->write(0xBE); // read (temperature) from EEPROM + for (i=0; i < 2; i++) data[i] = oneWire->read(); // first 2 bytes contain temperature + for (i=2; i < 8; i++) oneWire->read(); // read unused bytes + result = (data[1]<<8) | data[0]; + result >>= 4; // 9-bit precision accurate to 1°C (/16) + if (data[1]&0x80) result |= 0xF000; // fix negative value + //if (data[0]&0x08) ++result; + oneWire->reset(); + oneWire->write(0xCC); // skip ROM + oneWire->write(0x44,0); // request new temperature reading (without parasite power) + return result; } - void getTemperature() { - if (strip.isUpdating()) return; - #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS - temperature = sensor.getTempC(sensorDeviceAddress); - #else - temperature = sensor.getTempF(sensorDeviceAddress); - #endif + void requestTemperatures() { + readDallas(); + lastTemperaturesRequest = millis(); + waitingForConversion = true; + DEBUG_PRINTLN(F("Requested temperature.")); + } + void readTemperature() { + temperature = readDallas(); lastMeasurement = millis(); waitingForConversion = false; - getTemperatureComplete = true; + readTemperatureComplete = true; + DEBUG_PRINTF("Read temperature %2.1f.\n", temperature); + } + + bool findSensor() { + DEBUG_PRINTLN(F("Searching for sensor...")); + uint8_t deviceAddress[8] = {0,0,0,0,0,0,0,0}; + // find out if we have DS18xxx sensor attached + oneWire->reset_search(); + while (oneWire->search(deviceAddress)) { + if (oneWire->crc8(deviceAddress, 7) == deviceAddress[7]) { + switch (deviceAddress[0]) { + case 0x10: // DS18S20 + case 0x22: // DS18B20 + case 0x28: // DS1822 + case 0x3B: // DS1825 + case 0x42: // DS28EA00 + DEBUG_PRINTLN(F("Sensor found.")); + return true; + } + } + } + return false; } public: - void setup() { - sensor.begin(); - - // get the unique 64-bit serial code stored in on-board ROM - // if getAddress returns false, the sensor was not found - disabled = !sensor.getAddress(sensorDeviceAddress, 0); - - if (!disabled) { - DEBUG_PRINTLN(F("Dallas Temperature found")); - // set the resolution for this specific device - sensor.setResolution(sensorDeviceAddress, 9, true); - // do not block waiting for reading - sensor.setWaitForConversion(false); - // allocate pin & prevent other use - if (!pinManager.allocatePin(TEMPERATURE_PIN,false)) - disabled = true; + int retries = 10; + // pin retrieved from cfg.json (readFromConfig()) prior to running setup() + if (!pinManager.allocatePin(temperaturePin,false)) { + temperaturePin = -1; // allocation failed + disabled = true; + DEBUG_PRINTLN(F("Temperature pin allocation failed.")); } else { - DEBUG_PRINTLN(F("Dallas Temperature not found")); + if (!disabled) { + // config says we are enabled + oneWire = new OneWire(temperaturePin); + if (!oneWire->reset()) + disabled = true; // resetting 1-Wire bus yielded an error + else + while ((disabled=!findSensor()) && retries--) delay(25); // try to find sensor + } } + initDone = true; } void loop() { if (disabled || strip.isUpdating()) return; - + unsigned long now = millis(); // check to see if we are due for taking a measurement // lastMeasurement will not be updated until the conversion // is complete the the reading is finished - if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL) return; + if (now - lastMeasurement < readingInterval) return; - // we are due for a measurement, if we are not already waiting + // we are due for a measurement, if we are not already waiting // for a conversion to complete, then make a new request for temps - if (!waitingForConversion) - { + if (!waitingForConversion) { requestTemperatures(); return; } // we were waiting for a conversion to complete, have we waited log enough? - if (now - lastTemperaturesRequest >= 94 /* 93.75ms per the datasheet */) - { - getTemperature(); - + if (now - lastTemperaturesRequest >= 100 /* 93.75ms per the datasheet but can be up to 750ms */) { + readTemperature(); + if (WLED_MQTT_CONNECTED) { - char subuf[45]; + char subuf[64]; strcpy(subuf, mqttDeviceTopic); if (-100 <= temperature) { // dont publish super low temperature as the graph will get messed up @@ -128,6 +165,8 @@ class UsermodTemperature : public Usermod { // reading the sensor strcat_P(subuf, PSTR("/temperature")); mqtt->publish(subuf, 0, true, String(temperature).c_str()); + strcat_P(subuf, PSTR("_f")); + mqtt->publish(subuf, 0, true, String((float)temperature * 1.8f + 32).c_str()); } else { // publish something else to indicate status? } @@ -135,16 +174,32 @@ class UsermodTemperature : public Usermod { } } + /* + * API calls te enable data exchange between WLED modules + */ + inline float getTemperatureC() { + return (float)temperature; + } + inline float getTemperatureF() { + return (float)temperature * 1.8f + 32; + } + + /* + * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. + * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. + * Below it is shown how this could be used for e.g. a light sensor + */ void addToJsonInfo(JsonObject& root) { // dont add temperature to info if we are disabled if (disabled) return; - JsonObject user = root[F("u")]; - if (user.isNull()) user = root.createNestedObject(F("u")); + JsonObject user = root["u"]; + if (user.isNull()) user = root.createNestedObject("u"); - JsonArray temp = user.createNestedArray(F("Temperature")); + JsonArray temp = user.createNestedArray(FPSTR(_name)); + //temp.add(F("Loaded.")); - if (!getTemperatureComplete) { + if (!readTemperatureComplete) { // if we haven't read the sensor yet, let the user know // that we are still waiting for the first measurement temp.add((USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - millis()) / 1000); @@ -158,12 +213,85 @@ class UsermodTemperature : public Usermod { return; } - temp.add(temperature); - #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS - temp.add(F("°C")); - #else - temp.add(F("°F")); - #endif + temp.add(degC ? temperature : (float)temperature * 1.8f + 32); + if (degC) temp.add(F("°C")); + else temp.add(F("°F")); + } + + /** + * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + */ + //void addToJsonState(JsonObject &root) + //{ + //} + + /** + * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + * Read "_" from json state and and change settings (i.e. GPIO pin) used. + */ + //void readFromJsonState(JsonObject &root) { + // if (!initDone) return; // prevent crash on boot applyPreset() + //} + + /** + * addToConfig() (called from set.cpp) stores persistent properties to cfg.json + */ + void addToConfig(JsonObject &root) { + // we add JSON object: {"Temperature": {"pin": 0, "degC": true}} + JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname + top[FPSTR(_enabled)] = !disabled; + top["pin"] = temperaturePin; // usermodparam + top["degC"] = degC; // usermodparam + top[FPSTR(_readInterval)] = readingInterval / 1000; + DEBUG_PRINTLN(F("Temperature config saved.")); + } + + /** + * readFromConfig() is called before setup() to populate properties from values stored in cfg.json + */ + void readFromConfig(JsonObject &root) { + // we look for JSON object: {"Temperature": {"pin": 0, "degC": true}} + JsonObject top = root[FPSTR(_name)]; + int8_t newTemperaturePin = temperaturePin; + + if (!top.isNull() && top["pin"] != nullptr) { + if (top[FPSTR(_enabled)].is()) { + disabled = !top[FPSTR(_enabled)].as(); + } else { + String str = top[FPSTR(_enabled)]; // checkbox -> off or on + disabled = (bool)(str=="off"); // off is guaranteed to be present + } + newTemperaturePin = min(39,max(-1,top["pin"].as())); + if (top["degC"].is()) { + // reading from cfg.json + degC = top["degC"].as(); + } else { + // new configuration from set.cpp + String str = top["degC"]; // checkbox -> off or on + degC = (bool)(str!="off"); // off is guaranteed to be present + } + readingInterval = min(120,max(10,top[FPSTR(_readInterval)].as())) * 1000; // convert to ms + DEBUG_PRINTLN(F("Temperature config (re)loaded.")); + } else { + DEBUG_PRINTLN(F("No config found. (Using defaults.)")); + } + + if (!initDone) { + // first run: reading from cfg.json + temperaturePin = newTemperaturePin; + } else { + // changing paramters from settings page + if (newTemperaturePin != temperaturePin) { + // deallocate pin and release memory + delete oneWire; + pinManager.deallocatePin(temperaturePin); + temperaturePin = newTemperaturePin; + // initialise + setup(); + } + } } uint16_t getId() @@ -171,3 +299,8 @@ class UsermodTemperature : public Usermod { return USERMOD_ID_TEMPERATURE; } }; + +// strings to reduce flash memory usage (used more than twice) +const char UsermodTemperature::_name[] PROGMEM = "Temperature"; +const char UsermodTemperature::_enabled[] PROGMEM = "enabled"; +const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s"; \ No newline at end of file diff --git a/usermods/multi_relay/readme.md b/usermods/multi_relay/readme.md new file mode 100644 index 00000000..eab5a00c --- /dev/null +++ b/usermods/multi_relay/readme.md @@ -0,0 +1,55 @@ +# Multi Relay + +This usermod-v2 modification allows the connection of multiple relays each with individual delay and on/off mode. + +## Usermod installation + +1. Register the usermod by adding `#include "../usermods/multi_relay/usermod_multi_relay.h"` at the top and `usermods.add(new MultiRelay());` at the bottom of `usermods_list.cpp`. +or +2. Use `#define USERMOD_MULTI_RELAY` in wled.h or `-D USERMOD_MULTI_RELAY`in your platformio.ini + +You can override the default maximum number (4) of relays by defining MULTI_RELAY_MAX_RELAYS. + +Example **usermods_list.cpp**: + +```cpp +#include "wled.h" +/* + * Register your v2 usermods here! + * (for v1 usermods using just usermod.cpp, you can ignore this file) + */ + +/* + * Add/uncomment your usermod filename here (and once more below) + * || || || + * \/ \/ \/ + */ +//#include "usermod_v2_example.h" +//#include "usermod_temperature.h" +#include "../usermods/usermod_multi_relay.h" + +void registerUsermods() +{ + /* + * Add your usermod class name here + * || || || + * \/ \/ \/ + */ + //usermods.add(new MyExampleUsermod()); + //usermods.add(new UsermodTemperature()); + usermods.add(new MultiRelay()); + +} +``` + +## Configuration + +Usermod can be configured in Usermods settings page. + +If there is no MultiRelay section, just save current configuration and re-open Usermods settings page. + +Have fun - @blazoncek + +## Change log +2021-04 +* First implementation. \ No newline at end of file diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h new file mode 100644 index 00000000..8d2861ba --- /dev/null +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -0,0 +1,434 @@ +#pragma once + +#include "wled.h" + +#ifndef MULTI_RELAY_MAX_RELAYS + #define MULTI_RELAY_MAX_RELAYS 4 +#endif + +#define ON true +#define OFF false + +/* + * This usermod handles multiple relay outputs. + * These outputs complement built-in relay output in a way that the activation can be delayed. + * They can also activate/deactivate in reverse logic independently. + */ + + +typedef struct relay_t { + int8_t pin; + bool active; + bool mode; + bool state; + bool external; + uint16_t delay; +} Relay; + + +class MultiRelay : public Usermod { + + private: + // array of relays + Relay _relay[MULTI_RELAY_MAX_RELAYS]; + + // switch timer start time + uint32_t _switchTimerStart = 0; + // old brightness + uint8_t _oldBrightness = 0; + + // usermod enabled + bool enabled = false; // needs to be configured (no default config) + // status of initialisation + bool initDone = false; + + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _relay_str[]; + static const char _delay_str[]; + static const char _activeHigh[]; + static const char _external[]; + + + void publishMqtt(const char* state, int relay) { + //Check if MQTT Connected, otherwise it will crash the 8266 + if (WLED_MQTT_CONNECTED){ + char subuf[64]; + sprintf_P(subuf, PSTR("%s/relay/%d"), mqttDeviceTopic, relay); + mqtt->publish(subuf, 0, true, state); + } + } + + /** + * switch off the strip if the delay has elapsed + */ + void handleOffTimer() { + bool activeRelays = false; + for (uint8_t i=0; i 0 && millis() - _switchTimerStart > (_relay[i].delay*1000)) { + if (!_relay[i].external) toggleRelay(i); + _relay[i].active = false; + } + activeRelays = activeRelays || _relay[i].active; + } + if (!activeRelays) _switchTimerStart = 0; + } + + /** + * HTTP API handler + * borrowed from: + * https://github.com/gsieben/WLED/blob/master/usermods/GeoGab-Relays/usermod_GeoGab.h + */ + #define GEOGABVERSION "0.1.3" + void InitHtmlAPIHandle() { // https://github.com/me-no-dev/ESPAsyncWebServer + DEBUG_PRINTLN(F("Relays: Initialize HTML API")); + + server.on("/relays", HTTP_GET, [this](AsyncWebServerRequest *request) { + DEBUG_PRINTLN("Relays: HTML API"); + String janswer; + String error = ""; + int params = request->params(); + janswer = F("{\"NoOfRelays\":"); + janswer += String(MULTI_RELAY_MAX_RELAYS) + ","; + + if (getActiveRelayCount()) { + // Commands + if(request->hasParam("switch")) { + /**** Switch ****/ + AsyncWebParameter* p = request->getParam("switch"); + // Get Values + for (int i=0; ivalue(), ',', i); + if (value==-1) { + error = F("There must be as much arugments as relays"); + } else { + // Switch + if (_relay[i].external) switchRelay(i, (bool)value); + } + } + } else if(request->hasParam("toggle")) { + /**** Toggle ****/ + AsyncWebParameter* p = request->getParam("toggle"); + // Get Values + for (int i=0;ivalue(), ',', i); + if (value==-1) { + error = F("There must be as mutch arugments as relays"); + } else { + // Toggle + if (value && _relay[i].external) toggleRelay(i); + } + } + } else { + error = F("No valid command found"); + } + } else { + error = F("No active relays"); + } + + // Status response + char sbuf[16]; + for (int i=0; isend(200, "application/json", janswer); + }); + } + + int getValue(String data, char separator, int index) { + int found = 0; + int strIndex[] = {0, -1}; + int maxIndex = data.length()-1; + + for(int i=0; i<=maxIndex && found<=index; i++){ + if(data.charAt(i)==separator || i==maxIndex){ + found++; + strIndex[0] = strIndex[1]+1; + strIndex[1] = (i == maxIndex) ? i+1 : i; + } + } + return found>index ? data.substring(strIndex[0], strIndex[1]).toInt() : -1; + } + + public: + /** + * constructor + */ + MultiRelay() { + for (uint8_t i=0; i=MULTI_RELAY_MAX_RELAYS || _relay[relay].pin<0) return; + _relay[relay].state = mode; + pinMode(_relay[relay].pin, OUTPUT); + digitalWrite(_relay[relay].pin, mode ? !_relay[relay].mode : _relay[relay].mode); + publishMqtt(mode ? "on" : "off", relay); + } + + /** + * toggle relay + */ + inline void toggleRelay(uint8_t relay) { + switchRelay(relay, !_relay[relay].state); + } + + uint8_t getActiveRelayCount() { + uint8_t count = 0; + for (uint8_t i=0; i=0) count++; + return count; + } + + //Functions called by WLED + + /** + * handling of MQTT message + * topic only contains stripped topic (part after /wled/MAC) + * topic should look like: /relay/X/command; where X is relay number, 0 based + */ + bool onMqttMessage(char* topic, char* payload) { + if (strlen(topic) > 8 && strncmp_P(topic, PSTR("/relay/"), 7) == 0 && strncmp_P(topic+8, PSTR("/command"), 8) == 0) { + uint8_t relay = strtoul(topic+7, NULL, 10); + if (relaysubscribe(subuf, 0); + } + } + + /** + * setup() is called once at boot. WiFi is not yet connected at this point. + * You can use it to initialize variables, sensors or similar. + */ + void setup() { + // pins retrieved from cfg.json (readFromConfig()) prior to running setup() + for (uint8_t i=0; i=0) _relay[i].active = true; + } + } + + handleOffTimer(); + } + + /** + * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. + */ + void addToJsonInfo(JsonObject &root) { + if (enabled) { + JsonObject user = root["u"]; + if (user.isNull()) + user = root.createNestedObject("u"); + + JsonArray infoArr = user.createNestedArray(F("Number of relays")); //name + infoArr.add(String(getActiveRelayCount())); + } + } + + /** + * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + */ + void addToJsonState(JsonObject &root) { + } + + /** + * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + */ + void readFromJsonState(JsonObject &root) { + } + + /** + * provide the changeable values + */ + void addToConfig(JsonObject &root) { + JsonObject top = root.createNestedObject(FPSTR(_name)); + + top[FPSTR(_enabled)] = enabled; + for (uint8_t i=0; i()) { + enabled = top[FPSTR(_enabled)].as(); // reading from cfg.json + } else { + // change from settings page + String str = top[FPSTR(_enabled)]; // checkbox -> off or on + enabled = (bool)(str!="off"); // off is guaranteed to be present + } + } + + for (uint8_t i=0; i())); + + if (top[parName+FPSTR(_activeHigh)] != nullptr) { + if (top[parName+FPSTR(_activeHigh)].is()) { + _relay[i].mode = top[parName+FPSTR(_activeHigh)].as(); // reading from cfg.json + } else { + // change from settings page + String str = top[parName+FPSTR(_activeHigh)]; // checkbox -> off or on + _relay[i].mode = (bool)(str!="off"); // off is guaranteed to be present + } + } + + if (top[parName+FPSTR(_external)] != nullptr) { + if (top[parName+FPSTR(_external)].is()) { + _relay[i].external = top[parName+FPSTR(_external)].as(); // reading from cfg.json + } else { + // change from settings page + String str = top[parName+FPSTR(_external)]; // checkbox -> off or on + _relay[i].external = (bool)(str!="off"); // off is guaranteed to be present + } + } + + _relay[i].delay = min(600,max(0,abs(top[parName+FPSTR(_delay_str)].as()))); + } + + if (!initDone) { + // reading config prior to setup() + DEBUG_PRINTLN(F("MultiRelay config loaded.")); + } else { + // deallocate all pins 1st + for (uint8_t i=0; i=0) { + pinManager.deallocatePin(oldPin[i]); + } + // allocate new pins + for (uint8_t i=0; i=0 && pinManager.allocatePin(_relay[i].pin,true)) { + if (!_relay[i].external) switchRelay(i, _relay[i].state = (bool)bri); + } else { + _relay[i].pin = -1; + } + _relay[i].active = false; + } + DEBUG_PRINTLN(F("MultiRelay config (re)loaded.")); + } + } + + /** + * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). + * This could be used in the future for the system to determine whether your usermod is installed. + */ + uint16_t getId() + { + return USERMOD_ID_MULTI_RELAY; + } +}; + +// strings to reduce flash memory usage (used more than twice) +const char MultiRelay::_name[] PROGMEM = "MultiRelay"; +const char MultiRelay::_enabled[] PROGMEM = "enabled"; +const char MultiRelay::_relay_str[] PROGMEM = "relay"; +const char MultiRelay::_delay_str[] PROGMEM = "delay-s"; +const char MultiRelay::_activeHigh[] PROGMEM = "active-high"; +const char MultiRelay::_external[] PROGMEM = "external"; diff --git a/usermods/usermod_v2_auto_save/readme.md b/usermods/usermod_v2_auto_save/readme.md index 5c835c60..7cf81085 100644 --- a/usermods/usermod_v2_auto_save/readme.md +++ b/usermods/usermod_v2_auto_save/readme.md @@ -29,9 +29,9 @@ This file should be placed in the same directory as `platformio.ini`. ### Define Your Options * `USERMOD_AUTO_SAVE` - define this to have this the Auto Save usermod included wled00\usermods_list.cpp -* `USERMOD_FOUR_LINE_DISLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details) -* `AUTOSAVE_SETTLE_MS` - Minimum time to wave before auto saving, defaults to 10000 (10s) -* `AUTOSAVE_PRESET_NUM` - Preset number to auto-save to, auto-load at startup from, defaults to 99 +* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details) + +You can configure auto-save parameters using Usermods settings page. ### PlatformIO requirements @@ -43,3 +43,5 @@ Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`. 2021-02 * First public release +2021-04 +* Adaptation for runtime configuration. \ No newline at end of file diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h index bd7ea6d8..caf542e5 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h @@ -2,9 +2,8 @@ #include "wled.h" -// // v2 Usermod to automatically save settings -// to preset number AUTOSAVE_PRESET_NUM after a change to any of +// to configurable preset after a change to any of // // * brightness // * effect speed @@ -12,45 +11,34 @@ // * mode (effect) // * palette // -// but it will wait for AUTOSAVE_SETTLE_MS milliseconds, a "settle" +// but it will wait for configurable number of seconds, a "settle" // period in case there are other changes (any change will // extend the "settle" window). // -// It will additionally load preset AUTOSAVE_PRESET_NUM at startup. -// during the first `loop()`. Reasoning below. +// It can be configured to load auto saved preset at startup, +// during the first `loop()`. // // AutoSaveUsermod is standalone, but if FourLineDisplayUsermod // is installed, it will notify the user of the saved changes. -// -// Note: I don't love that WLED doesn't respect the brightness -// of the preset being auto loaded, so the AutoSaveUsermod -// will set the AUTOSAVE_PRESET_NUM preset in the first loop, -// so brightness IS honored. This means WLED will effectively -// ignore Default brightness and Apply N preset at boot when -// the AutoSaveUsermod is installed. -//How long to wait after settings change to auto-save -#ifndef AUTOSAVE_SETTLE_MS -#define AUTOSAVE_SETTLE_MS 10*1000 -#endif - -//Preset number to save to -#ifndef AUTOSAVE_PRESET_NUM -#define AUTOSAVE_PRESET_NUM 99 -#endif - -// "Auto save MM-DD HH:MM:SS" +// format: "~ MM-DD HH:MM:SS ~" #define PRESET_NAME_BUFFER_SIZE 25 class AutoSaveUsermod : public Usermod { - private: - // If we've detected the need to auto save, this will - // be non zero. - unsigned long autoSaveAfter = 0; - char presetNameBuffer[PRESET_NAME_BUFFER_SIZE]; + private: bool firstLoop = true; + bool initDone = false; + bool enabled = true; + + // configurable parameters + unsigned long autoSaveAfterSec = 15; // 15s by default + uint8_t autoSavePreset = 250; // last possible preset + bool applyAutoSaveOnBoot = false; // do we load auto-saved preset on boot? + + // If we've detected the need to auto save, this will be non zero. + unsigned long autoSaveAfter = 0; uint8_t knownBrightness = 0; uint8_t knownEffectSpeed = 0; @@ -58,35 +46,65 @@ class AutoSaveUsermod : public Usermod { uint8_t knownMode = 0; uint8_t knownPalette = 0; -#ifdef USERMOD_FOUR_LINE_DISLAY + #ifdef USERMOD_FOUR_LINE_DISPLAY FourLineDisplayUsermod* display; -#endif + #endif + + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _autoSaveEnabled[]; + static const char _autoSaveAfterSec[]; + static const char _autoSavePreset[]; + static const char _autoSaveApplyOnBoot[]; + + void inline saveSettings() { + char presetNameBuffer[PRESET_NAME_BUFFER_SIZE]; + updateLocalTime(); + sprintf_P(presetNameBuffer, + PSTR("~ %02d-%02d %02d:%02d:%02d ~"), + month(localTime), day(localTime), + hour(localTime), minute(localTime), second(localTime)); + savePreset(autoSavePreset, true, presetNameBuffer); + } + + void inline displayOverlay() { + #ifdef USERMOD_FOUR_LINE_DISPLAY + if (display != nullptr) { + display->wakeDisplay(); + display->overlay("Settings", "Auto Saved", 1500); + } + #endif + } public: + // gets called once at boot. Do all initialization that doesn't depend on // network here void setup() { -#ifdef USERMOD_FOUR_LINE_DISLAY - // This Usermod has enhanced funcionality if - // FourLineDisplayUsermod is available. - display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP); -#endif + #ifdef USERMOD_FOUR_LINE_DISPLAY + // This Usermod has enhanced funcionality if + // FourLineDisplayUsermod is available. + display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP); + #endif + initDone = true; } // gets called every time WiFi is (re-)connected. Initialize own network // interfaces here void connected() {} - /** + /* * Da loop. */ void loop() { + if (!autoSaveAfterSec || !enabled) return; // setting 0 as autosave seconds disables autosave + unsigned long now = millis(); uint8_t currentMode = strip.getMode(); uint8_t currentPalette = strip.getSegment(0).palette; if (firstLoop) { firstLoop = false; - applyPreset(AUTOSAVE_PRESET_NUM); + if (applyAutoSaveOnBoot) applyPreset(autoSavePreset); knownBrightness = bri; knownEffectSpeed = effectSpeed; knownEffectIntensity = effectIntensity; @@ -95,7 +113,7 @@ class AutoSaveUsermod : public Usermod { return; } - unsigned long wouldAutoSaveAfter = now + AUTOSAVE_SETTLE_MS; + unsigned long wouldAutoSaveAfter = now + autoSaveAfterSec*1000; if (knownBrightness != bri) { knownBrightness = bri; autoSaveAfter = wouldAutoSaveAfter; @@ -121,37 +139,32 @@ class AutoSaveUsermod : public Usermod { } } - void saveSettings() { - updateLocalTime(); - sprintf(presetNameBuffer, - "Auto save %02d-%02d %02d:%02d:%02d", - month(localTime), day(localTime), - hour(localTime), minute(localTime), second(localTime)); - savePreset(AUTOSAVE_PRESET_NUM, true, presetNameBuffer); - } - - void displayOverlay() { -#ifdef USERMOD_FOUR_LINE_DISLAY - if (display != nullptr) { - display->wakeDisplay(); - display->overlay("Settings", "Auto Saved", 1500); - } -#endif - } + /* + * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. + * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. + * Below it is shown how this could be used for e.g. a light sensor + */ + //void addToJsonInfo(JsonObject& root) { + //JsonObject user = root["u"]; + //if (user.isNull()) user = root.createNestedObject("u"); + //JsonArray data = user.createNestedArray(F("Autosave")); + //data.add(F("Loaded.")); + //} /* * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). * Values in the state object may be modified by connected clients */ - void addToJsonState(JsonObject& root) { - } + //void addToJsonState(JsonObject& root) { + //} /* * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). * Values in the state object may be modified by connected clients */ - void readFromJsonState(JsonObject& root) { - } + //void readFromJsonState(JsonObject& root) { + // if (!initDone) return; // prevent crash on boot applyPreset() + //} /* * addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object. @@ -168,6 +181,13 @@ class AutoSaveUsermod : public Usermod { * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! */ void addToConfig(JsonObject& root) { + // we add JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}} + JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname + top[FPSTR(_autoSaveEnabled)] = enabled; + top[FPSTR(_autoSaveAfterSec)] = autoSaveAfterSec; // usermodparam + top[FPSTR(_autoSavePreset)] = autoSavePreset; // usermodparam + top[FPSTR(_autoSaveApplyOnBoot)] = applyAutoSaveOnBoot; + DEBUG_PRINTLN(F("Autosave config saved.")); } /* @@ -179,7 +199,33 @@ class AutoSaveUsermod : public Usermod { * If you don't know what that is, don't fret. It most likely doesn't affect your use case :) */ void readFromConfig(JsonObject& root) { - } + // we look for JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}} + JsonObject top = root[FPSTR(_name)]; + if (top.isNull()) { + DEBUG_PRINTLN(F("No config found. (Using defaults.)")); + return; + } + + if (top[FPSTR(_autoSaveEnabled)].is()) { + // reading from cfg.json + enabled = top[FPSTR(_autoSaveEnabled)].as(); + } else { + // reading from POST message + String str = top[FPSTR(_autoSaveEnabled)]; // checkbox -> off or on + enabled = (bool)(str!="off"); // off is guaranteed to be present + } + autoSaveAfterSec = min(3600,max(10,top[FPSTR(_autoSaveAfterSec)].as())); + autoSavePreset = min(250,max(100,top[FPSTR(_autoSavePreset)].as())); + if (top[FPSTR(_autoSaveApplyOnBoot)].is()) { + // reading from cfg.json + applyAutoSaveOnBoot = top[FPSTR(_autoSaveApplyOnBoot)].as(); + } else { + // reading from POST message + String str = top[FPSTR(_autoSaveApplyOnBoot)]; // checkbox -> off or on + applyAutoSaveOnBoot = (bool)(str!="off"); // off is guaranteed to be present + } + DEBUG_PRINTLN(F("Autosave config (re)loaded.")); + } /* * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). @@ -188,5 +234,11 @@ class AutoSaveUsermod : public Usermod { uint16_t getId() { return USERMOD_ID_AUTO_SAVE; } +}; -}; \ No newline at end of file +// strings to reduce flash memory usage (used more than twice) +const char AutoSaveUsermod::_name[] PROGMEM = "Autosave"; +const char AutoSaveUsermod::_autoSaveEnabled[] PROGMEM = "enabled"; +const char AutoSaveUsermod::_autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec"; +const char AutoSaveUsermod::_autoSavePreset[] PROGMEM = "autoSavePreset"; +const char AutoSaveUsermod::_autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot"; diff --git a/usermods/usermod_v2_four_line_display/readme.md b/usermods/usermod_v2_four_line_display/readme.md index 3198b2be..367f3d7a 100644 --- a/usermods/usermod_v2_four_line_display/readme.md +++ b/usermods/usermod_v2_four_line_display/readme.md @@ -1,4 +1,4 @@ -# Rotary Encoder UI Usermod +# I2C 4 Line Display Usermod First, thanks to the authors of the ssd11306_i2c_oled_u8g2 mod. @@ -19,13 +19,11 @@ This file should be placed in the same directory as `platformio.ini`. ### Define Your Options -* `USERMOD_FOUR_LINE_DISLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells Rotary Encoder usermod, if installed, that the display is available +* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells Rotary Encoder usermod, if installed, that the display is available * `FLD_PIN_SCL` - The display SCL pin, defaults to 5 * `FLD_PIN_SDA` - The display SDA pin, defaults to 4 -* `FLIP_MODE` - Set to 0 or 1 -* `LINE_HEIGHT` - Set to 1 or 2 -There are other `#define` values in the Usermod that might be of interest. +All of the parameters can be configured using Usermods settings page, inluding GPIO pins. ### PlatformIO requirements @@ -37,3 +35,5 @@ UI usermod folder for how to include these using `platformio_override.ini`. 2021-02 * First public release +2021-04 +* Adaptation for runtime configuration. \ No newline at end of file diff --git a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h index 0b59af55..ea1a6f90 100644 --- a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h +++ b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h @@ -24,50 +24,25 @@ // //The SCL and SDA pins are defined here. -#ifndef FLD_PIN_SCL -#define FLD_PIN_SCL 5 -#endif - -#ifndef FLD_PIN_SDA -#define FLD_PIN_SDA 4 -#endif - -// U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8( -// U8X8_PIN_NONE, FLD_PIN_SCL, FLD_PIN_SDA); -U8X8_SH1106_128X64_WINSTAR_HW_I2C u8x8( - U8X8_PIN_NONE, FLD_PIN_SCL, FLD_PIN_SDA); - -// Screen upside down? Change to 0 or 1 -#ifndef FLIP_MODE -#define FLIP_MODE 0 -#endif - -// LINE_HEIGHT 1 is single height, for 128x32 displays. -// LINE_HEIGHT 2 makes the 128x64 screen display at double height. -#ifndef LINE_HEIGHT -#define LINE_HEIGHT 2 -#endif - -// If you aren't also including RotaryEncoderUIUsermod -// you probably want to set both -// SLEEP_MODE_ENABLED false -// CLOCK_MODE_ENABLED false -// as you will never be able wake the display / disable the clock. -#ifdef USERMOD_ROTARY_ENCODER_UI -#ifndef SLEEP_MODE_ENABLED -#define SLEEP_MODE_ENABLED true -#endif -#ifndef CLOCK_MODE_ENABLED -#define CLOCK_MODE_ENABLED true -#endif +#ifdef ARDUINO_ARCH_ESP32 + #ifndef FLD_PIN_SCL + #define FLD_PIN_SCL 22 + #endif + #ifndef FLD_PIN_SDA + #define FLD_PIN_SDA 21 + #endif #else -#define SLEEP_MODE_ENABLED false -#define CLOCK_MODE_ENABLED false + #ifndef FLD_PIN_SCL + #define FLD_PIN_SCL 5 + #endif + #ifndef FLD_PIN_SDA + #define FLD_PIN_SDA 4 + #endif #endif // When to time out to the clock or blank the screen // if SLEEP_MODE_ENABLED. -#define SCREEN_TIMEOUT_MS 15*1000 +#define SCREEN_TIMEOUT_MS 60*1000 // 1 min #define TIME_INDENT 0 #define DATE_INDENT 2 @@ -75,33 +50,43 @@ U8X8_SH1106_128X64_WINSTAR_HW_I2C u8x8( // Minimum time between redrawing screen in ms #define USER_LOOP_REFRESH_RATE_MS 1000 -#if LINE_HEIGHT == 2 -#define DRAW_STRING draw1x2String -#define DRAW_GLYPH draw1x2Glyph -#define DRAW_BIG_STRING draw2x2String -#else -#define DRAW_STRING drawString -#define DRAW_GLYPH drawGlyph -#define DRAW_BIG_STRING draw2x2String -#endif - // Extra char (+1) for null #define LINE_BUFFER_SIZE 16+1 -#define FLD_LINE_3_BRIGHTNESS 0 -#define FLD_LINE_3_EFFECT_SPEED 1 -#define FLD_LINE_3_EFFECT_INTENSITY 2 -#define FLD_LINE_3_PALETTE 3 -#if LINE_HEIGHT == 2 -#define TIME_LINE 1 -#else -#define TIME_LINE 0 -#endif +typedef enum { + FLD_LINE_4_BRIGHTNESS = 0, + FLD_LINE_4_EFFECT_SPEED, + FLD_LINE_4_EFFECT_INTENSITY, + FLD_LINE_4_MODE, + FLD_LINE_4_PALETTE +} Line4Type; + +typedef enum { + NONE = 0, + SSD1306, // U8X8_SSD1306_128X32_UNIVISION_HW_I2C + SH1106, // U8X8_SH1106_128X64_WINSTAR_HW_I2C + SSD1306_64 // U8X8_SSD1306_128X64_NONAME_HW_I2C +} DisplayType; class FourLineDisplayUsermod : public Usermod { + private: + + bool initDone = false; unsigned long lastTime = 0; + // HW interface & configuration + U8X8 *u8x8 = nullptr; // pointer to U8X8 display object + int8_t sclPin=FLD_PIN_SCL, sdaPin=FLD_PIN_SDA; // I2C pins for interfacing, get initialised in readFromConfig() + DisplayType type = SSD1306; // display type + bool flip = false; // flip display 180° + uint8_t contrast = 10; // screen contrast + uint8_t lineHeight = 1; // 1 row or 2 rows + uint32_t refreshRate = USER_LOOP_REFRESH_RATE_MS; // in ms + uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms + bool sleepMode = true; // allow screen sleep? + bool clockMode = false; // display clock + // needRedraw marks if redraw is required to prevent often redrawing. bool needRedraw = true; @@ -118,38 +103,72 @@ class FourLineDisplayUsermod : public Usermod { uint8_t knownHour = 99; bool displayTurnedOff = false; - long lastUpdate = 0; - long lastRedraw = 0; - long overlayUntil = 0; - byte lineThreeType = FLD_LINE_3_BRIGHTNESS; + unsigned long lastUpdate = 0; + unsigned long lastRedraw = 0; + unsigned long overlayUntil = 0; + Line4Type lineFourType = FLD_LINE_4_BRIGHTNESS; // Set to 2 or 3 to mark lines 2 or 3. Other values ignored. byte markLineNum = 0; - char lineBuffer[LINE_BUFFER_SIZE]; - - char **modes_qstrings = nullptr; - char **palettes_qstrings = nullptr; + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _contrast[]; + static const char _refreshRate[]; + static const char _screenTimeOut[]; + static const char _flip[]; + static const char _sleepMode[]; + static const char _clockMode[]; // If display does not work or looks corrupted check the // constructor reference: // https://github.com/olikraus/u8g2/wiki/u8x8setupcpp // or check the gallery: // https://github.com/olikraus/u8g2/wiki/gallery + public: // gets called once at boot. Do all initialization that doesn't depend on // network here void setup() { - u8x8.begin(); - u8x8.setFlipMode(FLIP_MODE); - u8x8.setPowerSave(0); - u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 - u8x8.setFont(u8x8_font_chroma48medium8_r); - u8x8.DRAW_STRING(0, 0*LINE_HEIGHT, "Loading..."); - - ModeSortUsermod *modeSortUsermod = (ModeSortUsermod*) usermods.lookup(USERMOD_ID_MODE_SORT); - modes_qstrings = modeSortUsermod->getModesQStrings(); - palettes_qstrings = modeSortUsermod->getPalettesQStrings(); + if (type==NONE) return; + if (!pinManager.allocatePin(sclPin)) { sclPin = -1; type = NONE; return;} + if (!pinManager.allocatePin(sdaPin)) { pinManager.deallocatePin(sclPin); sclPin = sdaPin = -1; type = NONE; return; } + switch (type) { + case SSD1306: + #ifdef ESP8266 + if (!(sclPin==5 && sdaPin==4)) + u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(sclPin, sdaPin); // SCL, SDA, reset + else + #endif + u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, sclPin, sdaPin); // Pins are Reset, SCL, SDA + break; + case SH1106: + #ifdef ESP8266 + if (!(sclPin==5 && sdaPin==4)) + u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(sclPin, sdaPin); // SCL, SDA, reset + else + #endif + u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, sclPin, sdaPin); // Pins are Reset, SCL, SDA + break; + case SSD1306_64: + #ifdef ESP8266 + if (!(sclPin==5 && sdaPin==4)) + u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(sclPin, sdaPin); // SCL, SDA, reset + else + #endif + u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, sclPin, sdaPin); // Pins are Reset, SCL, SDA + break; + default: + u8x8 = nullptr; + type = NONE; + return; + } + (static_cast(u8x8))->begin(); + setFlipMode(flip); + setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 + setPowerSave(0); + drawString(0, 0, "Loading..."); + initDone = true; } // gets called every time WiFi is (re-)connected. Initialize own network @@ -160,7 +179,7 @@ class FourLineDisplayUsermod : public Usermod { * Da loop. */ void loop() { - if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) { + if (millis() - lastUpdate < (clockMode?1000:refreshRate)) { return; } lastUpdate = millis(); @@ -168,18 +187,59 @@ class FourLineDisplayUsermod : public Usermod { redraw(false); } + /** + * Wrappers for screen drawing + */ + void setFlipMode(uint8_t mode) { + if (type==NONE) return; + (static_cast(u8x8))->setFlipMode(mode); + } + void setContrast(uint8_t contrast) { + if (type==NONE) return; + (static_cast(u8x8))->setContrast(contrast); + } + void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) { + if (type==NONE) return; + (static_cast(u8x8))->setFont(u8x8_font_chroma48medium8_r); + if (!ignoreLH && lineHeight==2) (static_cast(u8x8))->draw1x2String(col, row, string); + else (static_cast(u8x8))->drawString(col, row, string); + } + void draw2x2String(uint8_t col, uint8_t row, const char *string) { + if (type==NONE) return; + (static_cast(u8x8))->setFont(u8x8_font_chroma48medium8_r); + (static_cast(u8x8))->draw2x2String(col, row, string); + } + void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) { + if (type==NONE) return; + (static_cast(u8x8))->setFont(font); + if (!ignoreLH && lineHeight==2) (static_cast(u8x8))->draw1x2Glyph(col, row, glyph); + else (static_cast(u8x8))->drawGlyph(col, row, glyph); + } + uint8_t getCols() { + if (type==NONE) return 0; + return (static_cast(u8x8))->getCols(); + } + void clear() { + if (type==NONE) return; + (static_cast(u8x8))->clear(); + } + void setPowerSave(uint8_t save) { + if (type==NONE) return; + (static_cast(u8x8))->setPowerSave(save); + } + /** * Redraw the screen (but only if things have changed * or if forceRedraw). */ void redraw(bool forceRedraw) { + if (type==NONE) return; if (overlayUntil > 0) { if (millis() >= overlayUntil) { // Time to display the overlay has elapsed. overlayUntil = 0; forceRedraw = true; - } - else { + } else { // We are still displaying the overlay // Don't redraw. return; @@ -208,22 +268,46 @@ class FourLineDisplayUsermod : public Usermod { if (!needRedraw) { // Nothing to change. // Turn off display after 3 minutes with no change. - if(SLEEP_MODE_ENABLED && !displayTurnedOff && - (millis() - lastRedraw > SCREEN_TIMEOUT_MS)) { + if(sleepMode && !displayTurnedOff && (millis() - lastRedraw > screenTimeout)) { // We will still check if there is a change in redraw() // and turn it back on if it changed. + knownHour = 99; // force screen clear sleepOrClock(true); - } - else if (displayTurnedOff && CLOCK_MODE_ENABLED) { + } else if (displayTurnedOff && clockMode) { showTime(); + } else if ((millis() - lastRedraw)/1000%3 == 0) { + // change 4th line every 3s + switch (lineFourType) { + case FLD_LINE_4_BRIGHTNESS: + setLineFourType(FLD_LINE_4_EFFECT_SPEED); + break; + case FLD_LINE_4_MODE: + setLineFourType(FLD_LINE_4_BRIGHTNESS); + break; + case FLD_LINE_4_PALETTE: + setLineFourType(clockMode ? FLD_LINE_4_MODE : FLD_LINE_4_BRIGHTNESS); + break; + case FLD_LINE_4_EFFECT_SPEED: + setLineFourType(FLD_LINE_4_EFFECT_INTENSITY); + break; + case FLD_LINE_4_EFFECT_INTENSITY: + setLineFourType(FLD_LINE_4_PALETTE); + break; + default: + break; + } + drawLineFour(); } return; + } else { + knownHour = 99; // force time display + clear(); } + needRedraw = false; lastRedraw = millis(); - if (displayTurnedOff) - { + if (displayTurnedOff) { // Turn the display back on sleepOrClock(false); } @@ -242,79 +326,94 @@ class FourLineDisplayUsermod : public Usermod { knownEffectIntensity = effectIntensity; // Do the actual drawing - u8x8.clear(); - u8x8.setFont(u8x8_font_chroma48medium8_r); // First row with Wifi name - String ssidString = knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0); - u8x8.DRAW_STRING(1, 0*LINE_HEIGHT, ssidString.c_str()); - // Print `~` char to indicate that SSID is longer, than owr dicplay - if (knownSsid.length() > u8x8.getCols()) { - u8x8.DRAW_STRING(u8x8.getCols() - 1, 0*LINE_HEIGHT, "~"); + drawGlyph(0, 0, 80, u8x8_font_open_iconic_embedded_1x1); // wifi icon + String ssidString = knownSsid.substring(0, getCols() > 1 ? getCols() - 2 : 0); + drawString(1, 0, ssidString.c_str()); + // Print `~` char to indicate that SSID is longer, than our display + if (knownSsid.length() > getCols()) { + drawString(getCols() - 1, 0, "~"); } // Second row with IP or Psssword + drawGlyph(0, lineHeight, 68, u8x8_font_open_iconic_embedded_1x1); // home icon // Print password in AP mode and if led is OFF. if (apActive && bri == 0) { - u8x8.DRAW_STRING(1, 1*LINE_HEIGHT, apPass); - } - else { - String ipString = knownIp.toString(); - u8x8.DRAW_STRING(1, 1*LINE_HEIGHT, ipString.c_str()); + drawString(1, lineHeight, apPass); + } else { + drawString(1, lineHeight, (knownIp.toString()).c_str()); } - // Third row with mode name - showCurrentEffectOrPalette(modes_qstrings[knownMode], 2); + // Third row with mode name or current time + if (clockMode) showTime(false); + else showCurrentEffectOrPalette(knownMode, JSON_mode_names, 2); - switch(lineThreeType) { - case FLD_LINE_3_BRIGHTNESS: - sprintf(lineBuffer, "Brightness %d", bri); - u8x8.DRAW_STRING(1, 3*LINE_HEIGHT, lineBuffer); + // Fourth row + drawLineFour(); + + drawGlyph(0, 2*lineHeight, 66 + (bri > 0 ? 3 : 0), u8x8_font_open_iconic_weather_2x2); // sun/moon icon + //if (markLineNum>1) drawGlyph(2, markLineNum*lineHeight, 66, u8x8_font_open_iconic_arrow_1x1); // arrow icon + } + + void drawLineFour() { + char lineBuffer[LINE_BUFFER_SIZE]; + switch(lineFourType) { + case FLD_LINE_4_BRIGHTNESS: + sprintf_P(lineBuffer, PSTR("Brightness %3d"), bri); + drawString(2, 3*lineHeight, lineBuffer); break; - case FLD_LINE_3_EFFECT_SPEED: - sprintf(lineBuffer, "FX Speed %d", effectSpeed); - u8x8.DRAW_STRING(1, 3*LINE_HEIGHT, lineBuffer); + case FLD_LINE_4_EFFECT_SPEED: + sprintf_P(lineBuffer, PSTR("FX Speed %3d"), effectSpeed); + drawString(2, 3*lineHeight, lineBuffer); break; - case FLD_LINE_3_EFFECT_INTENSITY: - sprintf(lineBuffer, "FX Intense %d", effectIntensity); - u8x8.DRAW_STRING(1, 3*LINE_HEIGHT, lineBuffer); + case FLD_LINE_4_EFFECT_INTENSITY: + sprintf_P(lineBuffer, PSTR("FX Intens. %3d"), effectIntensity); + drawString(2, 3*lineHeight, lineBuffer); break; - case FLD_LINE_3_PALETTE: - showCurrentEffectOrPalette(palettes_qstrings[knownPalette], 3); + case FLD_LINE_4_MODE: + showCurrentEffectOrPalette(knownMode, JSON_mode_names, 3); + break; + case FLD_LINE_4_PALETTE: + default: + showCurrentEffectOrPalette(knownPalette, JSON_palette_names, 3); break; } - - u8x8.setFont(u8x8_font_open_iconic_arrow_1x1); - u8x8.DRAW_GLYPH(0, markLineNum*LINE_HEIGHT, 66); // arrow icon - - u8x8.setFont(u8x8_font_open_iconic_embedded_1x1); - u8x8.DRAW_GLYPH(0, 0*LINE_HEIGHT, 80); // wifi icon - u8x8.DRAW_GLYPH(0, 1*LINE_HEIGHT, 68); // home icon } /** * Display the current effect or palette (desiredEntry) * on the appropriate line (row). - * - * TODO: Should we cache the current effect and - * TODO: palette name? This seems expensive. */ - void showCurrentEffectOrPalette(char *qstring, uint8_t row) { - uint8_t printedChars = 1; + void showCurrentEffectOrPalette(int knownMode, const char *qstring, uint8_t row) { + char lineBuffer[LINE_BUFFER_SIZE]; + uint8_t qComma = 0; + bool insideQuotes = false; + uint8_t printedChars = 0; char singleJsonSymbol; - int i = 0; - while (true) { + + // Find the mode name in JSON + for (size_t i = 0; i < strlen_P(qstring); i++) { singleJsonSymbol = pgm_read_byte_near(qstring + i); - if (singleJsonSymbol == '"' || singleJsonSymbol == '\0' ) { - break; + if (singleJsonSymbol == '\0') break; + switch (singleJsonSymbol) { + case '"': + insideQuotes = !insideQuotes; + break; + case '[': + case ']': + break; + case ',': + qComma++; + default: + if (!insideQuotes || (qComma != knownMode)) break; + lineBuffer[printedChars++] = singleJsonSymbol; } - u8x8.DRAW_GLYPH(printedChars, row * LINE_HEIGHT, singleJsonSymbol); - printedChars++; - if ( (printedChars > u8x8.getCols() - 2)) { - break; - } - i++; + if ((qComma > knownMode) || (printedChars > getCols()-2) || printedChars > sizeof(lineBuffer)-2) break; } + for (;printedChars < getCols()-2 || printedChars > sizeof(lineBuffer)-2; printedChars++) lineBuffer[printedChars]=' '; + lineBuffer[printedChars] = 0; + drawString(2, row*lineHeight, lineBuffer); } /** @@ -324,6 +423,7 @@ class FourLineDisplayUsermod : public Usermod { * to wake up the screen. */ bool wakeDisplay() { + knownHour = 99; if (displayTurnedOff) { // Turn the display back on sleepOrClock(false); @@ -345,36 +445,31 @@ class FourLineDisplayUsermod : public Usermod { } // Print the overlay - u8x8.clear(); - u8x8.setFont(u8x8_font_chroma48medium8_r); - if (line1) { - u8x8.DRAW_STRING(0, 1*LINE_HEIGHT, line1); - } - if (line2) { - u8x8.DRAW_STRING(0, 2*LINE_HEIGHT, line2); - } + clear(); + if (line1) drawString(0, 1*lineHeight, line1); + if (line2) drawString(0, 2*lineHeight, line2); overlayUntil = millis() + showHowLong; } /** - * Specify what data should be defined on line 3 + * Specify what data should be defined on line 4 * (the last line). */ - void setLineThreeType(byte newLineThreeType) { - if (newLineThreeType == FLD_LINE_3_BRIGHTNESS || - newLineThreeType == FLD_LINE_3_EFFECT_SPEED || - newLineThreeType == FLD_LINE_3_EFFECT_INTENSITY || - newLineThreeType == FLD_LINE_3_PALETTE) { - lineThreeType = newLineThreeType; - } - else { - // Unknown value. - lineThreeType = FLD_LINE_3_BRIGHTNESS; + void setLineFourType(Line4Type newLineFourType) { + if (newLineFourType == FLD_LINE_4_BRIGHTNESS || + newLineFourType == FLD_LINE_4_EFFECT_SPEED || + newLineFourType == FLD_LINE_4_EFFECT_INTENSITY || + newLineFourType == FLD_LINE_4_MODE || + newLineFourType == FLD_LINE_4_PALETTE) { + lineFourType = newLineFourType; + } else { + // Unknown value + lineFourType = FLD_LINE_4_BRIGHTNESS; } } /** - * Line 2 or 3 (last two lines) can be marked with an + * Line 3 or 4 (last two lines) can be marked with an * arrow in the first column. Pass 2 or 3 to this to * specify which line to mark with an arrow. * Any other values are ignored. @@ -388,42 +483,17 @@ class FourLineDisplayUsermod : public Usermod { } } - /* - * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. - * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. - * Below it is shown how this could be used for e.g. a light sensor - */ - /* - void addToJsonInfo(JsonObject& root) - { - int reading = 20; - //this code adds "u":{"Light":[20," lux"]} to the info object - JsonObject user = root["u"]; - if (user.isNull()) user = root.createNestedObject("u"); - - JsonArray lightArr = user.createNestedArray("Light"); //name - lightArr.add(reading); //value - lightArr.add(" lux"); //unit - } - */ - /** * Enable sleep (turn the display off) or clock mode. */ void sleepOrClock(bool enabled) { if (enabled) { - if (CLOCK_MODE_ENABLED) { - showTime(); - } - else { - u8x8.setPowerSave(1); - } + if (clockMode) showTime(); + else setPowerSave(1); displayTurnedOff = true; } else { - if (!CLOCK_MODE_ENABLED) { - u8x8.setPowerSave(0); - } + setPowerSave(0); displayTurnedOff = false; } } @@ -433,23 +503,28 @@ class FourLineDisplayUsermod : public Usermod { * on the middle rows. Based 24 or 12 hour depending on * the useAMPM configuration. */ - void showTime() { + void showTime(bool fullScreen = true) { + char lineBuffer[LINE_BUFFER_SIZE]; + updateLocalTime(); byte minuteCurrent = minute(localTime); byte hourCurrent = hour(localTime); + byte secondCurrent = second(localTime); if (knownMinute == minuteCurrent && knownHour == hourCurrent) { // Time hasn't changed. - return; + if (!fullScreen) return; + } else { + if (fullScreen) clear(); } knownMinute = minuteCurrent; knownHour = hourCurrent; - u8x8.clear(); - u8x8.setFont(u8x8_font_chroma48medium8_r); - - int currentMonth = month(localTime); - sprintf(lineBuffer, "%s %d", monthShortStr(currentMonth), day(localTime)); - u8x8.DRAW_BIG_STRING(DATE_INDENT, TIME_LINE*LINE_HEIGHT, lineBuffer); + byte currentMonth = month(localTime); + sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(currentMonth), day(localTime)); + if (fullScreen) + draw2x2String(DATE_INDENT, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays + else + drawString(2, lineHeight*2, lineBuffer); byte showHour = hourCurrent; boolean isAM = false; @@ -467,25 +542,45 @@ class FourLineDisplayUsermod : public Usermod { } } - sprintf(lineBuffer, "%02d:%02d %s", showHour, minuteCurrent, useAMPM ? (isAM ? "AM" : "PM") : ""); + sprintf_P(lineBuffer, (secondCurrent%2 || !fullScreen) ? PSTR("%2d:%02d") : PSTR("%2d %02d"), (useAMPM ? showHour : hourCurrent), minuteCurrent); // For time, we always use LINE_HEIGHT of 2 since // we are printing it big. - u8x8.DRAW_BIG_STRING(TIME_INDENT + (useAMPM ? 0 : 2), (TIME_LINE + 1) * 2, lineBuffer); + if (fullScreen) { + draw2x2String(TIME_INDENT+2, lineHeight*2, lineBuffer); + sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent); + if (!useAMPM) drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line + } else { + drawString(9+(useAMPM?0:2), lineHeight*2, lineBuffer); + } + if (useAMPM) drawString(12+(fullScreen?0:2), lineHeight*2, (isAM ? "AM" : "PM"), true); } + /* + * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. + * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. + * Below it is shown how this could be used for e.g. a light sensor + */ + //void addToJsonInfo(JsonObject& root) { + //JsonObject user = root["u"]; + //if (user.isNull()) user = root.createNestedObject("u"); + //JsonArray data = user.createNestedArray(F("4LineDisplay")); + //data.add(F("Loaded.")); + //} + /* * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). * Values in the state object may be modified by connected clients */ - void addToJsonState(JsonObject& root) { - } + //void addToJsonState(JsonObject& root) { + //} /* * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). * Values in the state object may be modified by connected clients */ - void readFromJsonState(JsonObject& root) { - } + //void readFromJsonState(JsonObject& root) { + // if (!initDone) return; // prevent crash on boot applyPreset() + //} /* * addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object. @@ -502,6 +597,18 @@ class FourLineDisplayUsermod : public Usermod { * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! */ void addToConfig(JsonObject& root) { + JsonObject top = root.createNestedObject(FPSTR(_name)); + JsonArray i2c_pin = top.createNestedArray("pin"); + i2c_pin.add(sclPin); + i2c_pin.add(sdaPin); + top["type"] = type; + top[FPSTR(_flip)] = (bool) flip; + top[FPSTR(_contrast)] = contrast; + top[FPSTR(_refreshRate)] = refreshRate/1000; + top[FPSTR(_screenTimeOut)] = screenTimeout/1000; + top[FPSTR(_sleepMode)] = (bool) sleepMode; + top[FPSTR(_clockMode)] = (bool) clockMode; + DEBUG_PRINTLN(F("4 Line Display config saved.")); } /* @@ -513,6 +620,74 @@ class FourLineDisplayUsermod : public Usermod { * If you don't know what that is, don't fret. It most likely doesn't affect your use case :) */ void readFromConfig(JsonObject& root) { + bool needsRedraw = false; + DisplayType newType = type; + int8_t newScl = sclPin; + int8_t newSda = sdaPin; + + JsonObject top = root[FPSTR(_name)]; + if (!top.isNull() && top["pin"] != nullptr) { + newScl = top["pin"][0]; + newSda = top["pin"][1]; + newType = top["type"]; + if (top[FPSTR(_flip)].is()) { + flip = top[FPSTR(_flip)].as(); + } else { + String str = top[FPSTR(_flip)]; // checkbox -> off or on + flip = (bool)(str!="off"); // off is guaranteed to be present + needRedraw |= true; + } + contrast = top[FPSTR(_contrast)].as(); + refreshRate = top[FPSTR(_refreshRate)].as() * 1000; + screenTimeout = top[FPSTR(_screenTimeOut)].as() * 1000; + if (top[FPSTR(_sleepMode)].is()) { + sleepMode = top[FPSTR(_sleepMode)].as(); + } else { + String str = top[FPSTR(_sleepMode)]; // checkbox -> off or on + sleepMode = (bool)(str!="off"); // off is guaranteed to be present + needRedraw |= true; + } + if (top[FPSTR(_clockMode)].is()) { + clockMode = top[FPSTR(_clockMode)].as(); + } else { + String str = top[FPSTR(_clockMode)]; // checkbox -> off or on + clockMode = (bool)(str!="off"); // off is guaranteed to be present + needRedraw |= true; + } + DEBUG_PRINTLN(F("4 Line Display config (re)loaded.")); + } else { + DEBUG_PRINTLN(F("No config found. (Using defaults.)")); + } + + if (!initDone) { + // first run: reading from cfg.json + sclPin = newScl; + sdaPin = newSda; + type = newType; + lineHeight = type==SSD1306 ? 1 : 2; + } else { + // changing paramters from settings page + if (sclPin!=newScl || sdaPin!=newSda || type!=newType) { + if (type==SSD1306) delete (static_cast(u8x8)); + if (type==SH1106) delete (static_cast(u8x8)); + if (type==SSD1306_64) delete (static_cast(u8x8)); + pinManager.deallocatePin(sclPin); + pinManager.deallocatePin(sdaPin); + sclPin = newScl; + sdaPin = newSda; + if (newScl<0 || newSda<0) { + type = NONE; + return; + } else + type = newType; + lineHeight = type==SSD1306 ? 1 : 2; + setup(); + needRedraw |= true; + } + setContrast(contrast); + setFlipMode(flip); + if (needsRedraw && !wakeDisplay()) redraw(true); + } } /* @@ -522,5 +697,13 @@ class FourLineDisplayUsermod : public Usermod { uint16_t getId() { return USERMOD_ID_FOUR_LINE_DISP; } +}; -}; \ No newline at end of file +// strings to reduce flash memory usage (used more than twice) +const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay"; +const char FourLineDisplayUsermod::_contrast[] PROGMEM = "contrast"; +const char FourLineDisplayUsermod::_refreshRate[] PROGMEM = "refreshRateSec"; +const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOutSec"; +const char FourLineDisplayUsermod::_flip[] PROGMEM = "flip"; +const char FourLineDisplayUsermod::_sleepMode[] PROGMEM = "sleepMode"; +const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode"; diff --git a/wled00/const.h b/wled00/const.h index 850a0228..6cf07576 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -11,12 +11,24 @@ #define DEFAULT_OTA_PASS "wledota" //increase if you need more -#define WLED_MAX_USERMODS 4 +#ifndef WLED_MAX_USERMODS + #ifdef ESP8266 + #define WLED_MAX_USERMODS 4 + #else + #define WLED_MAX_USERMODS 6 + #endif +#endif -#ifdef ESP8266 -#define WLED_MAX_BUSSES 3 -#else -#define WLED_MAX_BUSSES 10 +#ifndef WLED_MAX_BUSSES + #ifdef ESP8266 + #define WLED_MAX_BUSSES 3 + #else + #ifdef CONFIG_IDF_TARGET_ESP32S2 + #define WLED_MAX_BUSSES 5 + #else + #define WLED_MAX_BUSSES 10 + #endif + #endif #endif //Usermod IDs @@ -33,6 +45,7 @@ #define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" #define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" #define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h" +#define USERMOD_ID_MULTI_RELAY 101 //Usermod "usermod_multi_relay.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot @@ -116,10 +129,10 @@ #define TYPE_LPD8806 52 #define TYPE_P9813 53 -#define IS_DIGITAL(t) (t & 0x10) //digital are 16-31 and 48-63 -#define IS_PWM(t) (t > 40 && t < 46) -#define NUM_PWM_PINS(t) (t - 40) //for analog PWM 41-45 only -#define IS_2PIN(t) (t > 47) +#define IS_DIGITAL(t) ((t) & 0x10) //digital are 16-31 and 48-63 +#define IS_PWM(t) ((t) > 40 && (t) < 46) +#define NUM_PWM_PINS(t) ((t) - 40) //for analog PWM 41-45 only +#define IS_2PIN(t) ((t) > 47) //Color orders #define COL_ORDER_GRB 0 //GRB(w),defaut @@ -241,7 +254,11 @@ //this is merely a default now and can be changed at runtime #ifndef LEDPIN -#define LEDPIN 2 +#ifdef ESP8266 + #define LEDPIN 2 // GPIO2 (D4) on Wemod D1 mini compatible boards +#else + #define LEDPIN 16 // alligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards +#endif #endif #ifdef WLED_ENABLE_DMX diff --git a/wled00/data/settings.htm b/wled00/data/settings.htm index 4d7eaaed..6cb09f83 100644 --- a/wled00/data/settings.htm +++ b/wled00/data/settings.htm @@ -10,18 +10,17 @@ margin: 0; } html { - --h: 11.55vh; + --h: 10.2vh; } button { background: #333; color: #fff; font-family: Verdana, Helvetica, sans-serif; - border: 0.3ch solid #333; - display: inline-block; - font-size: 8vmin; + border: 1px solid #333; + font-size: 6vmin; height: var(--h); width: 95%; - margin-top: 2.4vh; + margin-top: 2vh; } + + + + +
+
+
+
+ +
+
+

Usermod Setup

+
Loading settings...
+
+
+ + + \ No newline at end of file diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index c4405d14..4f11852a 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -150,6 +150,7 @@ void _overlayCronixie(); void _drawOverlayCronixie(); //playlist.cpp +void shufflePlaylist(); void unloadPlaylist(); void loadPlaylist(JsonObject playlistObject); void handlePlaylist(); @@ -186,6 +187,8 @@ class Usermod { virtual void readFromJsonState(JsonObject& obj) {} virtual void addToConfig(JsonObject& obj) {} virtual void readFromConfig(JsonObject& obj) {} + virtual void onMqttConnect(bool sessionPresent) {} + virtual bool onMqttMessage(char* topic, char* payload) { return false; } virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;} }; @@ -206,7 +209,8 @@ class UsermodManager { void addToConfig(JsonObject& obj); void readFromConfig(JsonObject& obj); - + void onMqttConnect(bool sessionPresent); + bool onMqttMessage(char* topic, char* payload); bool add(Usermod* um); Usermod* lookup(uint16_t mod_id); byte getModCount(); diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 28a4f71b..cbe22db7 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -12,7 +12,7 @@ const char PAGE_settingsCss[] PROGMEM = R"=====(
%DMXMENU%
+ action="/settings/um">
)====="; @@ -390,3 +391,18 @@ MIT license

Server message: Response error!
)====="; + +// Autogenerated from wled00/data/settings_um.htm, do not edit!! +const char PAGE_settings_um[] PROGMEM = R"=====(UI Settings%CSS%%SCSS%
+

+

Usermod Setup

Loading settings...

)====="; + diff --git a/wled00/html_ui.h b/wled00/html_ui.h index 1bdb2703..c2494be3 100644 --- a/wled00/html_ui.h +++ b/wled00/html_ui.h @@ -7,9 +7,9 @@ */ // Autogenerated from wled00/data/index.htm, do not edit!! -const uint16_t PAGE_index_L = 33357; +const uint16_t PAGE_index_L = 33350; const uint8_t PAGE_index[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xcc, 0xbd, 0x79, 0x5b, 0xe2, 0xca, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xcc, 0xbd, 0x79, 0x5b, 0xe2, 0xca, 0xb6, 0x38, 0xfc, 0xbf, 0x9f, 0x82, 0xa6, 0xf7, 0xee, 0x86, 0x26, 0x40, 0x18, 0x55, 0xe8, 0xb4, 0x37, 0x20, 0x28, 0x2a, 0x0e, 0x28, 0xda, 0xb6, 0xdb, 0x73, 0x9e, 0x10, 0x42, 0x88, 0x86, 0x84, 0x4e, 0xc2, 0x24, 0xf2, 0xfb, 0xec, 0xef, 0x5a, 0x55, 0x95, 0x09, 0x82, 0xba, 0xcf, 0xdd, 0xe7, @@ -1419,679 +1419,679 @@ const uint8_t PAGE_index[] PROGMEM = { 0x8f, 0x1e, 0x07, 0x3f, 0x8e, 0x4a, 0x42, 0x38, 0xf5, 0x81, 0x0a, 0xbd, 0x90, 0x6f, 0x90, 0x98, 0x70, 0x59, 0x00, 0xe6, 0x03, 0xc5, 0x12, 0x50, 0x58, 0x86, 0x10, 0x18, 0xbd, 0x59, 0x8b, 0x7d, 0xa8, 0xc2, 0x4f, 0xa5, 0x3b, 0xe8, 0x7a, 0x6a, 0x15, 0x04, 0x22, 0xe9, 0x43, 0x3c, 0x9d, 0x96, - 0xd3, 0x39, 0xdc, 0x1d, 0x57, 0xfd, 0xff, 0x8a, 0xfb, 0xd6, 0xee, 0xb6, 0x8d, 0x64, 0xc1, 0xef, - 0xfb, 0x2b, 0x20, 0x24, 0x91, 0x89, 0x08, 0x22, 0x41, 0x4a, 0x72, 0x6c, 0x52, 0x20, 0x8f, 0xed, - 0x38, 0x13, 0xdf, 0x75, 0x1c, 0x4d, 0xe4, 0xdc, 0x99, 0x1c, 0xaf, 0xce, 0x25, 0x48, 0x36, 0x45, - 0x8c, 0x40, 0x00, 0x06, 0x40, 0x3d, 0x56, 0xc2, 0x7f, 0xdf, 0xaa, 0xea, 0x6e, 0xa0, 0x1b, 0x0f, - 0x92, 0x76, 0x32, 0xb3, 0x39, 0x31, 0x05, 0x34, 0xfa, 0xdd, 0xd5, 0xd5, 0x55, 0xd5, 0xf5, 0xe0, - 0x87, 0x0d, 0xe6, 0xc5, 0xf9, 0x15, 0xb7, 0x6e, 0xa3, 0x85, 0x12, 0x09, 0xe3, 0xf5, 0xc3, 0xbb, - 0x45, 0x07, 0x4d, 0x4d, 0xee, 0x4c, 0x4b, 0x74, 0x53, 0xdc, 0x9e, 0xa2, 0x69, 0x1b, 0xbb, 0x9f, - 0x98, 0x52, 0xf5, 0x9c, 0x53, 0xa1, 0xf5, 0xb2, 0x02, 0xa0, 0xea, 0xa5, 0xf9, 0x87, 0xdd, 0x15, - 0x00, 0x88, 0xdf, 0x25, 0x5e, 0xdc, 0x50, 0x03, 0x7c, 0xd9, 0x5d, 0xfc, 0xf3, 0x3c, 0x3d, 0x6e, - 0xea, 0x3c, 0x6d, 0x99, 0x4a, 0xf1, 0x51, 0x29, 0x03, 0x2d, 0x26, 0x85, 0xef, 0x24, 0xf4, 0x4e, - 0x56, 0xe7, 0xea, 0x4c, 0x38, 0x28, 0x66, 0xc7, 0x94, 0xc3, 0x44, 0xc7, 0x16, 0xce, 0x28, 0x38, - 0x2f, 0xc4, 0x66, 0xc1, 0xd1, 0x91, 0x95, 0x7e, 0x0a, 0xae, 0x2a, 0x2d, 0x87, 0xd5, 0x36, 0x3b, - 0xb5, 0xaa, 0xa1, 0xde, 0xd5, 0x02, 0x0e, 0x96, 0x1d, 0x25, 0x6d, 0xb9, 0x9c, 0xd9, 0x0c, 0xf8, - 0x5d, 0xf8, 0xda, 0x3f, 0x8d, 0xef, 0x0d, 0xfe, 0xe3, 0x88, 0x27, 0x72, 0x39, 0x0c, 0xcf, 0x83, - 0x01, 0xfc, 0x9c, 0x8a, 0x07, 0x74, 0x86, 0x23, 0x8a, 0xce, 0x44, 0xd1, 0x97, 0xf0, 0xc9, 0x31, - 0x7e, 0xc0, 0x5f, 0x59, 0xc4, 0xa1, 0xfc, 0x8e, 0x9a, 0x19, 0x7a, 0x65, 0x57, 0x7b, 0xa1, 0x7c, - 0x5e, 0x67, 0xf4, 0xd9, 0xa1, 0x66, 0xcf, 0xb4, 0x76, 0xb2, 0xe3, 0x99, 0x69, 0x97, 0x40, 0x49, - 0x28, 0x0f, 0x27, 0x0f, 0x72, 0xf8, 0xff, 0x17, 0xe3, 0x0f, 0x53, 0x6c, 0xc5, 0x4b, 0x18, 0xbc, - 0x77, 0x4d, 0x3b, 0xe1, 0x5d, 0xc6, 0xd6, 0x1d, 0xf3, 0x0e, 0x8e, 0x86, 0xdf, 0x7d, 0x80, 0x7c, - 0xd3, 0xfe, 0xaf, 0xcb, 0x5f, 0x3f, 0x74, 0xb9, 0x71, 0x88, 0xbf, 0x7c, 0xe8, 0x40, 0x5d, 0xaa, - 0xc3, 0xba, 0xec, 0x3a, 0xf8, 0x99, 0x61, 0x6c, 0xaf, 0x0a, 0x30, 0x23, 0x8c, 0xba, 0x07, 0x0d, - 0x89, 0x76, 0xb9, 0xa7, 0xb4, 0x5a, 0xf8, 0xf6, 0xe2, 0xf5, 0x94, 0xdb, 0xca, 0x6d, 0xdb, 0x6f, - 0x13, 0x8e, 0xcf, 0x87, 0xe2, 0x7b, 0x5b, 0xad, 0xef, 0x09, 0x88, 0xd4, 0xee, 0x71, 0xb0, 0x52, - 0xba, 0x26, 0xe0, 0xac, 0xa9, 0x02, 0xb1, 0xe7, 0x81, 0x72, 0x62, 0x93, 0x8e, 0xb6, 0x87, 0xcd, - 0x6f, 0x18, 0x53, 0x97, 0x60, 0x7e, 0x8c, 0x5e, 0x3b, 0xe9, 0x32, 0x5b, 0x4d, 0x1c, 0x60, 0xe2, - 0x62, 0xb1, 0xd0, 0x12, 0x4f, 0x30, 0x71, 0x36, 0x9b, 0x69, 0x89, 0xa7, 0x98, 0xe8, 0x79, 0x9e, - 0x96, 0x78, 0x86, 0x89, 0x2f, 0x5f, 0xbe, 0xd4, 0x12, 0x9f, 0x37, 0x25, 0xbe, 0xc0, 0xc4, 0x17, - 0x2f, 0x5e, 0x68, 0x89, 0x33, 0x4c, 0x3c, 0x3d, 0x3d, 0xd5, 0x12, 0xe7, 0x98, 0x78, 0x72, 0x72, - 0xa2, 0x25, 0x22, 0x43, 0xf4, 0x4d, 0xbf, 0xdf, 0xd7, 0x12, 0x17, 0x98, 0x38, 0x18, 0x0c, 0xb4, - 0xc4, 0x04, 0x13, 0xe7, 0xa7, 0x7a, 0x62, 0x64, 0x8a, 0xeb, 0xfd, 0x81, 0x73, 0x6a, 0x1b, 0xe5, - 0x8f, 0xd3, 0x7d, 0x69, 0x69, 0x19, 0xd3, 0x99, 0x98, 0xa5, 0x93, 0x4a, 0xf2, 0x4a, 0xa4, 0x3f, - 0xd7, 0xd2, 0xb3, 0x59, 0x4b, 0xc5, 0x80, 0x2a, 0x3a, 0x04, 0xdb, 0x96, 0x55, 0x29, 0xe0, 0xc9, - 0x12, 0xfd, 0x1f, 0x1c, 0xdb, 0x28, 0x7f, 0xda, 0x4b, 0xac, 0xf6, 0x6a, 0xa3, 0x8e, 0xdf, 0xfc, - 0xf5, 0x75, 0x89, 0xde, 0xb8, 0x70, 0xc8, 0x05, 0xd2, 0x14, 0x75, 0x77, 0x3a, 0x4e, 0xf7, 0x05, - 0x14, 0x1a, 0x56, 0x61, 0xa6, 0x3a, 0xc3, 0x04, 0x33, 0xa8, 0x43, 0x51, 0x83, 0x99, 0xea, 0xb4, - 0x9f, 0x34, 0xad, 0xda, 0x69, 0xd3, 0xfa, 0x12, 0xcc, 0x9c, 0x9d, 0x9d, 0xd5, 0x61, 0xe6, 0xf9, - 0xf3, 0xe7, 0x7b, 0xc2, 0x4c, 0x15, 0x38, 0x09, 0x66, 0xd0, 0xe1, 0x77, 0x0d, 0x66, 0xaa, 0xbb, - 0x60, 0xd1, 0x04, 0xf0, 0x04, 0x33, 0x2f, 0x4e, 0xfa, 0xcd, 0x30, 0x73, 0x02, 0x73, 0x2d, 0xff, - 0xb5, 0x00, 0x0c, 0x4c, 0x51, 0x23, 0xc0, 0x40, 0xfa, 0x59, 0x0b, 0xc0, 0xa8, 0xb5, 0xee, 0x03, - 0x2d, 0xce, 0x00, 0xbd, 0xc1, 0xca, 0x9f, 0x3d, 0xa0, 0xe5, 0xac, 0x6f, 0x1b, 0xf2, 0xdf, 0x57, - 0x81, 0xca, 0x26, 0x44, 0x2e, 0x4d, 0xc1, 0x36, 0xe8, 0x6d, 0xf2, 0xf5, 0x35, 0x62, 0x1b, 0xa0, - 0x83, 0x81, 0x3c, 0xa8, 0xd7, 0x33, 0xbb, 0x36, 0xd1, 0x8c, 0x7d, 0x51, 0xf5, 0xd3, 0x09, 0xf5, - 0x9b, 0x74, 0x29, 0x16, 0x76, 0xd3, 0x64, 0xee, 0x32, 0xdb, 0x04, 0x84, 0xc9, 0x2c, 0x79, 0xa8, - 0xa6, 0xae, 0xa4, 0x9b, 0xd0, 0xe5, 0x26, 0xf0, 0x1b, 0xfd, 0xbe, 0x3d, 0x38, 0xb5, 0x4f, 0x6d, - 0x0a, 0x69, 0x9b, 0x0e, 0x7b, 0x3d, 0xcf, 0x4f, 0xe6, 0x51, 0x14, 0xdd, 0xf8, 0xac, 0x7b, 0xed, - 0x03, 0xbb, 0x3e, 0xeb, 0xfa, 0x51, 0xef, 0x7e, 0xed, 0xa5, 0xdd, 0x38, 0xbc, 0x46, 0x5d, 0x1d, - 0xc7, 0x1e, 0xd8, 0xfd, 0x1f, 0xec, 0x7e, 0x59, 0xc4, 0x5f, 0xc3, 0x81, 0x21, 0x6c, 0xd4, 0xe7, - 0xc0, 0x11, 0x24, 0xc8, 0xee, 0xaf, 0x7b, 0xa7, 0x2f, 0xfb, 0xf8, 0xaf, 0x3f, 0x38, 0xe9, 0xfe, - 0x2b, 0xa6, 0xa2, 0x03, 0x67, 0x30, 0xb0, 0x4f, 0xb0, 0xf4, 0x60, 0x47, 0x83, 0x0c, 0x88, 0x3a, - 0x96, 0xc8, 0x26, 0xa1, 0xdc, 0x09, 0x94, 0x7b, 0xf9, 0xe5, 0xc5, 0x4e, 0xa1, 0xc8, 0x49, 0xff, - 0x8b, 0xca, 0x5d, 0xd9, 0x3c, 0x52, 0x71, 0xa0, 0x46, 0x2a, 0x16, 0xaa, 0x87, 0x8e, 0xeb, 0x06, - 0x9f, 0xbc, 0xab, 0x4f, 0xce, 0xd5, 0x84, 0xb8, 0xde, 0x9f, 0x80, 0xbe, 0xfc, 0x83, 0x79, 0xe8, - 0xfd, 0x53, 0xa4, 0xa3, 0x06, 0x92, 0x98, 0xe1, 0x4e, 0x64, 0x53, 0x22, 0xb0, 0x70, 0xf4, 0x97, - 0x5b, 0x25, 0x17, 0x5f, 0x13, 0x58, 0x26, 0x3c, 0x65, 0xe9, 0xc5, 0x27, 0x9f, 0x8b, 0xf8, 0x64, - 0x1d, 0x51, 0x66, 0x34, 0x5c, 0x4e, 0xc7, 0xa8, 0xb5, 0x93, 0x9e, 0x63, 0xbc, 0x6b, 0xb1, 0x9e, - 0xf4, 0xed, 0xf4, 0xca, 0xca, 0xc3, 0x06, 0x2f, 0xa3, 0x08, 0x35, 0x40, 0x53, 0xba, 0xe3, 0x47, - 0xbe, 0xd4, 0x8a, 0x10, 0xa1, 0x7a, 0xec, 0xcf, 0xae, 0xa1, 0xf5, 0xf4, 0x83, 0xf7, 0xa1, 0x93, - 0x5a, 0x14, 0x13, 0xbb, 0xfb, 0x1c, 0xd5, 0x87, 0x38, 0x58, 0x0a, 0x77, 0xc2, 0x6e, 0x5a, 0xa4, - 0xcc, 0xbc, 0xf9, 0xcd, 0x35, 0x89, 0x1b, 0xde, 0xe1, 0x5a, 0xbb, 0x53, 0xd4, 0x82, 0xf8, 0xf6, - 0x91, 0xfa, 0x94, 0x5b, 0x53, 0x00, 0x44, 0xae, 0x9f, 0x57, 0x42, 0x70, 0x14, 0xa2, 0xa7, 0x53, - 0xbc, 0xef, 0x06, 0x20, 0x07, 0x7e, 0xc0, 0xad, 0x46, 0x54, 0x2b, 0xc2, 0xa6, 0xa1, 0x5e, 0x12, - 0xf2, 0xd8, 0x8e, 0xdd, 0x21, 0xde, 0xdb, 0xd5, 0xc8, 0x90, 0x6b, 0x49, 0x86, 0x40, 0xea, 0x3b, - 0x2e, 0x7c, 0x12, 0xd9, 0xa0, 0xfc, 0x3a, 0x06, 0x88, 0xff, 0x09, 0xea, 0x37, 0x90, 0x11, 0xed, - 0x1a, 0x17, 0x01, 0x23, 0x8f, 0x5d, 0x21, 0x2c, 0xa6, 0xf1, 0x8f, 0xf7, 0x6f, 0x7f, 0x34, 0xde, - 0x5d, 0x1c, 0x98, 0x6d, 0x84, 0x0d, 0xaf, 0xd1, 0xa6, 0xda, 0x2c, 0x4b, 0x52, 0xed, 0xcd, 0xad, - 0x97, 0x44, 0x90, 0x85, 0x44, 0x3c, 0xce, 0xa7, 0xbb, 0x66, 0xc9, 0x35, 0xfb, 0x91, 0xb1, 0x18, - 0xdf, 0x38, 0x6d, 0x44, 0x33, 0x8e, 0x92, 0x3c, 0xcb, 0x26, 0x8e, 0xfb, 0xe2, 0xf7, 0xcc, 0x0f, - 0x50, 0x22, 0x56, 0x50, 0x14, 0xb6, 0xd8, 0xda, 0x0a, 0x09, 0x73, 0x8d, 0x41, 0xd7, 0xac, 0x82, - 0xee, 0x6d, 0xda, 0xed, 0xf3, 0x14, 0x88, 0xdb, 0x32, 0xfc, 0x70, 0x83, 0x7a, 0x00, 0xca, 0x26, - 0x6b, 0x8b, 0xc5, 0xb5, 0x16, 0x45, 0x50, 0x26, 0x03, 0xff, 0xb7, 0xcc, 0x11, 0x17, 0x13, 0x5c, - 0x06, 0x51, 0x86, 0xb6, 0x24, 0x1b, 0xe2, 0x9c, 0x3e, 0x7a, 0x33, 0x8c, 0xa6, 0x96, 0x62, 0x0a, - 0x75, 0x5c, 0xf4, 0x9b, 0xb8, 0xd4, 0x2e, 0x30, 0x52, 0xaa, 0x86, 0xb2, 0xaa, 0xcd, 0x20, 0xcd, - 0x66, 0x3a, 0x24, 0xf4, 0x14, 0x8c, 0x78, 0xfb, 0x14, 0x5e, 0x00, 0x79, 0x6a, 0xd9, 0xa5, 0x47, - 0xd4, 0x4e, 0x47, 0xbb, 0x02, 0xd0, 0x19, 0x37, 0x2e, 0x49, 0xb5, 0x07, 0x67, 0x88, 0x47, 0xeb, - 0xd0, 0x7e, 0x5b, 0xb0, 0x87, 0x52, 0xbb, 0xbb, 0x99, 0x6d, 0xc4, 0x6a, 0x24, 0x85, 0xdb, 0x30, - 0xb3, 0xb7, 0x05, 0x36, 0x96, 0x60, 0xef, 0xd8, 0x66, 0x96, 0x50, 0xe8, 0xe8, 0xe6, 0x81, 0x00, - 0x37, 0x6f, 0xa2, 0x03, 0xa3, 0xe8, 0x1a, 0x98, 0xef, 0x0b, 0x92, 0x81, 0xa0, 0xec, 0x7e, 0xc4, - 0x37, 0x5d, 0x03, 0x8b, 0xd2, 0x7c, 0xe3, 0x54, 0x2c, 0x78, 0x60, 0x44, 0x4b, 0x23, 0xb5, 0x82, - 0x86, 0x31, 0x72, 0xf1, 0x96, 0x58, 0xa4, 0xd7, 0x24, 0x34, 0xc3, 0xcb, 0x7c, 0xbb, 0x29, 0xaf, - 0x2a, 0xde, 0xe6, 0x7d, 0xe3, 0x05, 0xb6, 0xe4, 0xe6, 0x0a, 0xe7, 0x6a, 0xde, 0x72, 0x03, 0x57, - 0x00, 0xa3, 0x10, 0x8b, 0x2e, 0xf4, 0x18, 0x8d, 0x6f, 0xa4, 0xda, 0x16, 0x54, 0x29, 0xf2, 0x9a, - 0xe5, 0xd0, 0x42, 0x83, 0x6e, 0x3f, 0xc3, 0x6e, 0xa1, 0xdd, 0xe5, 0x2a, 0xcf, 0xdd, 0x84, 0x01, - 0x53, 0x35, 0x87, 0xa2, 0x86, 0x27, 0xec, 0xb3, 0x4c, 0x28, 0xcc, 0xc5, 0x4a, 0xe8, 0x76, 0xf8, - 0x13, 0xbb, 0x2a, 0x73, 0x1f, 0xb9, 0x45, 0x36, 0x15, 0xcf, 0xc4, 0x2c, 0x84, 0x4e, 0x22, 0xb3, - 0x8e, 0x86, 0x29, 0x8f, 0xbc, 0xf0, 0xe1, 0xe1, 0x41, 0x86, 0xba, 0xee, 0x24, 0xa1, 0x80, 0x43, - 0xf0, 0x7f, 0xde, 0xf0, 0x7a, 0x70, 0xfc, 0x5d, 0x3e, 0xe0, 0x8e, 0x99, 0xae, 0xa3, 0x08, 0x3d, - 0xdd, 0x23, 0x7c, 0x40, 0x86, 0xba, 0x00, 0x00, 0xce, 0x79, 0xdf, 0xb4, 0x79, 0x25, 0xb5, 0x9d, - 0xc2, 0x54, 0xd6, 0x27, 0x5d, 0x45, 0x77, 0x1f, 0x23, 0x2f, 0xcd, 0x8a, 0x7e, 0xa0, 0x3e, 0x49, - 0x03, 0xb4, 0x45, 0x61, 0x08, 0x68, 0xb0, 0x00, 0xb9, 0xda, 0x56, 0xe5, 0xb4, 0x91, 0x30, 0x85, - 0xac, 0x97, 0xcf, 0xb0, 0x0d, 0xf8, 0x1e, 0x2a, 0xc1, 0xd5, 0x99, 0xad, 0x4e, 0x6f, 0x36, 0x31, - 0x19, 0x5e, 0x2e, 0x03, 0x3b, 0x84, 0x9d, 0x02, 0x86, 0x0f, 0x70, 0x62, 0x22, 0xb7, 0x9b, 0x10, - 0xa5, 0xa1, 0x5e, 0x0a, 0xef, 0x80, 0x17, 0xc2, 0xe1, 0xcd, 0x6f, 0x6c, 0x38, 0x3f, 0x5b, 0xff, - 0xc0, 0x2d, 0xb0, 0x78, 0x41, 0xb7, 0x65, 0xeb, 0xee, 0x5c, 0x60, 0xde, 0x17, 0xd3, 0xa4, 0x0d, - 0xfd, 0x12, 0x7d, 0xf9, 0x69, 0x73, 0x47, 0xf7, 0xe1, 0x7c, 0x02, 0x01, 0xa7, 0x14, 0x93, 0x69, - 0xbe, 0x81, 0xf9, 0x62, 0x82, 0x83, 0x8b, 0x0c, 0xe2, 0xef, 0x8c, 0xa5, 0x07, 0x08, 0x7f, 0x71, - 0x60, 0xe2, 0x46, 0x50, 0xf8, 0x33, 0x1c, 0xa6, 0x56, 0x4d, 0xeb, 0xec, 0x29, 0x7d, 0xdd, 0x23, - 0x4f, 0x39, 0x06, 0x3e, 0xaf, 0x34, 0x88, 0x32, 0xb4, 0x39, 0xcb, 0x7e, 0xdb, 0x84, 0x38, 0x3b, - 0x97, 0x59, 0x52, 0x6e, 0x92, 0x22, 0x08, 0x33, 0x39, 0xe4, 0x2b, 0x1d, 0xdb, 0x76, 0xb2, 0xde, - 0x0b, 0xf4, 0x13, 0x88, 0x1e, 0x29, 0x95, 0xd4, 0x4e, 0x76, 0x4c, 0xc9, 0xdf, 0x87, 0x56, 0xef, - 0xe4, 0x39, 0x79, 0x60, 0x6c, 0xfe, 0x7c, 0x8c, 0x5f, 0xbf, 0x4f, 0xad, 0xde, 0x73, 0x1e, 0x4f, - 0x64, 0xc2, 0xa3, 0x23, 0x74, 0xfa, 0x2e, 0x4a, 0x26, 0x16, 0x1e, 0x06, 0x88, 0x80, 0x5f, 0xd8, - 0x82, 0xe4, 0x98, 0x62, 0x68, 0x9a, 0x65, 0x18, 0x2b, 0x17, 0xfd, 0xaf, 0x4d, 0xd2, 0xa2, 0x40, - 0x3a, 0x31, 0x57, 0xd1, 0x06, 0x01, 0x05, 0xff, 0x40, 0x11, 0xc8, 0x6d, 0x63, 0xa4, 0xdf, 0x14, - 0x40, 0x17, 0xb2, 0x63, 0x05, 0x40, 0x13, 0x8c, 0xcf, 0x5e, 0xc2, 0x6e, 0x0a, 0x79, 0x5a, 0x00, - 0xa5, 0xe9, 0x52, 0xc9, 0xce, 0xce, 0xb1, 0x2b, 0x80, 0x05, 0xe9, 0xbb, 0x92, 0x5f, 0xa4, 0x63, - 0x4a, 0x76, 0x8c, 0xae, 0x2e, 0xa1, 0x48, 0xca, 0x90, 0x5f, 0xf0, 0x14, 0x8d, 0x9c, 0x10, 0x30, - 0x44, 0x74, 0xc7, 0xd5, 0xc9, 0xf0, 0xb2, 0x50, 0xdc, 0xa3, 0x4d, 0xcf, 0xb3, 0x64, 0x7c, 0x9e, - 0x2d, 0xb8, 0x2e, 0x84, 0x6b, 0xde, 0xb0, 0x87, 0x6c, 0x61, 0x8e, 0xbf, 0x7d, 0x64, 0xf9, 0x79, - 0x2f, 0x5b, 0xa8, 0x9f, 0x6e, 0xbd, 0x80, 0x7f, 0xca, 0x72, 0x20, 0x44, 0xc4, 0xe7, 0x1e, 0x14, - 0x9f, 0x6a, 0xab, 0xf3, 0x5e, 0x11, 0x66, 0x5f, 0x14, 0x2e, 0xa1, 0xfa, 0xe5, 0x69, 0x8b, 0x2a, - 0x6c, 0x24, 0x59, 0xb6, 0x32, 0x1e, 0x87, 0xf3, 0xe8, 0xa8, 0xf0, 0xfb, 0x3b, 0x1e, 0x9c, 0x39, - 0x64, 0xae, 0x0c, 0x7f, 0x2d, 0x55, 0x21, 0x0d, 0x50, 0xe7, 0xfc, 0xe6, 0x77, 0xa8, 0xb2, 0x19, - 0x2f, 0x12, 0x28, 0x4d, 0x63, 0xec, 0xb6, 0xbf, 0x98, 0x5a, 0xfc, 0xaa, 0x64, 0x74, 0x40, 0xcd, - 0x90, 0x4d, 0x9a, 0xc3, 0x3d, 0xa0, 0x43, 0x83, 0x93, 0x96, 0x72, 0x77, 0x1e, 0xcc, 0x86, 0xa5, - 0x6c, 0x73, 0xd3, 0x1c, 0xee, 0x9b, 0x75, 0x7a, 0xf8, 0xcd, 0x4b, 0x60, 0xe6, 0x46, 0xc6, 0xaf, - 0xc0, 0x81, 0xa2, 0x6e, 0x9d, 0x1f, 0x5e, 0x1b, 0xdf, 0x3e, 0xc6, 0x84, 0xa6, 0x33, 0x2b, 0x3f, - 0x50, 0xa6, 0x88, 0x27, 0x96, 0x97, 0x5e, 0xfc, 0xa6, 0x00, 0x40, 0xa4, 0xf0, 0x7e, 0xcc, 0x7b, - 0x0d, 0x98, 0x18, 0x61, 0x00, 0x40, 0xbb, 0x78, 0x45, 0xaf, 0x25, 0x65, 0x3d, 0x5e, 0xec, 0xff, - 0xb7, 0x17, 0xc8, 0xab, 0x4d, 0x99, 0x4b, 0x5c, 0x69, 0x02, 0x1c, 0xf2, 0xfa, 0x6b, 0xba, 0xe2, - 0x45, 0xc6, 0xe2, 0xe2, 0xac, 0x7b, 0x47, 0xce, 0x38, 0xe0, 0x77, 0xd8, 0x59, 0xc0, 0x29, 0x9a, - 0x31, 0x48, 0x0b, 0xed, 0xe2, 0x31, 0x2e, 0x1f, 0x3f, 0x07, 0x55, 0x91, 0x54, 0xa6, 0x62, 0xe5, - 0xcf, 0x81, 0x1c, 0x5c, 0x65, 0x28, 0x87, 0x87, 0xc5, 0x28, 0x3e, 0x07, 0x13, 0xe5, 0x19, 0x05, - 0xfd, 0xe5, 0x22, 0xc7, 0xaf, 0xe7, 0x37, 0x05, 0xc8, 0x34, 0xb0, 0x60, 0xf3, 0x1b, 0xa4, 0x06, - 0xbb, 0x9c, 0xa0, 0xa2, 0xab, 0x31, 0xb4, 0x6d, 0xa3, 0x37, 0x28, 0x4f, 0x57, 0x1e, 0x40, 0x77, - 0xbd, 0xa4, 0xff, 0x90, 0xf6, 0x40, 0xaf, 0x37, 0x6f, 0xa2, 0xf5, 0x1a, 0xc8, 0x14, 0x3c, 0x0a, - 0xe2, 0x07, 0xa4, 0x85, 0x54, 0x64, 0x17, 0xfb, 0x6c, 0x81, 0x88, 0x6e, 0x1e, 0xf8, 0xf1, 0x2c, - 0xf2, 0x12, 0xc0, 0x72, 0xca, 0x70, 0x62, 0x5a, 0x1a, 0xae, 0x3a, 0x54, 0x2c, 0x18, 0xde, 0x42, - 0x01, 0x6c, 0x8c, 0xd0, 0x1d, 0x7c, 0x27, 0xdc, 0x46, 0x7a, 0xa1, 0x30, 0x93, 0x13, 0x8c, 0xe3, - 0xbe, 0x43, 0x4b, 0x89, 0x08, 0xb4, 0xf0, 0xbd, 0x9e, 0x73, 0xf2, 0xe5, 0xd9, 0xf9, 0xc2, 0xbf, - 0x95, 0x7b, 0x2c, 0x65, 0xd7, 0xc6, 0xdc, 0x1c, 0x3f, 0x1b, 0xa5, 0x47, 0x78, 0xd5, 0xfe, 0x47, - 0xb4, 0x31, 0x56, 0xde, 0x2d, 0x33, 0xc2, 0x48, 0x74, 0x26, 0x35, 0x1e, 0x58, 0x76, 0x00, 0x28, - 0xe4, 0x32, 0x4a, 0x92, 0x07, 0xdb, 0x00, 0x8a, 0x36, 0x61, 0xc6, 0x1d, 0xea, 0x30, 0xc1, 0x26, - 0x4f, 0xd3, 0x0d, 0x33, 0x44, 0xe0, 0x04, 0xe3, 0x01, 0x90, 0x8c, 0x2c, 0x05, 0xc8, 0x1b, 0xcf, - 0x47, 0xa8, 0xd5, 0x3c, 0x9f, 0xc1, 0x86, 0x87, 0x7f, 0xa6, 0xcd, 0xdb, 0xf8, 0x19, 0xf6, 0x2b, - 0x40, 0xad, 0xac, 0xca, 0x4f, 0x0d, 0x3c, 0x23, 0x37, 0xb1, 0x28, 0x6a, 0xc0, 0x19, 0xec, 0x21, - 0x51, 0xe1, 0x61, 0xc2, 0xad, 0x1f, 0x6d, 0x52, 0xae, 0x68, 0x15, 0x70, 0xad, 0x0a, 0xc3, 0xbb, - 0x85, 0xe3, 0x01, 0xaf, 0x2f, 0xbb, 0x58, 0xab, 0xf1, 0x7f, 0x42, 0xc3, 0x30, 0x3a, 0x97, 0xde, - 0x2d, 0x76, 0xc1, 0x93, 0x95, 0xdc, 0xf9, 0x41, 0x60, 0xac, 0xe0, 0x54, 0x27, 0x0f, 0x7c, 0xd0, - 0xd7, 0x85, 0x11, 0x89, 0xad, 0x82, 0x49, 0x4c, 0xb4, 0x69, 0xc1, 0xc0, 0x7e, 0x16, 0xbd, 0xf0, - 0x64, 0x3f, 0x90, 0xa0, 0x81, 0x1c, 0x78, 0xeb, 0x60, 0xdc, 0x84, 0xd1, 0x1d, 0x60, 0x99, 0x28, - 0x5a, 0x18, 0x64, 0x0a, 0x3a, 0xa4, 0x51, 0x3c, 0x3b, 0xcf, 0xd8, 0x3d, 0xd0, 0x61, 0xcc, 0x33, - 0xfc, 0x85, 0x4b, 0x60, 0x82, 0x98, 0x49, 0xa4, 0x8d, 0xcb, 0x7e, 0x9d, 0xcf, 0x36, 0x59, 0x46, - 0x67, 0x17, 0xcd, 0xf6, 0x2c, 0x0b, 0x0d, 0xf8, 0x77, 0x1c, 0x9b, 0xc0, 0x3d, 0x01, 0x08, 0xcc, - 0x6f, 0x5c, 0x53, 0xc0, 0xa0, 0x39, 0x06, 0xe0, 0x78, 0xd0, 0x40, 0xe3, 0xbc, 0xc7, 0x4b, 0x8f, - 0x9f, 0x59, 0x36, 0x4d, 0x64, 0x0f, 0x16, 0x6e, 0xdc, 0x28, 0xfd, 0x47, 0x7f, 0xfc, 0xa6, 0x8a, - 0x20, 0x52, 0xbb, 0x99, 0x3c, 0x21, 0x88, 0x16, 0x17, 0xbb, 0x61, 0x45, 0x1c, 0xc1, 0x11, 0x43, - 0x5a, 0xec, 0x07, 0xb3, 0x27, 0x16, 0xb3, 0xfb, 0x2f, 0xd8, 0x3e, 0xe6, 0x08, 0x20, 0x8f, 0x50, - 0xe5, 0x14, 0x19, 0x6d, 0xe0, 0xb3, 0xbf, 0x7d, 0x24, 0xc6, 0x2a, 0xd7, 0xb2, 0x4d, 0x2d, 0x7b, - 0xc9, 0x08, 0xe0, 0xec, 0xc7, 0x35, 0xcb, 0x56, 0xd1, 0x82, 0x2b, 0x48, 0xe4, 0x16, 0xc5, 0x50, - 0x80, 0xe2, 0xe3, 0x0e, 0x10, 0xe2, 0x37, 0x4f, 0x4f, 0x55, 0xaa, 0x00, 0x36, 0x17, 0x56, 0xd0, - 0x01, 0xd6, 0xaa, 0xc8, 0xfa, 0xc8, 0x6f, 0x04, 0x99, 0x1d, 0x47, 0xa4, 0x55, 0xc3, 0x8a, 0x3e, - 0x42, 0x7d, 0x1c, 0xb0, 0x35, 0x5d, 0x0d, 0x95, 0x4a, 0x43, 0x2a, 0x1a, 0x6f, 0x28, 0x23, 0x80, - 0x94, 0x20, 0x42, 0x51, 0x8b, 0xad, 0xee, 0x2f, 0xa1, 0xc4, 0x81, 0x43, 0xc5, 0x66, 0x65, 0x00, - 0x87, 0xf8, 0xef, 0xef, 0xdd, 0x4f, 0x57, 0xe5, 0x45, 0x95, 0x6c, 0xf8, 0xef, 0xef, 0xcb, 0x79, - 0x31, 0x51, 0xfa, 0x02, 0x19, 0xe5, 0x66, 0x73, 0xac, 0x47, 0x86, 0x40, 0x11, 0xcb, 0x75, 0xe6, - 0x52, 0x66, 0x73, 0xfc, 0x77, 0xbc, 0xfd, 0xa0, 0xb9, 0x3d, 0xef, 0xc5, 0xb0, 0xc9, 0xf8, 0x86, - 0x76, 0x74, 0xe2, 0x19, 0x2a, 0x22, 0x33, 0x6d, 0xa8, 0x62, 0x5a, 0x81, 0x97, 0xfb, 0xfb, 0x14, - 0xe1, 0xc5, 0x88, 0xd3, 0x2c, 0x35, 0x09, 0xd4, 0xe0, 0x38, 0x08, 0x3f, 0x39, 0x57, 0xf9, 0xe7, - 0x60, 0xa6, 0xc0, 0x10, 0x91, 0xb4, 0x64, 0x1c, 0x2c, 0x3e, 0x5b, 0x23, 0x3c, 0x37, 0x43, 0xb4, - 0x29, 0x29, 0xa0, 0x68, 0x6a, 0x1f, 0x1d, 0x65, 0xe3, 0x53, 0xc2, 0x0b, 0x8e, 0xcd, 0xc4, 0xce, - 0x04, 0xfc, 0x06, 0x47, 0x15, 0xf9, 0x0a, 0x29, 0x52, 0xec, 0xe6, 0xd1, 0x00, 0xa3, 0x23, 0xb7, - 0x37, 0x0d, 0x27, 0x6f, 0x00, 0xc4, 0xcf, 0x81, 0x06, 0x86, 0xca, 0x81, 0x5a, 0x5d, 0x41, 0x46, - 0x2e, 0x7b, 0x3b, 0x7c, 0x81, 0x15, 0xd6, 0x7a, 0x3b, 0x7e, 0xb3, 0xe4, 0xd1, 0xc0, 0x51, 0xba, - 0x73, 0x35, 0x92, 0xaa, 0x1c, 0x76, 0xa1, 0x37, 0x0e, 0xbd, 0x49, 0x50, 0x65, 0x99, 0x9f, 0xf9, - 0x40, 0x49, 0xa7, 0x51, 0x92, 0x75, 0xe6, 0xeb, 0xf8, 0x42, 0x72, 0x70, 0x07, 0xfd, 0x91, 0x58, - 0x67, 0xee, 0x84, 0x18, 0x17, 0x5c, 0x2c, 0x09, 0xa1, 0x9e, 0x90, 0x16, 0x84, 0x8e, 0x39, 0x3f, - 0x15, 0x0a, 0xcd, 0x1e, 0x7a, 0x9f, 0x2b, 0x03, 0x5f, 0xa0, 0xd4, 0x8e, 0x95, 0x54, 0xa0, 0x07, - 0x5d, 0xe1, 0xb5, 0x47, 0x2e, 0xe6, 0x84, 0x93, 0x66, 0x14, 0xc1, 0x21, 0x04, 0x40, 0xc2, 0x03, - 0xed, 0x32, 0x3b, 0xc2, 0x20, 0x38, 0x85, 0xf3, 0x84, 0x0c, 0x57, 0xbb, 0x82, 0x88, 0x71, 0x72, - 0x8b, 0x65, 0x66, 0x79, 0x64, 0xc2, 0x9a, 0x15, 0x37, 0x17, 0xb1, 0x4f, 0x1a, 0x5f, 0x95, 0x62, - 0x90, 0x2a, 0x89, 0x27, 0x44, 0x0e, 0xd3, 0xc6, 0x8a, 0x31, 0x46, 0xbd, 0x11, 0xe3, 0x6f, 0x0b, - 0xcc, 0xb0, 0xdc, 0xc2, 0x5a, 0x24, 0xa5, 0x20, 0x2a, 0x13, 0x28, 0xcc, 0x97, 0x35, 0xf9, 0xb8, - 0x9b, 0x0c, 0x76, 0x8c, 0x7f, 0x8d, 0x65, 0x90, 0x00, 0xc1, 0x21, 0xd5, 0x18, 0x3e, 0xb1, 0xa3, - 0xbe, 0xe3, 0x5c, 0x01, 0x67, 0x72, 0x1f, 0x23, 0x4d, 0x9a, 0xf3, 0x61, 0x40, 0xdb, 0x0c, 0x32, - 0xe1, 0xb7, 0x5c, 0x69, 0x9a, 0x97, 0xea, 0xc8, 0x2f, 0xd0, 0xf6, 0xe1, 0x37, 0xf7, 0xec, 0xe4, - 0xe5, 0xd9, 0xe8, 0xbc, 0xe7, 0xcb, 0x66, 0xf5, 0x21, 0x00, 0x45, 0x2a, 0x6b, 0x2c, 0x2a, 0x1c, - 0x2b, 0xdd, 0xe4, 0x8f, 0x08, 0xbe, 0x53, 0x20, 0xbc, 0x0f, 0x9c, 0x1c, 0xd6, 0x6e, 0x1f, 0x3c, - 0x99, 0xd9, 0x29, 0x70, 0x94, 0x28, 0xd3, 0x38, 0x70, 0xe1, 0xcf, 0xe1, 0xa1, 0x23, 0xfe, 0x76, - 0xda, 0xaf, 0xca, 0x50, 0xc4, 0x81, 0x72, 0x10, 0xcb, 0x96, 0x40, 0x88, 0x3a, 0x08, 0x5b, 0xf2, - 0xd7, 0xae, 0xd5, 0x38, 0x64, 0x16, 0xd2, 0x14, 0xf8, 0x2d, 0x5d, 0x2d, 0x03, 0x7a, 0x48, 0x4a, - 0xc9, 0x24, 0x59, 0x05, 0x70, 0x58, 0x0b, 0xd0, 0xe5, 0x72, 0x65, 0xc2, 0x81, 0x98, 0xe5, 0x73, - 0x49, 0xaf, 0xc4, 0x2f, 0x71, 0x7b, 0x40, 0x0d, 0xd3, 0x39, 0xd6, 0x88, 0xb3, 0xb6, 0x17, 0xaf, - 0x00, 0xcd, 0xaa, 0x18, 0xad, 0xbe, 0x3d, 0x51, 0xbf, 0x45, 0xd5, 0x90, 0x22, 0x47, 0xaa, 0xcb, - 0x84, 0xb1, 0x15, 0xf3, 0xe2, 0x5e, 0x9f, 0x9d, 0x8c, 0x80, 0x5f, 0x2c, 0xf4, 0x95, 0xfa, 0x72, - 0x47, 0xa1, 0x2a, 0xf6, 0x22, 0xed, 0xc6, 0x77, 0x09, 0x46, 0x92, 0xff, 0xc0, 0x55, 0x9e, 0xe7, - 0x54, 0xe3, 0xc2, 0x1c, 0xa5, 0x63, 0x28, 0x38, 0x09, 0xdc, 0x4e, 0x0a, 0xff, 0xf7, 0x5c, 0x78, - 0xb1, 0x8a, 0x2a, 0xe0, 0x1b, 0x85, 0x97, 0xe3, 0xe1, 0xe0, 0xcc, 0x61, 0x3a, 0x46, 0xd2, 0x85, - 0xf2, 0x9e, 0x39, 0xdf, 0x2b, 0x5a, 0x50, 0x69, 0x0f, 0x48, 0x74, 0xcc, 0xb4, 0x7e, 0x25, 0xf8, - 0x67, 0x4f, 0xa0, 0x62, 0xd6, 0xdd, 0x90, 0xf8, 0x9b, 0xf4, 0x51, 0x3e, 0x01, 0xbf, 0x71, 0x05, - 0x7b, 0xb8, 0x82, 0x0c, 0x30, 0x8f, 0x15, 0x92, 0xc2, 0xf1, 0x91, 0x2b, 0x99, 0x13, 0xc8, 0x8a, - 0x02, 0x5d, 0x4c, 0xb6, 0x86, 0x7a, 0xba, 0xdc, 0xcc, 0xe6, 0xff, 0xde, 0x6c, 0x56, 0xde, 0xcd, - 0xc6, 0x04, 0x32, 0x10, 0x08, 0x88, 0x2e, 0x89, 0x5f, 0xd2, 0x7f, 0xf8, 0xd9, 0xaa, 0x63, 0x3a, - 0xdd, 0xfe, 0xa0, 0x6b, 0x72, 0x95, 0x61, 0xf3, 0x67, 0xff, 0xc6, 0x4b, 0x7c, 0x44, 0x9e, 0xdd, - 0x79, 0x28, 0xb4, 0x88, 0xe7, 0x21, 0xdf, 0x8f, 0xb7, 0x00, 0xb3, 0x58, 0x3a, 0x37, 0xcc, 0x6f, - 0x1f, 0xa3, 0xbc, 0x20, 0x89, 0xce, 0xc9, 0x26, 0xa6, 0xd8, 0x5f, 0xd0, 0x7a, 0x66, 0x12, 0x3c, - 0x7f, 0xfb, 0xe8, 0xe5, 0xfc, 0xaf, 0xec, 0x92, 0xf9, 0x7a, 0xe3, 0x07, 0x28, 0xfb, 0xed, 0xde, - 0xa2, 0xd1, 0x66, 0xe5, 0xe3, 0x25, 0xd0, 0xda, 0x1e, 0xb9, 0x44, 0x24, 0xb0, 0xc1, 0x6c, 0x77, - 0xfe, 0xd2, 0xef, 0xa6, 0x94, 0x7e, 0x64, 0x7e, 0x67, 0x90, 0xb5, 0x2e, 0xa5, 0x25, 0x40, 0x99, - 0xdb, 0xa6, 0xb1, 0x78, 0xbd, 0xb6, 0xcc, 0x5a, 0x45, 0xbf, 0xc7, 0xc8, 0xe9, 0x92, 0xee, 0xae, - 0xca, 0xf5, 0x76, 0x37, 0x94, 0x6e, 0xd5, 0xf2, 0xff, 0x04, 0x90, 0x61, 0x20, 0x68, 0x00, 0xa0, - 0x40, 0xa5, 0x37, 0xaf, 0x45, 0x95, 0x6a, 0x9e, 0xb7, 0x69, 0x86, 0x92, 0x06, 0x20, 0x7c, 0x85, - 0xae, 0x92, 0x69, 0x07, 0xf5, 0x5c, 0x3f, 0x25, 0x80, 0x7c, 0x52, 0xa3, 0x87, 0xac, 0x64, 0x14, - 0xd2, 0x48, 0x09, 0xa4, 0x96, 0x71, 0x5a, 0x6b, 0xf5, 0x97, 0x57, 0x6f, 0x0c, 0x6f, 0xb1, 0x48, - 0x28, 0x68, 0x1e, 0xeb, 0xae, 0xbd, 0x79, 0xbd, 0x63, 0x7e, 0xc0, 0xd2, 0x87, 0x14, 0x36, 0x21, - 0xe6, 0x58, 0xa6, 0xdd, 0xcd, 0x91, 0xd9, 0xc3, 0x39, 0x80, 0xc7, 0xec, 0x08, 0x7b, 0x8a, 0x53, - 0xa2, 0x87, 0x93, 0xfe, 0x9e, 0x67, 0xec, 0xf1, 0x4c, 0x16, 0xf9, 0xca, 0xac, 0x55, 0xfc, 0x36, - 0xbc, 0xf5, 0x93, 0x28, 0x5c, 0xd3, 0x38, 0x58, 0xd7, 0x4b, 0xe6, 0x2b, 0x62, 0xb8, 0x51, 0x07, - 0x24, 0x61, 0xf0, 0x48, 0x33, 0x1d, 0xdc, 0xf9, 0x31, 0x1a, 0x0e, 0xf2, 0xe2, 0x40, 0x1b, 0xe2, - 0x42, 0x03, 0x6e, 0xaa, 0xe3, 0xa4, 0x9b, 0x5b, 0x1d, 0x21, 0xd5, 0xb7, 0xe4, 0x25, 0xbb, 0x26, - 0x51, 0x9c, 0xba, 0x2d, 0x47, 0xaa, 0x62, 0x97, 0xae, 0xcd, 0xc5, 0x95, 0xb8, 0x46, 0xba, 0xa1, - 0x59, 0x07, 0x71, 0xd2, 0x35, 0x77, 0x07, 0xa3, 0x9a, 0x9c, 0xc9, 0x6a, 0x80, 0x25, 0x96, 0x1b, - 0x19, 0x92, 0xd0, 0x02, 0x0d, 0x91, 0x4e, 0x50, 0x1e, 0x70, 0xe8, 0x1e, 0xcd, 0x1a, 0x09, 0x45, - 0xb5, 0x4f, 0xc1, 0x95, 0x8b, 0x9e, 0xbb, 0x60, 0xaf, 0xbb, 0x6a, 0xeb, 0x84, 0x36, 0x95, 0xce, - 0x04, 0x47, 0x7d, 0x38, 0xf3, 0xc6, 0xd8, 0x23, 0xfc, 0x84, 0x1d, 0x0b, 0x1a, 0x4f, 0x28, 0x53, - 0x62, 0x7d, 0xa2, 0x35, 0xe4, 0x07, 0xe2, 0xc1, 0x8d, 0x74, 0xbe, 0xba, 0x09, 0x64, 0x06, 0xe3, - 0x30, 0x9c, 0xa5, 0xf1, 0x48, 0xbc, 0x9c, 0x93, 0xf4, 0xd4, 0xe0, 0x62, 0x57, 0xca, 0x3d, 0x8b, - 0xee, 0x95, 0x83, 0x22, 0xc8, 0x81, 0x73, 0xa3, 0x83, 0x87, 0xfb, 0x2a, 0x81, 0x54, 0xec, 0x44, - 0x07, 0xbf, 0x58, 0x26, 0xac, 0x2a, 0xfa, 0x2a, 0x09, 0x26, 0xbc, 0x28, 0xc6, 0xec, 0x86, 0x93, - 0x4b, 0x36, 0x74, 0x9e, 0x02, 0x62, 0xd5, 0x7a, 0xb2, 0xf6, 0x12, 0xde, 0x1b, 0x3c, 0x79, 0xf0, - 0xab, 0xec, 0x74, 0x8f, 0x7a, 0xdd, 0x7c, 0x70, 0xd5, 0x4e, 0x5d, 0xec, 0xc0, 0xdb, 0x7b, 0xd1, - 0x05, 0xd9, 0x98, 0x58, 0x62, 0x03, 0x53, 0x65, 0xa5, 0x5f, 0x7a, 0x04, 0x07, 0x2d, 0xc7, 0x6f, - 0xd0, 0x78, 0xf4, 0x06, 0x7b, 0x1e, 0xbb, 0x0d, 0x2d, 0xd0, 0x8b, 0xde, 0x0c, 0xb5, 0x22, 0xab, - 0xd0, 0x90, 0x1a, 0x7c, 0xcc, 0x8a, 0x61, 0xa2, 0xec, 0x47, 0x3c, 0x1a, 0x8a, 0xa0, 0x07, 0xf3, - 0x00, 0x19, 0x43, 0x31, 0xe3, 0x8d, 0xf7, 0x6f, 0x7f, 0x24, 0x49, 0xcf, 0xb6, 0x7c, 0x51, 0x5c, - 0xcd, 0x46, 0x72, 0xa1, 0xbd, 0x5a, 0x11, 0x30, 0x23, 0x12, 0xc3, 0x88, 0x54, 0xda, 0x0c, 0x5c, - 0x29, 0x1d, 0x70, 0x4c, 0x01, 0x56, 0xe1, 0x66, 0x3d, 0x63, 0x09, 0x09, 0xc5, 0x5c, 0xd3, 0x81, - 0xbf, 0xde, 0xbd, 0x0b, 0x58, 0x5c, 0x6a, 0x53, 0x1e, 0xf7, 0x61, 0x16, 0x38, 0x3f, 0x65, 0x12, - 0x3c, 0xe1, 0x20, 0x68, 0xc6, 0xa9, 0x1d, 0xd7, 0xe4, 0x27, 0xef, 0x7b, 0xe0, 0x67, 0xc4, 0xa4, - 0xef, 0x18, 0xdd, 0x9e, 0xfd, 0x63, 0x7b, 0xf6, 0xaf, 0xda, 0xbb, 0x28, 0xde, 0xbb, 0x73, 0xca, - 0x9c, 0x4a, 0x04, 0xf6, 0x27, 0x57, 0xf8, 0x6f, 0x80, 0x6a, 0x63, 0xa0, 0x81, 0x76, 0x2d, 0x30, - 0x5e, 0xd3, 0xe8, 0xb9, 0xfe, 0xf2, 0xf5, 0xbd, 0x4e, 0xe2, 0xc6, 0x19, 0xec, 0x8b, 0x19, 0x1c, - 0x9c, 0x9d, 0x69, 0x33, 0x07, 0xf9, 0xff, 0x03, 0xab, 0x9a, 0xc6, 0xf3, 0xad, 0xeb, 0x5a, 0xed, - 0x15, 0xe4, 0xff, 0x0b, 0x96, 0x53, 0xd9, 0xf3, 0x2b, 0x63, 0x16, 0x6b, 0x3d, 0x82, 0xc3, 0x42, - 0x23, 0xb4, 0xdb, 0x90, 0x11, 0x50, 0x7e, 0x28, 0x80, 0x2c, 0xce, 0x87, 0x89, 0xe9, 0xcd, 0xb3, - 0x3a, 0x92, 0x80, 0x6c, 0x3a, 0x0f, 0x02, 0x98, 0xef, 0xe2, 0x2e, 0x51, 0x11, 0x92, 0xf3, 0x62, - 0xd9, 0x86, 0x90, 0x48, 0xfb, 0x14, 0xd5, 0x14, 0x0d, 0x1f, 0x88, 0x9d, 0xbb, 0xb4, 0x04, 0x3b, - 0x3e, 0xbd, 0x4a, 0x43, 0x33, 0xa0, 0xc5, 0x6a, 0xd3, 0xed, 0xa7, 0xfa, 0x61, 0x80, 0xad, 0xbf, - 0x4e, 0x7c, 0x79, 0x1e, 0x54, 0xe6, 0xf1, 0x63, 0xe2, 0xf9, 0xdc, 0x01, 0xa9, 0xa5, 0x4e, 0xbf, - 0x04, 0x13, 0xf5, 0xb2, 0x4f, 0x5d, 0x13, 0x68, 0x19, 0xc6, 0xdc, 0x2b, 0xba, 0x56, 0x1b, 0x80, - 0xd0, 0x34, 0xac, 0x4c, 0xab, 0xf2, 0xdc, 0x36, 0xc7, 0xf3, 0x70, 0x89, 0xff, 0x8e, 0xd3, 0x62, - 0x4a, 0xe7, 0x15, 0xf4, 0xce, 0x87, 0xa4, 0xa3, 0x77, 0x47, 0x99, 0xcd, 0xb6, 0x9a, 0x17, 0x78, - 0x4c, 0x8a, 0x3a, 0x17, 0x95, 0x3a, 0x17, 0xea, 0x99, 0xc9, 0x57, 0xe8, 0xe4, 0x07, 0xad, 0xce, - 0x86, 0x43, 0x3b, 0x61, 0xb7, 0xda, 0xb1, 0x6d, 0xfc, 0x86, 0x32, 0x3f, 0x60, 0x4c, 0x16, 0xd2, - 0xd5, 0x50, 0xb1, 0x57, 0x76, 0x9e, 0xe1, 0x50, 0x57, 0x65, 0xd9, 0xa0, 0x32, 0xf5, 0x0c, 0x87, - 0x0c, 0xcd, 0x67, 0xf8, 0x17, 0x1c, 0xe2, 0x95, 0x53, 0x7c, 0xbf, 0x41, 0xfd, 0xe2, 0x23, 0x83, - 0x65, 0xb0, 0xe5, 0x12, 0xc6, 0xb4, 0xff, 0x80, 0xd6, 0x7e, 0x65, 0x3c, 0xbf, 0xf8, 0xea, 0x70, - 0xd6, 0xfe, 0x5f, 0x3d, 0x9a, 0x66, 0x46, 0xb9, 0x41, 0x7e, 0x83, 0x20, 0x55, 0x67, 0x91, 0x55, - 0x9a, 0x6e, 0xec, 0x72, 0x6b, 0x81, 0x49, 0xa7, 0xb1, 0xf4, 0x26, 0xf3, 0x75, 0x09, 0xd0, 0x33, - 0xad, 0xd3, 0x2b, 0x73, 0xfc, 0x8b, 0x77, 0xef, 0xaf, 0x37, 0x6b, 0x83, 0xe3, 0x37, 0xba, 0x18, - 0x17, 0xf4, 0x2d, 0xcc, 0xaf, 0x07, 0xa3, 0x5a, 0x74, 0xc5, 0x50, 0x9e, 0xa9, 0x26, 0x19, 0x8e, - 0x35, 0x2c, 0xde, 0xd0, 0x90, 0x5f, 0x51, 0x61, 0x50, 0x0d, 0x37, 0x94, 0x3b, 0x77, 0xd2, 0x13, - 0x76, 0x11, 0x76, 0x49, 0x49, 0xb8, 0xc4, 0x8d, 0x41, 0x71, 0xd3, 0x4b, 0x1b, 0xbc, 0x7e, 0xe7, - 0x52, 0xa2, 0x90, 0x29, 0xc6, 0x06, 0x16, 0x24, 0xf2, 0xf9, 0xa0, 0x51, 0xa2, 0x8a, 0x3b, 0xc6, - 0x3c, 0xc2, 0x66, 0xaa, 0x9a, 0xc4, 0x42, 0x73, 0xb7, 0x41, 0xd3, 0x3b, 0x49, 0x67, 0x59, 0x58, - 0xd3, 0x96, 0x96, 0x0d, 0x8d, 0xfb, 0xd2, 0xe3, 0xb8, 0xd4, 0xfe, 0xad, 0xf3, 0x04, 0x6f, 0x09, - 0xe4, 0x14, 0x96, 0xa0, 0x22, 0xd5, 0x47, 0xb6, 0x04, 0x1d, 0x3e, 0x8f, 0x35, 0x68, 0x44, 0x09, - 0xb5, 0xa9, 0x67, 0x32, 0x0d, 0xba, 0xfb, 0x5c, 0x45, 0x01, 0x3a, 0xa9, 0x32, 0x2f, 0x45, 0x62, - 0x81, 0x0a, 0x79, 0x2e, 0x89, 0x05, 0x7b, 0x6d, 0x78, 0x84, 0x67, 0x3b, 0x9e, 0xa3, 0x39, 0x74, - 0x40, 0x38, 0x45, 0x15, 0x71, 0x53, 0xea, 0xa5, 0x5a, 0x13, 0xc7, 0x4d, 0x02, 0xd3, 0x73, 0x98, - 0x7c, 0x86, 0x17, 0x2d, 0x2b, 0x7f, 0x89, 0x6e, 0xc8, 0x71, 0x11, 0xb9, 0x5e, 0x9c, 0x33, 0xca, - 0xca, 0xd8, 0x5d, 0xc0, 0xa6, 0x58, 0xe4, 0x3b, 0x02, 0xdd, 0xe2, 0x14, 0xac, 0x09, 0x70, 0x6a, - 0x7d, 0x1b, 0xe9, 0x6c, 0xf2, 0x2b, 0x91, 0x63, 0x35, 0x24, 0xf0, 0x8b, 0xd6, 0xe8, 0x19, 0xcb, - 0xa2, 0x20, 0x8c, 0xbc, 0x62, 0x2c, 0xe6, 0xf0, 0xac, 0xe6, 0x65, 0x04, 0xc8, 0x18, 0x2f, 0xcf, - 0xc9, 0x7f, 0x1d, 0xb0, 0xa8, 0xf3, 0x9b, 0x07, 0x33, 0x2f, 0x9b, 0x6e, 0x08, 0x1b, 0x06, 0x8c, - 0xcb, 0x35, 0xea, 0x56, 0x20, 0x1c, 0xf9, 0x29, 0x49, 0x78, 0x7e, 0xce, 0xd6, 0x41, 0xc7, 0x5c, - 0xde, 0x03, 0x2b, 0x88, 0xea, 0x39, 0xfe, 0x82, 0xff, 0xc5, 0x26, 0x6c, 0xdc, 0xd9, 0xff, 0xc4, - 0xdb, 0x64, 0x9e, 0x46, 0x2d, 0x35, 0x41, 0xc3, 0xf2, 0x1e, 0xcd, 0x21, 0x77, 0x71, 0x81, 0x17, - 0xc2, 0x60, 0x86, 0x04, 0xa7, 0xff, 0xc9, 0x89, 0xfa, 0x51, 0xfa, 0x69, 0xab, 0x4d, 0xd5, 0xff, - 0x07, 0xc8, 0xfb, 0xb7, 0xc0, 0xdd, 0x96, 0x25, 0x27, 0xd9, 0x5b, 0x8a, 0xcb, 0x0e, 0xf3, 0x7f, - 0x01, 0x07, 0xc0, 0x9b, 0x14, 0x56, 0x80, 0x2f, 0xb5, 0x35, 0x6a, 0x05, 0x08, 0x61, 0xdd, 0xd4, - 0x06, 0x15, 0x17, 0xf2, 0xb3, 0xc6, 0x07, 0x07, 0x50, 0x43, 0x4c, 0x87, 0x1d, 0xe1, 0x05, 0xa2, - 0x26, 0x0a, 0x29, 0xe7, 0x54, 0x05, 0xa2, 0x46, 0xcc, 0x8d, 0x97, 0x92, 0xb2, 0xe2, 0x16, 0x58, - 0x02, 0xd2, 0x2c, 0xf1, 0xee, 0xc4, 0x48, 0x3a, 0x52, 0xb0, 0xd8, 0x64, 0x72, 0xf1, 0x8d, 0x56, - 0x9f, 0xd1, 0xc5, 0xbe, 0x99, 0x5b, 0xc1, 0xed, 0x91, 0xcf, 0x20, 0x42, 0x56, 0x17, 0xaf, 0xf0, - 0x60, 0x98, 0xe4, 0x00, 0x92, 0xa7, 0x54, 0x2d, 0x2f, 0x8a, 0xb1, 0x5a, 0x23, 0x44, 0xe7, 0x29, - 0x47, 0x85, 0x95, 0x79, 0x46, 0x6b, 0x48, 0xf5, 0xaa, 0x5f, 0x5b, 0x03, 0x12, 0xcf, 0xab, 0x56, - 0x64, 0xa5, 0x66, 0x46, 0x99, 0xf6, 0x89, 0x5d, 0x8d, 0xc8, 0x0e, 0x57, 0xde, 0x52, 0x4b, 0xa7, - 0x84, 0x06, 0xb7, 0x0a, 0xe9, 0x53, 0xe0, 0x08, 0xe1, 0x9f, 0x80, 0x6c, 0x38, 0x5d, 0x74, 0xcf, - 0x65, 0x57, 0x5c, 0x08, 0xa3, 0x7c, 0x50, 0x7c, 0x47, 0x69, 0x2f, 0x85, 0x35, 0x12, 0x1a, 0x3c, - 0xe2, 0xea, 0x80, 0xcf, 0xa4, 0x33, 0x62, 0xa5, 0xce, 0x1e, 0xc3, 0x49, 0xe1, 0x26, 0x72, 0xa9, - 0x8b, 0x8a, 0x4e, 0x5c, 0xa4, 0x62, 0x7b, 0x76, 0x64, 0x27, 0x78, 0x05, 0x01, 0x1d, 0xd3, 0xdb, - 0x49, 0x2d, 0x2b, 0x71, 0xd1, 0xe6, 0x17, 0x43, 0xd0, 0x7c, 0x8f, 0x02, 0xdd, 0xc0, 0x45, 0xb7, - 0x08, 0xb6, 0x07, 0x7f, 0x06, 0x57, 0x76, 0x04, 0x7f, 0x4e, 0xae, 0x28, 0x0a, 0xb0, 0x81, 0x51, - 0x80, 0x13, 0xd3, 0x75, 0x53, 0x2b, 0xc0, 0xfe, 0x7c, 0xaf, 0x45, 0xfc, 0x80, 0x02, 0xf5, 0xb4, - 0xa8, 0x9e, 0x56, 0x54, 0x55, 0x18, 0x43, 0x4a, 0x98, 0xc0, 0x66, 0x8f, 0xfb, 0x23, 0x68, 0x5f, - 0x7e, 0x81, 0x01, 0xe0, 0xcc, 0x78, 0x7a, 0x4a, 0x9f, 0x7a, 0xa5, 0xa6, 0x0c, 0xae, 0xf2, 0x03, - 0xe9, 0x8d, 0x2e, 0x71, 0x59, 0x4f, 0xce, 0xc7, 0xf7, 0x64, 0xcc, 0xcb, 0xbd, 0xe5, 0x74, 0xa6, - 0xa8, 0xb0, 0x88, 0x67, 0xac, 0x8d, 0x92, 0x4e, 0x1b, 0x85, 0xa2, 0x16, 0xd0, 0x3e, 0x49, 0xfe, - 0xdd, 0x54, 0x1a, 0xc0, 0x4e, 0x4b, 0xcd, 0xa9, 0xa1, 0xc1, 0xdd, 0xb3, 0x1d, 0x5f, 0x0b, 0xff, - 0x6c, 0x9d, 0x2c, 0x32, 0x12, 0x72, 0xfc, 0x87, 0x1a, 0xaa, 0xff, 0x8a, 0xfc, 0x10, 0x2f, 0x04, - 0x47, 0x53, 0x1d, 0x5a, 0xea, 0xfb, 0x92, 0x94, 0x51, 0x6c, 0xf4, 0x9a, 0x08, 0x48, 0xd9, 0xd3, - 0xb4, 0x52, 0x2a, 0xfb, 0x90, 0xae, 0xdd, 0x96, 0xf7, 0xf8, 0x8b, 0x3d, 0x34, 0xe9, 0x56, 0xfa, - 0x18, 0x69, 0x38, 0x54, 0x47, 0x41, 0x1c, 0xf3, 0x86, 0xe3, 0x18, 0xdc, 0xa3, 0x1d, 0x4c, 0xb3, - 0x9a, 0x65, 0x58, 0xd8, 0xe3, 0x08, 0x6a, 0xd2, 0x08, 0x47, 0x0d, 0x35, 0x52, 0x0e, 0x85, 0x83, - 0xc0, 0xea, 0x11, 0x53, 0xe0, 0x33, 0xcb, 0xcd, 0x46, 0x79, 0x14, 0x95, 0x41, 0xe2, 0x6f, 0xab, - 0x28, 0xaa, 0x5a, 0x0a, 0x07, 0x46, 0xf2, 0xa8, 0xf2, 0x3b, 0x8a, 0x60, 0xc3, 0xbc, 0xcc, 0xae, - 0x11, 0x91, 0x46, 0x29, 0x8f, 0x12, 0x48, 0xa8, 0x9c, 0xdf, 0x19, 0x76, 0x9e, 0xae, 0x5c, 0x79, - 0x98, 0x0f, 0x11, 0xe1, 0xc3, 0x38, 0x19, 0x0c, 0xc5, 0x56, 0x7b, 0x7b, 0x79, 0x71, 0x32, 0x30, - 0x79, 0x9c, 0xdc, 0x17, 0x6a, 0xea, 0x8b, 0xc1, 0xf3, 0xe7, 0xa6, 0x58, 0x65, 0x73, 0xa2, 0x10, - 0x37, 0xb3, 0x50, 0x53, 0xe6, 0x30, 0x51, 0xbf, 0x17, 0x75, 0xdb, 0x09, 0x71, 0x4e, 0x58, 0xd7, - 0x8f, 0x87, 0xfc, 0xb9, 0x7e, 0x3a, 0x92, 0x31, 0xae, 0xea, 0x43, 0x0a, 0x16, 0x38, 0xc5, 0x1f, - 0x24, 0x03, 0x31, 0x00, 0x66, 0x37, 0x24, 0xaf, 0x19, 0x8f, 0xe2, 0x81, 0x9f, 0x7c, 0x54, 0xc0, - 0x1d, 0xf3, 0x4a, 0x49, 0x6f, 0x39, 0x60, 0x6f, 0xf8, 0x69, 0x88, 0x25, 0x3c, 0x94, 0x78, 0x97, - 0x37, 0x83, 0xa4, 0x33, 0x2e, 0xcb, 0xd7, 0x35, 0xc7, 0xc5, 0x97, 0x4f, 0x1e, 0xa1, 0x9c, 0x88, - 0x17, 0x4f, 0xcb, 0x4b, 0x85, 0x69, 0xb3, 0x32, 0x80, 0xc7, 0x39, 0x30, 0x60, 0xc8, 0x95, 0x93, - 0xab, 0x50, 0xa1, 0x16, 0x6a, 0x34, 0xcf, 0x8a, 0x2b, 0xf7, 0x08, 0x66, 0x21, 0x7f, 0xc6, 0xef, - 0x77, 0xf9, 0x7c, 0x45, 0x96, 0x7a, 0xc7, 0x3b, 0x85, 0x64, 0x5a, 0x9a, 0x88, 0xc7, 0x5d, 0xc9, - 0xe9, 0x9e, 0xc1, 0x87, 0xdc, 0x8e, 0xeb, 0x46, 0x78, 0x79, 0x30, 0x31, 0x3f, 0xf4, 0x5e, 0x99, - 0x43, 0x7a, 0xce, 0xf1, 0x18, 0x9c, 0x5a, 0x36, 0x10, 0xc8, 0x79, 0x0e, 0xd3, 0xb0, 0x98, 0x9f, - 0x3b, 0x93, 0xf0, 0xc8, 0x35, 0xdf, 0x09, 0xd7, 0x36, 0x06, 0xee, 0x1f, 0xd4, 0x8e, 0x90, 0x26, - 0xe3, 0x5d, 0x73, 0x88, 0x2a, 0xf2, 0xdc, 0xf8, 0xde, 0xfc, 0x10, 0x19, 0x11, 0xaa, 0x71, 0x14, - 0xae, 0x70, 0x52, 0x63, 0x89, 0x3b, 0xb6, 0x8b, 0xa6, 0x0b, 0x28, 0xe6, 0x6d, 0xbb, 0xe0, 0x20, - 0xd8, 0x4a, 0xf3, 0xe2, 0xb1, 0x10, 0xaf, 0xbf, 0xe1, 0x57, 0x04, 0x45, 0x85, 0x43, 0x14, 0xb2, - 0xd3, 0x54, 0x4a, 0x40, 0xdc, 0x22, 0x4a, 0x0f, 0xb5, 0x83, 0x2f, 0xd4, 0xd5, 0x1b, 0x38, 0x88, - 0x94, 0xca, 0x0d, 0x78, 0xeb, 0xdf, 0xa3, 0x25, 0xdb, 0xa2, 0xda, 0x50, 0x66, 0xfa, 0x32, 0xc5, - 0x86, 0x42, 0xe1, 0x67, 0x13, 0x2c, 0x0c, 0xf4, 0x00, 0x84, 0x3d, 0x30, 0xb0, 0x0b, 0x06, 0x12, - 0x7b, 0x5c, 0xb7, 0xb1, 0x59, 0xe3, 0x41, 0x83, 0x68, 0x69, 0xe5, 0x4c, 0xfe, 0x48, 0xbf, 0x5c, - 0xe3, 0x21, 0xb7, 0xea, 0xfa, 0xbe, 0xc4, 0xf4, 0x48, 0xfb, 0x7d, 0xe1, 0x97, 0x4a, 0xec, 0x1a, - 0xee, 0x3c, 0xd5, 0x4b, 0xab, 0x9e, 0x23, 0x60, 0xef, 0x79, 0x32, 0x09, 0x5d, 0xb6, 0xde, 0x73, - 0x0d, 0x92, 0x21, 0x86, 0x5b, 0x0e, 0x5c, 0x7e, 0x73, 0x42, 0x29, 0xbd, 0x54, 0x86, 0xfd, 0x51, - 0xae, 0x0e, 0x50, 0xe4, 0x2f, 0xb0, 0x43, 0x7f, 0x08, 0x3b, 0xf3, 0x9b, 0xa5, 0xe3, 0x98, 0x6a, - 0x14, 0xed, 0x01, 0xa5, 0x3a, 0x4b, 0x3d, 0xf5, 0x84, 0xa7, 0x3a, 0x4b, 0x99, 0x2a, 0x1c, 0x06, - 0x63, 0x32, 0xb7, 0xc1, 0x99, 0x1f, 0x2f, 0x2d, 0x33, 0xe7, 0x7b, 0x73, 0x5a, 0x3d, 0x22, 0x5e, - 0x3a, 0x0b, 0x76, 0x6d, 0x73, 0xf4, 0x86, 0x68, 0xec, 0x3b, 0x69, 0xb9, 0x33, 0x3f, 0x3e, 0xb5, - 0x78, 0x8a, 0x35, 0x05, 0x12, 0x98, 0x7b, 0xcf, 0xc5, 0xd9, 0x6e, 0x55, 0x7b, 0xd6, 0xc5, 0x36, - 0x18, 0xb2, 0xa3, 0xa6, 0xdc, 0xeb, 0x7a, 0x79, 0x75, 0xa2, 0xb9, 0xbe, 0x75, 0xc9, 0xa1, 0x15, - 0x6e, 0x15, 0xda, 0x5a, 0xfc, 0xe8, 0x5d, 0xf3, 0xf6, 0xa2, 0x4d, 0x46, 0x3e, 0x0f, 0x50, 0xbd, - 0x01, 0xaf, 0xa2, 0x33, 0x55, 0xa3, 0x42, 0x73, 0xce, 0xa0, 0xda, 0x3f, 0x2a, 0x4a, 0xde, 0x9c, - 0x47, 0xa8, 0x37, 0x57, 0xa1, 0xc2, 0x64, 0x3b, 0x0d, 0x9a, 0xd3, 0xdc, 0x06, 0xdb, 0xac, 0x41, - 0x0f, 0xf2, 0xcf, 0x9c, 0xf4, 0x6a, 0x61, 0x9b, 0x59, 0x0e, 0x3b, 0xa5, 0xa6, 0x24, 0xbb, 0x2d, - 0xb3, 0x18, 0x89, 0x1d, 0xee, 0x91, 0x9d, 0x15, 0xd9, 0x8f, 0xd1, 0x33, 0xb8, 0x29, 0xd4, 0x07, - 0x2d, 0xba, 0x06, 0x0e, 0x81, 0x71, 0x4e, 0x5d, 0xd4, 0x97, 0x85, 0x73, 0x23, 0x35, 0xd1, 0x5f, - 0x7b, 0x48, 0x96, 0x2f, 0x66, 0x1f, 0x53, 0x10, 0x25, 0x11, 0xb4, 0xb7, 0xd6, 0x7e, 0x9d, 0xc4, - 0xb2, 0xef, 0xc1, 0x1e, 0x9d, 0xa1, 0xec, 0xb2, 0xf7, 0xde, 0x3e, 0x83, 0x8d, 0xe7, 0x45, 0x81, - 0x91, 0xc0, 0xa2, 0xb0, 0x7d, 0xe4, 0x55, 0x33, 0x91, 0x66, 0x73, 0x06, 0xbb, 0x33, 0xec, 0x75, - 0x82, 0x23, 0x0f, 0xce, 0x9e, 0x03, 0x6e, 0xc1, 0x13, 0x21, 0xf5, 0x19, 0x8c, 0xfb, 0x4f, 0x4f, - 0xde, 0xd8, 0xb1, 0xb8, 0x5e, 0xdd, 0xd4, 0xe8, 0x20, 0xd9, 0x64, 0xdc, 0xfa, 0x49, 0xb6, 0xf1, - 0x02, 0x6b, 0xda, 0xc0, 0x15, 0xc8, 0x86, 0xe1, 0xb0, 0xd2, 0xd4, 0x47, 0xd3, 0x1a, 0xb0, 0xa2, - 0x66, 0x40, 0x83, 0x1a, 0x64, 0x65, 0x1f, 0xb0, 0x6b, 0x73, 0x27, 0xcb, 0xd9, 0xa6, 0xf7, 0x2e, - 0x37, 0xdf, 0x00, 0x16, 0x6b, 0x5b, 0x23, 0xa4, 0xeb, 0xf4, 0x97, 0xb4, 0x02, 0x20, 0xa1, 0x39, - 0xc7, 0x40, 0x3d, 0xad, 0x2d, 0x9a, 0xbc, 0x5a, 0xde, 0x3c, 0x9a, 0x92, 0xc7, 0xc8, 0x83, 0xe2, - 0xf2, 0x4b, 0xfb, 0x2c, 0x94, 0x2f, 0x3a, 0x75, 0xeb, 0xa9, 0xb2, 0x0b, 0xcf, 0xd1, 0x3c, 0xb0, - 0xb3, 0x57, 0x63, 0x9f, 0x83, 0xd9, 0x94, 0x42, 0x25, 0xee, 0xaa, 0xaf, 0xb6, 0x6e, 0xbf, 0xbf, - 0x6b, 0xd4, 0x83, 0xe7, 0xe4, 0xc0, 0x05, 0x4a, 0xe3, 0x35, 0x6d, 0x78, 0x74, 0x6b, 0x42, 0x92, - 0x79, 0xb4, 0xb1, 0x40, 0x6d, 0xf0, 0xb6, 0xa2, 0x1f, 0x02, 0xad, 0x5c, 0x18, 0xbc, 0xda, 0xab, - 0xd8, 0xe5, 0x43, 0x38, 0xd7, 0x0a, 0x4a, 0xdf, 0x28, 0x5a, 0xe9, 0xad, 0xd2, 0x37, 0x81, 0x6d, - 0x5f, 0xa3, 0x2e, 0x85, 0xb5, 0x57, 0xd6, 0xcb, 0x98, 0xb1, 0xc5, 0xbe, 0x99, 0x61, 0x83, 0xb2, - 0x30, 0xf5, 0xb3, 0x87, 0x7d, 0x0b, 0xfc, 0x03, 0x33, 0x72, 0x3f, 0x2e, 0x8d, 0xf2, 0xbf, 0xbb, - 0x46, 0xb7, 0x09, 0xc2, 0x7a, 0x5f, 0x36, 0x41, 0x8a, 0x37, 0xfc, 0x91, 0x0c, 0xe8, 0xc5, 0x33, - 0x86, 0x6e, 0x56, 0x50, 0xac, 0x28, 0xfc, 0x1b, 0x6a, 0xaa, 0x4a, 0x27, 0x16, 0x35, 0xd1, 0x21, - 0x7e, 0x2c, 0x9a, 0xa3, 0x40, 0x0e, 0xb0, 0x55, 0xd6, 0xa8, 0x80, 0x43, 0xc1, 0x34, 0x1c, 0xe2, - 0x68, 0xa3, 0x64, 0x62, 0xd2, 0x37, 0xa4, 0x24, 0xfe, 0xe8, 0x38, 0xf1, 0x3d, 0x6a, 0xba, 0x2a, - 0x29, 0xe8, 0xb9, 0xd9, 0x32, 0x05, 0x0f, 0x8b, 0x65, 0xe3, 0x09, 0xfd, 0xa2, 0x3d, 0x41, 0x28, - 0xf5, 0x1a, 0x07, 0xe4, 0x84, 0xc9, 0x34, 0xd0, 0xf9, 0x9c, 0x61, 0x1e, 0x85, 0x4d, 0xd6, 0x55, - 0x81, 0xae, 0xbe, 0x30, 0x25, 0x9b, 0x3c, 0x1f, 0x65, 0xb9, 0x80, 0xc9, 0x48, 0x27, 0x17, 0xfb, - 0x85, 0xb7, 0xc8, 0xdd, 0x60, 0x9d, 0x13, 0x1b, 0x85, 0x47, 0x72, 0x13, 0xf9, 0x46, 0x43, 0xc3, - 0xfb, 0xd3, 0xda, 0x6c, 0xca, 0xc1, 0x89, 0x91, 0x69, 0x9e, 0x11, 0x14, 0x6d, 0x6e, 0x41, 0xb9, - 0xab, 0xae, 0x40, 0x39, 0xed, 0x78, 0xce, 0x89, 0xf9, 0xc9, 0x71, 0x7f, 0xd8, 0x57, 0xf2, 0xaf, - 0xe3, 0x0b, 0x3d, 0x33, 0x2a, 0xee, 0x85, 0x13, 0xfe, 0xa7, 0xca, 0x0e, 0x50, 0xa2, 0x2d, 0x82, - 0x4b, 0x3c, 0x92, 0x0f, 0x58, 0x7f, 0x2e, 0xdd, 0xd9, 0x3a, 0x57, 0x63, 0x94, 0x1b, 0xa8, 0x92, - 0x96, 0xd2, 0xd2, 0x8d, 0x0c, 0x86, 0x1c, 0x38, 0xdf, 0x80, 0x3e, 0x7b, 0xfc, 0x1a, 0x8b, 0x21, - 0xef, 0xa5, 0x63, 0xaa, 0x6e, 0x7d, 0x0a, 0x03, 0x5f, 0x45, 0x71, 0xf5, 0xe9, 0xa9, 0xa3, 0xbc, - 0xa9, 0x56, 0x3c, 0xba, 0x9e, 0xad, 0x7d, 0xc2, 0x4e, 0x2c, 0xa9, 0xb5, 0xc5, 0xe3, 0x31, 0xb8, - 0xed, 0x22, 0x49, 0x38, 0xd6, 0x76, 0x8a, 0x9a, 0xec, 0x08, 0x4d, 0x92, 0x38, 0xa5, 0x9c, 0xfa, - 0xe6, 0x90, 0x15, 0x2f, 0xa8, 0x30, 0x0d, 0xcb, 0xd4, 0x53, 0xd5, 0x87, 0xa3, 0x1a, 0x8d, 0x8d, - 0xa7, 0xd8, 0x94, 0xf7, 0x28, 0x41, 0xfd, 0xf0, 0x38, 0x4a, 0xf1, 0xe2, 0x10, 0x69, 0x6b, 0x32, - 0xc4, 0x04, 0xd2, 0x12, 0x7d, 0x05, 0x77, 0x51, 0x01, 0x49, 0xb5, 0x99, 0xc1, 0x19, 0x00, 0x96, - 0xeb, 0xae, 0x63, 0xa1, 0x5a, 0x1a, 0xda, 0xdb, 0x54, 0xb4, 0xec, 0xd0, 0x1d, 0x26, 0x27, 0xd9, - 0xa3, 0x82, 0x64, 0x47, 0xe7, 0xf4, 0x1e, 0xda, 0x2f, 0x0f, 0x1f, 0xd1, 0xf4, 0x08, 0x70, 0x41, - 0x76, 0x8c, 0x7c, 0x12, 0x34, 0x88, 0x16, 0x9c, 0x3e, 0x67, 0xbb, 0xa8, 0xc7, 0x23, 0x63, 0xbe, - 0xc2, 0x23, 0x3d, 0x73, 0x7f, 0xff, 0xf8, 0xd3, 0xf1, 0x0b, 0x33, 0xb7, 0xd1, 0x53, 0xe2, 0x30, - 0xfd, 0x0a, 0x4d, 0xe6, 0x10, 0xe8, 0x7a, 0x3c, 0x8d, 0x54, 0x43, 0x2d, 0x65, 0xb5, 0x2c, 0x75, - 0x21, 0xf9, 0xa2, 0xd4, 0x8c, 0x9d, 0xec, 0xaf, 0x01, 0x1c, 0xe7, 0x07, 0x00, 0x9c, 0x50, 0xe3, - 0x48, 0xde, 0xae, 0xe3, 0xec, 0x01, 0xc0, 0x33, 0x8d, 0x81, 0x51, 0x60, 0x9c, 0x0d, 0x39, 0x08, - 0xbb, 0xe9, 0x66, 0x0e, 0xcc, 0x9b, 0xf0, 0xa5, 0x0c, 0x80, 0x41, 0x52, 0x33, 0xf6, 0xf4, 0x84, - 0x51, 0x82, 0x00, 0xb4, 0x3a, 0xe8, 0x85, 0x09, 0x4d, 0xd2, 0x96, 0x11, 0xea, 0x46, 0xa1, 0xf2, - 0x23, 0xe9, 0x49, 0xbe, 0xbf, 0x7c, 0x7a, 0x02, 0x8c, 0x03, 0x4f, 0x13, 0x05, 0xe2, 0x14, 0x65, - 0x72, 0xfb, 0xe5, 0x4b, 0x6b, 0x58, 0x55, 0xfd, 0xc5, 0x36, 0xa5, 0x23, 0x27, 0xf8, 0x6b, 0x57, - 0x2f, 0x35, 0xc2, 0x2e, 0xbf, 0x51, 0x4b, 0x4b, 0x65, 0xc5, 0x42, 0xfa, 0x1d, 0x76, 0xa5, 0x7c, - 0xcf, 0x92, 0x74, 0x13, 0xef, 0x97, 0x9d, 0xb8, 0x9c, 0xe7, 0x6e, 0x90, 0xb0, 0x63, 0xb2, 0xf0, - 0x1f, 0xa3, 0xe0, 0xaa, 0xc4, 0x36, 0x7f, 0xa4, 0xb7, 0x19, 0xe2, 0x11, 0x21, 0xb2, 0x6a, 0x73, - 0x1b, 0x54, 0x62, 0x5a, 0xc0, 0x53, 0x14, 0xdc, 0xa8, 0xff, 0x02, 0x39, 0x0c, 0x3c, 0xe4, 0x23, - 0x81, 0x9e, 0x3a, 0x30, 0xe7, 0x9d, 0xf7, 0xf0, 0x68, 0x01, 0xb6, 0x4c, 0xc8, 0x28, 0x59, 0x26, - 0x8a, 0x94, 0x05, 0x40, 0x71, 0x86, 0x1e, 0xbd, 0xa5, 0x67, 0xb0, 0x88, 0x2b, 0xb9, 0xdd, 0xdd, - 0x96, 0xee, 0xb9, 0x44, 0xd2, 0x1c, 0x5f, 0x34, 0x7f, 0x62, 0x11, 0xc2, 0xb6, 0x74, 0xd6, 0x25, - 0x72, 0xc1, 0x1b, 0x50, 0x65, 0xe4, 0x24, 0x4b, 0xae, 0x8c, 0x0d, 0xcb, 0x86, 0xef, 0xae, 0x98, - 0x62, 0xf4, 0x5b, 0xde, 0xb6, 0x34, 0xda, 0x32, 0xb4, 0xd2, 0x02, 0xc4, 0x23, 0x57, 0x71, 0x72, - 0x84, 0xd2, 0x02, 0xd4, 0xd5, 0x14, 0x56, 0xdf, 0x34, 0x93, 0xe4, 0xf7, 0x6f, 0xfc, 0xc3, 0x0f, - 0x4e, 0xd5, 0x89, 0x4e, 0xe1, 0xad, 0x2b, 0x12, 0x3e, 0xd4, 0x0e, 0x0f, 0x35, 0x8d, 0xd3, 0xc8, - 0xb2, 0xb5, 0xd3, 0x2f, 0xc2, 0xf0, 0xbd, 0x3c, 0xfa, 0x16, 0x70, 0x8f, 0x4f, 0x4f, 0xd4, 0x6f, - 0x45, 0xb0, 0x0b, 0xc7, 0x26, 0xb9, 0x68, 0x23, 0x2d, 0xb4, 0xad, 0x34, 0x84, 0x30, 0x76, 0xa0, - 0x7b, 0x79, 0x72, 0xe7, 0x96, 0x76, 0xc3, 0x00, 0x4b, 0x71, 0x3f, 0x6b, 0xf4, 0xb6, 0xd8, 0x24, - 0xc2, 0xdb, 0x1a, 0xbd, 0x66, 0x3c, 0x2b, 0x79, 0x5d, 0xa3, 0x84, 0x25, 0x3c, 0x95, 0x6e, 0xde, - 0xd2, 0xee, 0x66, 0x11, 0x43, 0xe7, 0xe0, 0xb9, 0xe2, 0x7d, 0x0d, 0xe6, 0x3f, 0x6d, 0xda, 0xa8, - 0x0f, 0x1f, 0x89, 0xad, 0x22, 0x03, 0x6f, 0xba, 0xd7, 0xc5, 0x9c, 0xc1, 0x18, 0xbd, 0xa9, 0x35, - 0x64, 0x9e, 0xa7, 0x4a, 0xaf, 0xe7, 0xf3, 0x70, 0xd9, 0x5d, 0xfb, 0x61, 0x73, 0x4e, 0x56, 0xcb, - 0xe9, 0xdd, 0x37, 0xe7, 0xcc, 0xaa, 0x39, 0x11, 0x9d, 0xf6, 0xfa, 0x2d, 0x3d, 0xc8, 0xd4, 0xec, - 0x04, 0xfa, 0x3e, 0xe1, 0xc5, 0xbe, 0x23, 0x42, 0xb6, 0xa1, 0x1b, 0x49, 0x67, 0x54, 0xd3, 0x50, - 0x4c, 0xad, 0x8a, 0x34, 0x1c, 0x25, 0xfb, 0x15, 0xbd, 0x43, 0x92, 0x8b, 0xa3, 0xcc, 0x99, 0x34, - 0x0d, 0xd9, 0x15, 0xaa, 0xe0, 0x41, 0x82, 0x3b, 0xe7, 0x6c, 0x7e, 0x3e, 0x3f, 0x3a, 0x22, 0x9e, - 0x3e, 0x76, 0x79, 0x0e, 0x9f, 0x8b, 0xf0, 0x63, 0xe9, 0x3b, 0x53, 0x41, 0x66, 0x1f, 0x22, 0xa9, - 0x39, 0x97, 0x0a, 0x89, 0x0a, 0x9d, 0xcf, 0x25, 0x69, 0x3c, 0x2a, 0x44, 0xd3, 0x2e, 0xb9, 0x25, - 0xa2, 0xde, 0x5f, 0xef, 0x34, 0xbf, 0x57, 0x06, 0x31, 0x18, 0xb1, 0x31, 0x8e, 0xe4, 0xf8, 0xd8, - 0xe2, 0x9d, 0x6d, 0x37, 0xc0, 0x37, 0x8f, 0xa8, 0x0d, 0x2e, 0x28, 0x3f, 0x32, 0x6d, 0xe5, 0xbd, - 0x5f, 0x79, 0x1f, 0x5c, 0xa1, 0x72, 0x68, 0x49, 0x56, 0x72, 0xef, 0x80, 0xf0, 0xa5, 0xe4, 0x22, - 0x8b, 0xbc, 0x27, 0x57, 0x74, 0x09, 0x5d, 0x98, 0xf4, 0xa3, 0xdf, 0xbf, 0xa6, 0x6b, 0x44, 0x8d, - 0x18, 0x16, 0x8b, 0x27, 0xea, 0xc5, 0x22, 0x57, 0xf6, 0x7e, 0x45, 0xe2, 0x6e, 0x7a, 0x6f, 0xef, - 0x41, 0x3d, 0x17, 0xd9, 0xfd, 0x7b, 0x3b, 0xa8, 0x48, 0x16, 0xa6, 0xdc, 0x1c, 0x9e, 0x4b, 0xb1, - 0x97, 0xf7, 0xe6, 0xd5, 0xa7, 0x42, 0xba, 0x1d, 0x77, 0x97, 0xf7, 0xb9, 0x79, 0x35, 0x2d, 0xb7, - 0xc2, 0x01, 0x87, 0xa9, 0x8d, 0x1b, 0xd4, 0x6e, 0x89, 0xa4, 0xbf, 0x43, 0xe0, 0x07, 0x37, 0x87, - 0x87, 0x1b, 0x45, 0x4e, 0xc1, 0x1d, 0xc0, 0x4a, 0x5a, 0x84, 0x72, 0x60, 0x25, 0xeb, 0x5a, 0x25, - 0x53, 0xba, 0x6a, 0xfa, 0xa4, 0x88, 0xef, 0x8b, 0x1e, 0x90, 0x8f, 0x69, 0xa5, 0x4e, 0x6f, 0xb1, - 0x50, 0x2b, 0x54, 0xbd, 0x2d, 0x62, 0x19, 0xdb, 0xdb, 0x36, 0x4a, 0x79, 0xe3, 0xa7, 0x0d, 0x15, - 0x12, 0xab, 0x63, 0xb5, 0x3b, 0x1b, 0xd7, 0xdb, 0x32, 0x50, 0x6b, 0xd7, 0x38, 0xeb, 0xdd, 0x68, - 0x18, 0x61, 0xd9, 0x70, 0xeb, 0xe8, 0xe0, 0x94, 0x58, 0x77, 0xd3, 0x79, 0x12, 0x05, 0x01, 0xac, - 0x6a, 0xf4, 0xdf, 0x3e, 0xbb, 0xeb, 0x3c, 0xce, 0xd8, 0xca, 0xbb, 0xf5, 0x31, 0xfc, 0x98, 0x34, - 0x9d, 0x27, 0x34, 0x0e, 0x58, 0x1c, 0xc8, 0x11, 0xa0, 0x67, 0x79, 0x20, 0x14, 0x32, 0x93, 0x26, - 0x53, 0x09, 0xf1, 0xcc, 0xc9, 0x86, 0x25, 0xe9, 0x25, 0x73, 0xf1, 0x5f, 0xf1, 0x81, 0x8b, 0xfd, - 0x9c, 0x21, 0x7c, 0x2c, 0x85, 0xa1, 0x14, 0x5b, 0xd0, 0x58, 0x16, 0x2a, 0xda, 0x07, 0x9a, 0xe0, - 0xaf, 0xdf, 0xc7, 0xdc, 0x68, 0x43, 0xc0, 0xc2, 0x68, 0x73, 0xbd, 0x32, 0xd2, 0xd8, 0x9b, 0x33, - 0x34, 0x8d, 0x4b, 0xd1, 0x34, 0x91, 0x9b, 0x36, 0x54, 0x8a, 0x0c, 0xb0, 0xc8, 0xc7, 0x15, 0x93, - 0x84, 0x37, 0x5b, 0x14, 0xe6, 0x84, 0x11, 0x4b, 0xa9, 0x51, 0x76, 0x8f, 0xd3, 0xa0, 0x17, 0x7b, - 0x89, 0xc5, 0x5e, 0x29, 0x3d, 0x31, 0xa8, 0xdb, 0xc6, 0xca, 0x4b, 0x8d, 0x68, 0x0e, 0xc8, 0x1d, - 0x05, 0xde, 0xb9, 0x4a, 0x3e, 0xd1, 0x67, 0xf3, 0x48, 0x8c, 0xef, 0xc8, 0x1c, 0xc2, 0xcb, 0x92, - 0x0c, 0x2f, 0x4a, 0xac, 0x93, 0xff, 0x69, 0x51, 0xad, 0xf0, 0x3c, 0x81, 0xfc, 0x7b, 0x21, 0x97, - 0x79, 0x8c, 0xc2, 0x21, 0x77, 0x4b, 0x8a, 0xbf, 0x78, 0x7b, 0x5f, 0x22, 0xe6, 0x12, 0x6d, 0xf4, - 0x9d, 0xef, 0x77, 0x60, 0x74, 0xf4, 0xff, 0xa1, 0x30, 0x27, 0xb5, 0x56, 0x3f, 0x04, 0x9a, 0x85, - 0x7e, 0x87, 0x5c, 0xa0, 0xc2, 0x8f, 0x35, 0x99, 0x22, 0x15, 0x91, 0x08, 0x17, 0x0d, 0x5d, 0xe3, - 0x0f, 0xb4, 0xf7, 0xe4, 0x16, 0xfb, 0x64, 0x6e, 0x49, 0xd8, 0x19, 0x98, 0x3b, 0x3c, 0x48, 0xc7, - 0x40, 0x01, 0x00, 0xd1, 0x3f, 0x34, 0xa3, 0xe5, 0xd2, 0xcc, 0x29, 0x15, 0x8f, 0x53, 0x48, 0xbc, - 0x25, 0x07, 0xce, 0xde, 0x32, 0x83, 0xbf, 0xfc, 0x03, 0x1c, 0xc3, 0x39, 0x6a, 0xd5, 0x91, 0x70, - 0x79, 0x3a, 0x34, 0x79, 0x2b, 0x0b, 0x46, 0xed, 0xa0, 0xdd, 0x00, 0xde, 0x26, 0xa8, 0x7d, 0x86, - 0x32, 0x43, 0x9c, 0x0d, 0xe8, 0x54, 0x9e, 0xd7, 0xfa, 0x8f, 0x32, 0x08, 0x7d, 0x04, 0xa5, 0x83, - 0x56, 0xf9, 0x64, 0x4d, 0xcc, 0x5f, 0xe9, 0xde, 0x82, 0xba, 0x8f, 0x06, 0xa6, 0x64, 0xf2, 0x19, - 0xb2, 0xec, 0x2e, 0x4a, 0x6e, 0xf8, 0x70, 0x80, 0xb5, 0x30, 0x30, 0x3f, 0x02, 0x1e, 0x19, 0x91, - 0x02, 0x21, 0xd3, 0x85, 0xae, 0x7f, 0xc4, 0x67, 0x3e, 0x6c, 0x32, 0x2b, 0xdd, 0x5d, 0x8f, 0x11, - 0x44, 0xe1, 0x35, 0x64, 0xc2, 0xda, 0xba, 0xa6, 0x74, 0x43, 0xf3, 0x88, 0x54, 0xc4, 0xf0, 0x11, - 0xc9, 0x88, 0xa1, 0xec, 0x57, 0x9e, 0x8f, 0x14, 0x8a, 0x8f, 0x98, 0x1f, 0xa2, 0x35, 0x12, 0xa4, - 0xff, 0x8a, 0xce, 0xef, 0x58, 0x40, 0xa4, 0x40, 0x6f, 0x71, 0x3b, 0xc3, 0xa9, 0x4a, 0x7e, 0x6b, - 0xf1, 0xb7, 0x89, 0x75, 0x17, 0xf9, 0x6a, 0xa4, 0x1d, 0xe6, 0xaf, 0xfa, 0x4f, 0x2c, 0x5c, 0xe7, - 0x4c, 0x6a, 0x77, 0x24, 0xb2, 0x1e, 0x58, 0xba, 0xe2, 0xd9, 0x1c, 0x6d, 0x6f, 0x2f, 0x99, 0xf3, - 0x56, 0x30, 0xaa, 0xe4, 0x0c, 0xfd, 0x9a, 0xce, 0x02, 0x2f, 0xbc, 0xd9, 0x22, 0x58, 0xaa, 0xca, - 0xb1, 0xb0, 0x87, 0x8a, 0x48, 0x89, 0x7b, 0x7f, 0xa9, 0xce, 0x04, 0x91, 0x96, 0x38, 0x0b, 0x44, - 0xc2, 0x4a, 0x87, 0x2e, 0xe2, 0x22, 0xc8, 0xee, 0x48, 0x6f, 0xbe, 0xfc, 0xaf, 0x55, 0x21, 0x49, - 0x25, 0xc9, 0xda, 0xe8, 0xe3, 0x0b, 0xd2, 0x1b, 0x84, 0x30, 0xbc, 0xa2, 0xbd, 0x44, 0x2f, 0xad, - 0x23, 0x7d, 0x57, 0x19, 0x28, 0xaf, 0xb1, 0x1c, 0x6a, 0x6d, 0xbb, 0x8a, 0x6b, 0x2d, 0x49, 0x56, - 0xab, 0x23, 0x2f, 0xbd, 0x14, 0x8b, 0x87, 0x86, 0x56, 0x43, 0x8d, 0xba, 0x57, 0xc7, 0x42, 0x25, - 0xfe, 0xdc, 0x60, 0x24, 0xeb, 0xa0, 0x0e, 0x48, 0x54, 0xab, 0x2c, 0x5e, 0xb1, 0x3e, 0xca, 0x35, - 0x5d, 0x39, 0xcc, 0xb5, 0x77, 0x83, 0x04, 0x66, 0x81, 0x07, 0xe9, 0x3e, 0x57, 0x53, 0x49, 0xdc, - 0x22, 0xd7, 0xe5, 0xaa, 0x7c, 0x4a, 0xe6, 0xe3, 0x7e, 0x79, 0x89, 0x30, 0xca, 0xce, 0x25, 0xd7, - 0xc5, 0x43, 0xd6, 0x73, 0x73, 0xe0, 0xb0, 0xdd, 0x3c, 0xa5, 0xc1, 0xae, 0x32, 0x64, 0x77, 0x4a, - 0x0e, 0xe3, 0x03, 0xbb, 0x93, 0x0a, 0x8d, 0x86, 0xde, 0x72, 0x93, 0x61, 0x47, 0x69, 0x28, 0x5e, - 0xb3, 0xbb, 0x28, 0x0c, 0x2d, 0x4a, 0xb5, 0xf7, 0x56, 0xad, 0x7b, 0x4d, 0x25, 0x7e, 0x6f, 0xcb, - 0x8a, 0x3d, 0x4d, 0x2b, 0x34, 0xdd, 0xfb, 0x5d, 0x2d, 0xed, 0xa7, 0xe7, 0xae, 0xce, 0xca, 0xd7, - 0x19, 0x5a, 0xb0, 0x56, 0xb5, 0x77, 0xb5, 0xee, 0xaa, 0x5e, 0xfe, 0x5f, 0xd2, 0xe1, 0xaf, 0xb1, - 0xbc, 0x50, 0xd2, 0xbe, 0xbc, 0xd7, 0x9a, 0xed, 0x83, 0xa6, 0xb9, 0xaf, 0xab, 0xee, 0xb7, 0x75, - 0x98, 0x54, 0xf8, 0x95, 0x89, 0x64, 0x39, 0x5d, 0x90, 0x7d, 0x91, 0xc6, 0x39, 0x50, 0x44, 0xc1, - 0x52, 0x53, 0x3b, 0x57, 0x5b, 0x68, 0xd4, 0x40, 0xd7, 0x86, 0x34, 0x32, 0x14, 0x8d, 0xdd, 0x51, - 0x93, 0x6a, 0x7a, 0x4d, 0x47, 0x79, 0x3a, 0xda, 0x4f, 0xc3, 0x58, 0x8d, 0xb3, 0x55, 0xb6, 0xf1, - 0xb8, 0xaf, 0x7a, 0x72, 0xb3, 0x87, 0x06, 0xb2, 0xbb, 0x3f, 0xf6, 0x95, 0x81, 0x15, 0x68, 0x08, - 0x61, 0x46, 0x9f, 0x2c, 0xca, 0x8a, 0xaa, 0x87, 0x34, 0xac, 0xfe, 0x0b, 0x8f, 0x86, 0xf5, 0x6a, - 0xb1, 0x90, 0x98, 0xa0, 0xd0, 0xcf, 0xc0, 0x0d, 0xff, 0x4c, 0x47, 0x6d, 0x17, 0xa5, 0xc2, 0xcb, - 0x94, 0x6c, 0x05, 0x5b, 0xd5, 0x26, 0xe3, 0xec, 0x3e, 0x33, 0x04, 0x84, 0x2a, 0x66, 0xe2, 0x19, - 0x66, 0xf1, 0x36, 0xe8, 0x69, 0x6f, 0x1d, 0xe3, 0x6d, 0xa8, 0x4b, 0x44, 0x17, 0x82, 0x23, 0xe7, - 0xb8, 0xdd, 0x93, 0x81, 0xb2, 0x71, 0x80, 0x32, 0x93, 0x76, 0xde, 0xdc, 0x3a, 0x43, 0xd3, 0xc2, - 0x7c, 0x4b, 0x8e, 0xf5, 0x48, 0x1d, 0xa6, 0xdb, 0x35, 0x7b, 0x85, 0x2b, 0x0b, 0x15, 0xd0, 0xe6, - 0xaa, 0x63, 0x03, 0x83, 0xe4, 0x6a, 0xc3, 0x2d, 0xdd, 0x4e, 0xb5, 0x6e, 0x97, 0xbd, 0x52, 0x3a, - 0x55, 0xb8, 0x71, 0xc9, 0x95, 0x71, 0x7d, 0x0e, 0x9a, 0x86, 0xd5, 0x53, 0xac, 0x26, 0x74, 0xe8, - 0x1f, 0x03, 0xc7, 0x8e, 0xfc, 0x01, 0x23, 0x09, 0x27, 0x9c, 0x61, 0x48, 0x79, 0x29, 0x1d, 0xe5, - 0x4b, 0x60, 0x29, 0xc5, 0x77, 0xaa, 0xf8, 0xf3, 0xe9, 0x32, 0x7f, 0x2d, 0x3c, 0x87, 0x00, 0x73, - 0xb3, 0x32, 0xa4, 0x5c, 0xfb, 0x77, 0xe0, 0x20, 0x84, 0xfc, 0x47, 0xa4, 0x09, 0x15, 0x95, 0x76, - 0x03, 0x00, 0x1a, 0xd8, 0x3c, 0xcd, 0xae, 0x35, 0xab, 0x44, 0x78, 0x7d, 0x93, 0x0a, 0x33, 0x7c, - 0xd9, 0x26, 0xd4, 0x2f, 0x6d, 0x00, 0x84, 0x01, 0xc0, 0xbe, 0xda, 0xff, 0x52, 0x07, 0xac, 0x69, - 0xe9, 0xe2, 0x68, 0xa0, 0x3a, 0x18, 0x18, 0x88, 0x71, 0xbe, 0xba, 0x78, 0x87, 0xb7, 0x27, 0xe8, - 0xb6, 0xa6, 0x38, 0x92, 0x4a, 0x17, 0x27, 0x3a, 0x6e, 0x54, 0xca, 0x7b, 0xb1, 0xaf, 0xf9, 0x3d, - 0xe1, 0xad, 0x37, 0xad, 0x4e, 0x1c, 0xf5, 0xd5, 0x76, 0xfb, 0xa2, 0xdd, 0x3d, 0x8c, 0x2c, 0xde, - 0xf1, 0x80, 0x6c, 0xc6, 0x2c, 0x91, 0xae, 0xf1, 0xa5, 0x19, 0xd2, 0xf6, 0x49, 0xf6, 0x67, 0x34, - 0xc9, 0x62, 0x0e, 0x25, 0x8e, 0xd9, 0xd7, 0x80, 0x42, 0xd3, 0xa3, 0xdb, 0xa3, 0x97, 0x97, 0x08, - 0x78, 0xf2, 0xd8, 0x9f, 0xa1, 0x5c, 0x68, 0xcf, 0x6e, 0xa6, 0x7f, 0x59, 0x37, 0x9b, 0x27, 0x1e, - 0xf6, 0x2a, 0xf5, 0x0d, 0x78, 0x98, 0x77, 0x3f, 0x1a, 0x8d, 0x87, 0x9d, 0x3a, 0x69, 0x8b, 0xea, - 0xd9, 0x56, 0x9c, 0x56, 0xa5, 0x3f, 0x2c, 0x01, 0xa7, 0x78, 0xda, 0x0d, 0xce, 0x1c, 0x3a, 0xfd, - 0xfa, 0x62, 0x2b, 0x73, 0xd8, 0x65, 0xc3, 0xba, 0x57, 0xae, 0x7c, 0xdc, 0xda, 0x3f, 0x3e, 0x92, - 0x66, 0x34, 0xec, 0xd7, 0xdc, 0xe5, 0xa0, 0x08, 0xe0, 0x42, 0xba, 0xac, 0xd8, 0x8e, 0x88, 0xe5, - 0xf9, 0x22, 0x76, 0x14, 0xcd, 0x03, 0xdf, 0x72, 0x29, 0xfa, 0x33, 0x2a, 0x65, 0x09, 0x66, 0xa9, - 0x40, 0xa7, 0x6c, 0xfb, 0x67, 0x7b, 0xf7, 0x69, 0xc1, 0x82, 0x8b, 0xce, 0xb3, 0x23, 0x76, 0xf4, - 0x6c, 0x67, 0x9f, 0xa4, 0xe9, 0xd4, 0x8f, 0xc2, 0x8b, 0x09, 0xb5, 0x5f, 0x3a, 0xfa, 0x19, 0x3e, - 0xdb, 0xc3, 0x63, 0x90, 0xea, 0x77, 0xd4, 0x1c, 0xbf, 0x21, 0x25, 0xf7, 0xb2, 0x8a, 0x7c, 0xcb, - 0x2e, 0x44, 0x3f, 0x62, 0x12, 0xc1, 0xcc, 0xb8, 0xa5, 0xb0, 0x31, 0x57, 0xd6, 0x1f, 0xbf, 0xf3, - 0x05, 0xd1, 0xea, 0x90, 0xf3, 0xa1, 0xa3, 0x5b, 0x80, 0x27, 0x1c, 0xb3, 0x74, 0x4b, 0x84, 0x95, - 0x4d, 0x2b, 0x47, 0x5b, 0xeb, 0x51, 0x1c, 0xd7, 0x0e, 0xe2, 0x66, 0x67, 0x28, 0x02, 0x38, 0x76, - 0x92, 0xdd, 0x48, 0x75, 0xcb, 0xb9, 0x2c, 0xc9, 0x88, 0x5d, 0x34, 0xf5, 0xb7, 0x8f, 0xfc, 0x00, - 0x76, 0xa4, 0xc7, 0x13, 0xa9, 0x6a, 0xbf, 0x5d, 0x2f, 0x20, 0x76, 0xd0, 0x4b, 0x6d, 0x85, 0xea, - 0xf8, 0x92, 0xb1, 0x7e, 0x19, 0xd1, 0x51, 0xac, 0xf4, 0x7e, 0x64, 0xc7, 0x1b, 0xf2, 0x16, 0x5d, - 0x85, 0xac, 0x0a, 0xe1, 0xc1, 0x4f, 0x9c, 0x5d, 0x9e, 0xed, 0xe8, 0xa0, 0x2a, 0xa5, 0x97, 0xa3, - 0x96, 0x6c, 0x51, 0x7f, 0x5a, 0x0b, 0xfc, 0xb0, 0x33, 0x62, 0x84, 0x28, 0x3a, 0x68, 0x2a, 0x4a, - 0x45, 0x86, 0xa2, 0x06, 0xc5, 0x8d, 0xa4, 0xb4, 0x9d, 0x2f, 0xfa, 0x8d, 0xee, 0x0b, 0x86, 0x9f, - 0xae, 0xf2, 0x8a, 0x05, 0x07, 0x37, 0xfa, 0x22, 0x8b, 0x1d, 0xbc, 0x41, 0xe0, 0x2a, 0xe7, 0x90, - 0x37, 0x18, 0x86, 0x18, 0x50, 0x12, 0x1d, 0xd1, 0x95, 0xf2, 0x13, 0x35, 0x02, 0x88, 0x70, 0x0f, - 0xc0, 0x74, 0x4f, 0xb5, 0xd4, 0x0a, 0x5a, 0xc4, 0x30, 0x14, 0x09, 0x0f, 0xdb, 0xd5, 0xbb, 0x98, - 0x32, 0x59, 0x79, 0x4e, 0xce, 0x6d, 0x95, 0xaa, 0x33, 0x51, 0xf5, 0xbf, 0x5d, 0x35, 0x8e, 0x74, - 0xe1, 0xce, 0x81, 0x9b, 0x5d, 0xc8, 0xe1, 0x90, 0x9e, 0xbf, 0xb8, 0xda, 0x55, 0x47, 0x83, 0x6c, - 0xe1, 0x30, 0xb3, 0xd1, 0x2a, 0x7c, 0x18, 0xe6, 0xf9, 0x68, 0x9b, 0x5a, 0xdf, 0x7f, 0x54, 0x39, - 0x8e, 0x6e, 0x7e, 0xd0, 0xe6, 0xda, 0x0d, 0x6c, 0xfe, 0x0c, 0x9f, 0x5d, 0x2f, 0x57, 0x97, 0x25, - 0x55, 0xb5, 0xa1, 0x8a, 0xa1, 0x3e, 0x96, 0xe6, 0x7a, 0x13, 0x45, 0x6e, 0x8b, 0x8e, 0xed, 0x42, - 0xc6, 0x7d, 0xef, 0x91, 0x83, 0xbb, 0xf5, 0x26, 0xc8, 0x7c, 0xa0, 0x2b, 0x4b, 0xeb, 0x43, 0xf8, - 0x22, 0x7c, 0x4b, 0x01, 0xf8, 0x1d, 0xa0, 0x43, 0xff, 0xd2, 0xd9, 0xce, 0x15, 0x8f, 0xbe, 0xc4, - 0x6b, 0x3e, 0x3e, 0xb6, 0xdb, 0xc0, 0x03, 0x27, 0xd2, 0xe1, 0x4b, 0xaf, 0xaf, 0x3d, 0x5a, 0xac, - 0xb6, 0x83, 0x15, 0x50, 0x13, 0xed, 0x60, 0x05, 0x1f, 0xb7, 0x82, 0xd5, 0x2f, 0xfe, 0x96, 0x9a, - 0xd7, 0x7e, 0x7b, 0xc5, 0x6b, 0x7f, 0x17, 0xb8, 0xa2, 0x65, 0x76, 0x7b, 0xdd, 0x51, 0x38, 0x3c, - 0x90, 0x06, 0xdf, 0xec, 0x4a, 0x93, 0xc4, 0x96, 0xa6, 0xd5, 0xed, 0xc5, 0x81, 0xa2, 0x1b, 0xee, - 0x06, 0x0b, 0x32, 0xc2, 0x94, 0xca, 0xae, 0x95, 0x26, 0xfe, 0xd9, 0x61, 0x3c, 0xae, 0xe0, 0x23, - 0x8f, 0x15, 0x8b, 0xf1, 0x75, 0x55, 0x48, 0xd3, 0xef, 0x49, 0x9e, 0x7d, 0xc3, 0xb5, 0x5a, 0x8c, - 0xea, 0xe5, 0xd4, 0x50, 0xcc, 0xc1, 0x33, 0xd9, 0xce, 0x70, 0xef, 0xa2, 0xf2, 0xb2, 0x07, 0x0e, - 0xc2, 0xda, 0x85, 0x56, 0x56, 0x0f, 0x38, 0x23, 0xab, 0x51, 0x2f, 0xb6, 0x32, 0x54, 0x6b, 0xda, - 0x7a, 0xe1, 0x53, 0xad, 0x66, 0x5a, 0x54, 0x53, 0xbd, 0xf8, 0x61, 0xbb, 0x2e, 0x7d, 0xea, 0x4b, - 0xb1, 0xbc, 0x1f, 0x2a, 0xae, 0x6c, 0xab, 0x33, 0x2c, 0xae, 0xdc, 0xbf, 0x70, 0x9e, 0x75, 0xdb, - 0xb1, 0xc6, 0x5b, 0xb2, 0x7d, 0xe6, 0x7c, 0x8f, 0x6a, 0xbe, 0x74, 0xfe, 0x2b, 0x56, 0x6d, 0x7f, - 0x72, 0x19, 0x1a, 0x6c, 0xe4, 0xfe, 0xe4, 0x6a, 0xc0, 0xc0, 0x86, 0xac, 0xba, 0x08, 0xb8, 0x8d, - 0x8a, 0x4b, 0xa0, 0xed, 0xbb, 0xa6, 0xae, 0xf8, 0x60, 0xfd, 0x3b, 0x2e, 0x8a, 0x70, 0x7b, 0xe3, - 0xa5, 0x71, 0xa7, 0x69, 0x73, 0xa7, 0xf7, 0xbb, 0x3b, 0xa8, 0x5d, 0x39, 0x5b, 0x0d, 0xc8, 0xa7, - 0xb8, 0x68, 0x6e, 0x6c, 0xc2, 0xdf, 0xa3, 0x89, 0xda, 0x55, 0x75, 0x53, 0x33, 0xef, 0xa3, 0x3a, - 0x82, 0xc3, 0x88, 0x70, 0xac, 0x7e, 0xad, 0xf4, 0xe6, 0x8f, 0x72, 0x11, 0xe2, 0x60, 0x78, 0xdc, - 0xcf, 0x47, 0xfb, 0x68, 0x7a, 0x1c, 0x1e, 0x76, 0x3a, 0xbc, 0x84, 0x63, 0xa3, 0xde, 0xc5, 0xf0, - 0x11, 0x18, 0xa6, 0x6d, 0xbd, 0x57, 0xf5, 0x3f, 0x2c, 0xd4, 0xf6, 0xd9, 0x91, 0x99, 0x95, 0x99, - 0x51, 0xa5, 0x63, 0xb8, 0x7b, 0x81, 0x95, 0x09, 0xb1, 0xbe, 0x16, 0x34, 0xb6, 0xc2, 0x86, 0xf0, - 0x2b, 0x58, 0x92, 0x69, 0x71, 0x0a, 0x33, 0x3a, 0x52, 0x8e, 0xe3, 0xf7, 0xc2, 0x65, 0x6c, 0x2c, - 0x7d, 0x11, 0x4b, 0x91, 0x94, 0xf0, 0x9f, 0x45, 0xae, 0xb3, 0xec, 0x56, 0x32, 0x8d, 0x78, 0x40, - 0xa8, 0xbe, 0x73, 0xd0, 0x89, 0xdf, 0x6d, 0xa3, 0x2d, 0x2a, 0x0e, 0x9a, 0x31, 0xb6, 0x44, 0xfc, - 0xee, 0xbc, 0x8f, 0xaa, 0xd6, 0x50, 0xb0, 0x8d, 0x59, 0xb5, 0x28, 0xa4, 0x4a, 0x27, 0xfe, 0xd0, - 0x46, 0x18, 0x67, 0xf7, 0x59, 0x51, 0x25, 0x56, 0xf5, 0x41, 0xf1, 0xaa, 0x1c, 0xbf, 0x93, 0x86, - 0xd1, 0x8f, 0x2d, 0x04, 0x55, 0x13, 0x6d, 0x0d, 0x94, 0xaa, 0x3f, 0x6b, 0xf5, 0x30, 0x3d, 0xd3, - 0xf2, 0x62, 0xcc, 0x8e, 0xd6, 0xbc, 0xa9, 0x9e, 0xb7, 0xa4, 0xfc, 0xc2, 0xb6, 0x12, 0x5e, 0xec, - 0x97, 0x17, 0x22, 0xc9, 0xc3, 0x63, 0xa6, 0x7a, 0xe3, 0x0c, 0xa5, 0xff, 0xe0, 0x94, 0x74, 0x76, - 0xc8, 0x69, 0xb3, 0x1b, 0xda, 0x52, 0x45, 0xf8, 0x7c, 0x20, 0xb5, 0x72, 0x50, 0xf1, 0xa6, 0xb3, - 0xb7, 0xa7, 0x6b, 0xe9, 0xbe, 0x5a, 0x0b, 0xe7, 0x41, 0xfe, 0x83, 0x15, 0x51, 0x94, 0xb1, 0xf4, - 0x13, 0xf2, 0x85, 0x4f, 0xb1, 0x6e, 0x7c, 0xa0, 0xc4, 0xee, 0x7f, 0x5d, 0x76, 0xcc, 0x47, 0xd3, - 0x1a, 0x1f, 0xf7, 0xff, 0x5c, 0xbb, 0x97, 0x0f, 0x61, 0xe6, 0xdd, 0x8b, 0xcb, 0x7e, 0x60, 0x0c, - 0xe7, 0x1b, 0x20, 0xdd, 0xd6, 0x06, 0x0e, 0x5c, 0xed, 0x01, 0x6f, 0xdb, 0x71, 0x5d, 0xa5, 0x79, - 0xde, 0x65, 0xd3, 0xfa, 0x4b, 0x06, 0x9e, 0xb0, 0x25, 0xc0, 0xcd, 0x8a, 0x2e, 0x8d, 0x63, 0xef, - 0x9a, 0x19, 0x33, 0x06, 0xac, 0x0c, 0x50, 0xa7, 0xd1, 0xc2, 0x5f, 0x3e, 0xe0, 0x0e, 0xa1, 0x9b, - 0x67, 0x21, 0xa6, 0xb0, 0xf2, 0xac, 0x1b, 0xa1, 0x73, 0xcb, 0xac, 0x1b, 0xe3, 0x1e, 0x70, 0xe3, - 0x77, 0x00, 0x0b, 0xb0, 0x71, 0x3f, 0x14, 0x91, 0x29, 0x1a, 0xbb, 0xf1, 0x39, 0x28, 0x16, 0x38, - 0x2d, 0x7c, 0xd6, 0x92, 0xb5, 0xc1, 0xe7, 0xc0, 0x4d, 0x35, 0x0f, 0xd5, 0xc2, 0x8f, 0x32, 0x6e, - 0x48, 0xbe, 0x15, 0xe3, 0x77, 0x4d, 0x7b, 0x11, 0x9a, 0x8d, 0x26, 0xdc, 0x8d, 0xe5, 0xa7, 0xf8, - 0xdd, 0x95, 0x9b, 0xe9, 0x6e, 0x59, 0x21, 0x89, 0xf7, 0xb0, 0x9e, 0x1c, 0xd5, 0x93, 0x6e, 0xeb, - 0x49, 0xe4, 0x6c, 0x70, 0xa8, 0x34, 0xf0, 0x08, 0x38, 0xf3, 0x83, 0x8d, 0x1e, 0xc3, 0xcd, 0xb6, - 0xa9, 0x43, 0xfd, 0x10, 0x26, 0xfc, 0x3d, 0x87, 0xec, 0x2e, 0x78, 0x20, 0x3c, 0xb1, 0x90, 0x6b, - 0xd9, 0x35, 0x73, 0x9b, 0xc0, 0x57, 0x3a, 0x9d, 0xa5, 0x86, 0x10, 0x9c, 0x29, 0x15, 0x87, 0xf4, - 0x39, 0xd0, 0xbe, 0xc1, 0xe4, 0x60, 0x9a, 0x65, 0xd5, 0xbd, 0x0f, 0x6b, 0xb1, 0x5f, 0x34, 0x2e, - 0xe4, 0xa2, 0x76, 0x9e, 0xc4, 0x90, 0x8a, 0x07, 0x8a, 0x3e, 0x4a, 0x76, 0xd5, 0xe0, 0xd3, 0x58, - 0x65, 0x44, 0xa5, 0xba, 0x17, 0x1a, 0xd6, 0x62, 0xa4, 0x57, 0x36, 0xda, 0x2f, 0x74, 0xcc, 0x36, - 0x73, 0xf4, 0x4c, 0xd1, 0x60, 0x8b, 0x12, 0x12, 0xf8, 0x63, 0xc4, 0xc2, 0x14, 0x5d, 0x61, 0x18, - 0xa4, 0x2b, 0x66, 0xda, 0x4a, 0x9e, 0xb5, 0x97, 0x5c, 0xe3, 0xdd, 0x16, 0x06, 0x19, 0x54, 0xd3, - 0x29, 0x68, 0xa9, 0x6b, 0x9e, 0x62, 0x90, 0xc3, 0x51, 0xc6, 0xb5, 0xcb, 0x2a, 0xd5, 0x9e, 0xd5, - 0xab, 0x55, 0xb3, 0xc9, 0x9a, 0x07, 0xbc, 0x66, 0xf5, 0x93, 0xa8, 0xfc, 0x0c, 0xe3, 0x1b, 0x8a, - 0xe8, 0x34, 0x3c, 0xb8, 0x26, 0x1e, 0x29, 0x95, 0xc6, 0x74, 0x2d, 0x3c, 0xcb, 0xde, 0x62, 0xc3, - 0xd1, 0xa4, 0x10, 0xb7, 0xb7, 0xf9, 0x47, 0x8b, 0xe5, 0x86, 0x5d, 0xf1, 0xa7, 0x40, 0xb7, 0xc7, - 0xa8, 0x36, 0xb0, 0x42, 0xff, 0x8b, 0x85, 0x89, 0xf2, 0x1b, 0x61, 0x31, 0x67, 0x26, 0x14, 0xe2, - 0x18, 0xcf, 0x2d, 0xa0, 0x08, 0x56, 0x40, 0x10, 0xa4, 0xf0, 0xef, 0x76, 0x48, 0x3e, 0x70, 0xbb, - 0x5a, 0xb8, 0x88, 0xc2, 0xf3, 0xa9, 0x30, 0xd4, 0x3f, 0x3a, 0x73, 0xac, 0xd1, 0x22, 0x7a, 0x64, - 0xdd, 0x95, 0x9a, 0xed, 0xe4, 0x79, 0x25, 0x9f, 0x95, 0xc3, 0x00, 0x03, 0xd6, 0xa1, 0x44, 0x6f, - 0x86, 0x6e, 0x4f, 0x57, 0x14, 0x3e, 0x75, 0x65, 0x9d, 0x63, 0x15, 0xbc, 0x73, 0x90, 0x98, 0x57, - 0x67, 0x96, 0x51, 0xd0, 0x1e, 0x1e, 0xe9, 0xc7, 0xa9, 0x99, 0xfd, 0xd1, 0x70, 0x05, 0xf5, 0xa3, - 0x96, 0x4c, 0xae, 0x67, 0x76, 0x13, 0x48, 0xf2, 0xb9, 0xfb, 0x0d, 0xe9, 0x6a, 0x31, 0xf1, 0xac, - 0x9b, 0x68, 0xf3, 0x9d, 0xd9, 0xfd, 0x66, 0xeb, 0x28, 0x51, 0xf6, 0x6f, 0xe8, 0xcc, 0x5e, 0x16, - 0xbd, 0xae, 0x14, 0x1d, 0x6c, 0x2d, 0xfa, 0x5a, 0x2d, 0x3a, 0xab, 0x14, 0x3d, 0xa9, 0x8d, 0x8d, - 0x47, 0xb4, 0xac, 0x8f, 0x6d, 0xc5, 0xee, 0x2f, 0xc9, 0x96, 0x60, 0x84, 0xf5, 0xa4, 0x9b, 0x19, - 0xb7, 0x2c, 0x90, 0x3e, 0x6f, 0x33, 0x0d, 0x96, 0x46, 0x19, 0x61, 0x54, 0x76, 0xe4, 0xa2, 0x0d, - 0xe5, 0xa5, 0xc8, 0xf9, 0xdc, 0x6a, 0x82, 0x49, 0xa8, 0x78, 0x5e, 0x00, 0x24, 0x6b, 0xc9, 0x10, - 0x2e, 0xdb, 0xf5, 0xfa, 0xa5, 0x45, 0xd8, 0x89, 0xa5, 0x48, 0xc7, 0xa0, 0x10, 0x5d, 0xde, 0x35, - 0xca, 0x20, 0xf7, 0xad, 0xf1, 0xb9, 0x65, 0xda, 0xfd, 0x13, 0x80, 0x51, 0x0c, 0x25, 0xd4, 0xbd, - 0x61, 0x0f, 0x6f, 0x28, 0xd4, 0x0e, 0x1a, 0x00, 0xd1, 0x34, 0x95, 0xcd, 0x15, 0x49, 0xad, 0xc1, - 0x13, 0xd4, 0x61, 0x8e, 0xd4, 0xb9, 0x52, 0x62, 0xa7, 0x28, 0xd3, 0xfa, 0xdc, 0xb2, 0x61, 0xbe, - 0x88, 0x02, 0xa9, 0xc2, 0xa6, 0xf9, 0x0d, 0xba, 0x54, 0x2d, 0xb3, 0x3a, 0x36, 0x4c, 0x6c, 0x19, - 0xd7, 0xa0, 0x9e, 0x7d, 0xb9, 0xf4, 0x3c, 0x0c, 0xce, 0x99, 0x73, 0xf3, 0x49, 0xb5, 0x71, 0xab, - 0xd4, 0xb6, 0xe5, 0x9d, 0x71, 0x14, 0xc0, 0x1f, 0x54, 0x06, 0xa8, 0x82, 0xfd, 0x16, 0x20, 0xe7, - 0x63, 0xb4, 0xb7, 0x02, 0xb3, 0xc8, 0x13, 0x6e, 0x83, 0x5a, 0x31, 0x57, 0xd5, 0xf1, 0x08, 0x67, - 0x19, 0x0c, 0xfd, 0x64, 0x64, 0xf8, 0x13, 0xe6, 0xd6, 0xb4, 0x65, 0xbb, 0x16, 0x89, 0xed, 0xb2, - 0xdd, 0xea, 0x79, 0xd1, 0xa7, 0xa0, 0x28, 0x7a, 0x08, 0x31, 0xd7, 0xdd, 0x8a, 0x69, 0x0f, 0x0f, - 0x2b, 0x7d, 0xc4, 0x38, 0x5c, 0x21, 0x0b, 0x60, 0xd1, 0xd3, 0x5b, 0xd3, 0x36, 0xe1, 0x1f, 0x79, - 0xfb, 0xd8, 0x5a, 0x49, 0x15, 0x91, 0xf0, 0x4d, 0x63, 0x0f, 0x28, 0x70, 0x8a, 0xbe, 0x46, 0x3b, - 0xf1, 0xba, 0xf4, 0xc6, 0x52, 0xc5, 0x4d, 0x52, 0xdc, 0x09, 0x29, 0xc3, 0x4f, 0x9f, 0x42, 0xc0, - 0x41, 0x21, 0x20, 0x93, 0x10, 0xb0, 0x82, 0x5a, 0xff, 0x95, 0xfd, 0x09, 0xff, 0xbf, 0xca, 0x73, - 0x9c, 0x0c, 0x4c, 0x9a, 0xe8, 0x05, 0xe1, 0xeb, 0xb6, 0xb2, 0x50, 0x70, 0x38, 0xe0, 0x05, 0xc9, - 0xde, 0xb8, 0x52, 0x74, 0x5b, 0x69, 0x14, 0x9b, 0xb5, 0x1e, 0x2f, 0xe9, 0x5f, 0xc2, 0xb8, 0xa7, - 0xfc, 0x5c, 0x5a, 0xcd, 0xd5, 0x43, 0x09, 0x83, 0x6a, 0xfd, 0xed, 0x67, 0x00, 0x6e, 0x61, 0xbd, - 0x81, 0xef, 0x9d, 0x22, 0x82, 0xa2, 0x08, 0x9b, 0x88, 0x21, 0x1e, 0x5f, 0x15, 0xc1, 0x14, 0x7b, - 0x68, 0xda, 0xd7, 0xbb, 0xf3, 0x6f, 0x7c, 0xd8, 0x58, 0x82, 0x45, 0x4f, 0xa0, 0x3d, 0x2d, 0x4c, - 0x94, 0xd4, 0x42, 0xeb, 0x74, 0x56, 0xf3, 0x23, 0xb7, 0xff, 0xc2, 0x1a, 0x9f, 0x50, 0xac, 0x20, - 0x6c, 0xdd, 0xb2, 0x57, 0xf3, 0xf1, 0x40, 0xbe, 0x9e, 0x38, 0xb8, 0xe3, 0x4f, 0x4f, 0x5d, 0x77, - 0x35, 0xa7, 0x94, 0x23, 0xf7, 0x04, 0x53, 0x9c, 0x17, 0x4a, 0x0a, 0x54, 0xd0, 0x88, 0x1f, 0x31, - 0x04, 0x9a, 0x44, 0x66, 0xb4, 0xda, 0xee, 0x74, 0x95, 0x62, 0xbc, 0xc2, 0xd5, 0x3c, 0xc7, 0xa8, - 0x9e, 0xce, 0x77, 0xb6, 0x71, 0xe6, 0x7c, 0x87, 0x46, 0xd1, 0x96, 0xfd, 0xb2, 0x2f, 0x42, 0xb7, - 0x01, 0x0a, 0x24, 0xc7, 0x3b, 0xa5, 0x05, 0x60, 0xb8, 0xfc, 0x8d, 0x58, 0x55, 0xee, 0xeb, 0x1f, - 0xbf, 0xb7, 0x6f, 0x77, 0xa2, 0xd2, 0xc8, 0x6f, 0x5b, 0x11, 0x3d, 0x48, 0xeb, 0x01, 0xf7, 0x6b, - 0x60, 0x33, 0x95, 0xdc, 0x7f, 0x13, 0x85, 0xc0, 0xc4, 0xac, 0x8d, 0xdf, 0xd8, 0x2c, 0x8a, 0x32, - 0x93, 0xcc, 0x13, 0x3a, 0xbc, 0x1b, 0xb0, 0x6b, 0xab, 0xf1, 0x12, 0x57, 0x40, 0xd3, 0xba, 0x66, - 0x4f, 0xdc, 0x49, 0xca, 0x1e, 0x5f, 0x6a, 0x5d, 0x4e, 0xd0, 0xd1, 0xdd, 0x16, 0xa4, 0x24, 0x5c, - 0xcb, 0x8d, 0xe4, 0x78, 0x2e, 0xad, 0x2f, 0xee, 0x2c, 0x6f, 0xbf, 0xec, 0xeb, 0x25, 0x76, 0x76, - 0x24, 0xbb, 0x62, 0xd7, 0x2a, 0x5a, 0x2e, 0x2b, 0x15, 0xd1, 0x9c, 0x16, 0x82, 0x75, 0x19, 0x18, - 0x88, 0x5f, 0xd6, 0x3c, 0xf2, 0x4b, 0x07, 0x87, 0xcb, 0xca, 0xa5, 0x4e, 0x12, 0x5d, 0xac, 0x00, - 0x63, 0xa3, 0x5c, 0xe5, 0x60, 0x08, 0x27, 0x26, 0xae, 0x72, 0x58, 0xf5, 0x2a, 0x87, 0xcb, 0xd9, - 0xdb, 0x2f, 0x72, 0xea, 0xe6, 0x42, 0x35, 0x6f, 0x51, 0x7c, 0x5a, 0x76, 0x86, 0x84, 0x84, 0x5a, - 0xee, 0xf9, 0x74, 0x32, 0x0b, 0xcf, 0x26, 0xe6, 0x6a, 0x61, 0x20, 0x47, 0xd2, 0x16, 0x93, 0x72, - 0x1c, 0x1e, 0x92, 0x7b, 0x76, 0xd7, 0x95, 0xba, 0xa3, 0xe4, 0xac, 0x5d, 0x65, 0x14, 0xd5, 0x2e, - 0x00, 0x55, 0x11, 0xab, 0xe1, 0x79, 0xb4, 0x6f, 0x8f, 0x39, 0xfa, 0x60, 0xd7, 0xc6, 0xe0, 0x68, - 0x71, 0x19, 0xb7, 0xc4, 0x1b, 0xc0, 0x2e, 0x57, 0x43, 0x0e, 0x3c, 0xc6, 0x43, 0xb5, 0x7e, 0x1b, - 0x3a, 0x36, 0x54, 0x7b, 0x99, 0x5b, 0x75, 0x72, 0xd6, 0xd2, 0xc3, 0xa0, 0x69, 0x9d, 0x51, 0x5d, - 0xed, 0x70, 0x73, 0x4f, 0xa8, 0xfe, 0x7e, 0x82, 0x9c, 0x98, 0x8b, 0xa1, 0xa5, 0xb8, 0xed, 0x5b, - 0xd8, 0x60, 0xed, 0x19, 0xe6, 0x85, 0x2b, 0x95, 0x50, 0x77, 0xa5, 0xf2, 0x27, 0x6c, 0x33, 0xbf, - 0xd2, 0x28, 0x53, 0x9b, 0xf2, 0x7a, 0xe4, 0x2a, 0x75, 0xc2, 0x42, 0x58, 0x2c, 0x9b, 0x9d, 0x87, - 0xdd, 0xf5, 0xa4, 0x36, 0x17, 0x47, 0x7d, 0x98, 0x8d, 0x61, 0xf6, 0xd7, 0x45, 0xa5, 0x51, 0xce, - 0x73, 0x72, 0x5e, 0xa7, 0x38, 0x11, 0x21, 0x0c, 0x0f, 0x34, 0xe6, 0xef, 0x71, 0xcc, 0x92, 0x37, - 0xc0, 0x09, 0xa3, 0x1b, 0x2f, 0xe1, 0xe4, 0x43, 0x9a, 0x2c, 0xb6, 0x3b, 0x70, 0xa8, 0x79, 0xcb, - 0x53, 0xbc, 0x99, 0x14, 0x37, 0xb0, 0x52, 0xb8, 0xd3, 0x2f, 0xae, 0x62, 0x85, 0x3b, 0xca, 0xc2, - 0x5e, 0x5c, 0x6f, 0x4e, 0x7f, 0xab, 0x3b, 0x93, 0x53, 0xbd, 0xc7, 0xf9, 0xa8, 0xbf, 0x7b, 0x2e, - 0xe5, 0x47, 0x23, 0x5f, 0xfa, 0x4f, 0x4a, 0xdd, 0x10, 0x2d, 0xbd, 0xd2, 0x46, 0x4f, 0x71, 0xe4, - 0xb4, 0x4a, 0xc8, 0x51, 0x3e, 0xb2, 0xfb, 0x4c, 0x1f, 0x7e, 0x21, 0x9b, 0xc9, 0x50, 0x30, 0x34, - 0x49, 0xab, 0xa6, 0xf8, 0xe6, 0x30, 0x6d, 0xf4, 0xcc, 0xa9, 0x5c, 0x1f, 0x6a, 0x9e, 0x02, 0x95, - 0xc9, 0xfe, 0x92, 0x69, 0x15, 0xfe, 0x5a, 0x04, 0x5d, 0x8f, 0x3a, 0xe9, 0xc2, 0xf1, 0x20, 0x8a, - 0x16, 0x96, 0xd1, 0x7c, 0xa3, 0x71, 0xf8, 0x32, 0x6e, 0x87, 0xf0, 0xc3, 0x83, 0x46, 0xb6, 0xda, - 0x75, 0xa3, 0xf2, 0xd2, 0xc8, 0xd7, 0xb2, 0x6b, 0x13, 0xef, 0x3c, 0x2a, 0x76, 0xf2, 0x65, 0xa1, - 0x9d, 0x17, 0xf0, 0xe4, 0x1d, 0x5e, 0xa9, 0x43, 0x71, 0x25, 0xa0, 0xd6, 0x52, 0x31, 0x76, 0x1d, - 0xca, 0x04, 0xfe, 0x6a, 0xb3, 0x31, 0x12, 0x7a, 0x02, 0x11, 0xb0, 0x63, 0x78, 0x69, 0x95, 0x79, - 0x86, 0xe8, 0x53, 0xa3, 0xee, 0xdf, 0x42, 0x69, 0xed, 0xe9, 0x29, 0x3c, 0x70, 0x35, 0x8b, 0xca, - 0x89, 0xea, 0xd0, 0x63, 0xa8, 0xb1, 0x29, 0x28, 0xa2, 0x6d, 0x9f, 0x97, 0xe2, 0x34, 0x6a, 0x51, - 0x04, 0xd5, 0x33, 0xb9, 0x5c, 0x0f, 0x24, 0x94, 0x76, 0xf1, 0x32, 0xd4, 0x5d, 0x68, 0x8d, 0x5a, - 0x86, 0xa2, 0x08, 0x4d, 0xdd, 0xd4, 0x76, 0x5c, 0x37, 0xad, 0x4b, 0x08, 0x9b, 0xdc, 0x45, 0xf0, - 0xd2, 0x15, 0xe1, 0x2f, 0x9e, 0xaf, 0x36, 0x57, 0xc9, 0x08, 0xad, 0x5c, 0xf5, 0xf1, 0x11, 0x12, - 0xdc, 0x50, 0x78, 0xd2, 0x24, 0x6d, 0x56, 0x6a, 0x55, 0x2e, 0x7c, 0x66, 0xc1, 0x26, 0xe9, 0x58, - 0x3b, 0xed, 0xfc, 0x76, 0x64, 0x53, 0x2f, 0x4e, 0x78, 0xd6, 0x9c, 0x7b, 0x31, 0xfc, 0x9f, 0x37, - 0xf5, 0x1b, 0xb5, 0x2e, 0xba, 0x0b, 0xf6, 0x00, 0x37, 0x24, 0xa6, 0x65, 0x7f, 0x70, 0x4f, 0xc9, - 0xc7, 0xe1, 0x9d, 0x88, 0xa8, 0xea, 0x3a, 0xf6, 0xbd, 0xc3, 0xed, 0xd9, 0xb9, 0xa1, 0xd9, 0x25, - 0x45, 0xab, 0xe0, 0x43, 0x56, 0x68, 0x9a, 0x4d, 0xc8, 0xcd, 0xf5, 0x4b, 0xa7, 0x0d, 0x5c, 0x4d, - 0x6b, 0xf1, 0x91, 0x42, 0xd8, 0xa6, 0x93, 0x6a, 0x02, 0x6c, 0xb4, 0xa1, 0xe2, 0x04, 0x6e, 0xe5, - 0xa5, 0xef, 0x92, 0x88, 0x36, 0x24, 0xd6, 0x52, 0x86, 0x59, 0xae, 0x3b, 0xa9, 0xc4, 0x53, 0x9a, - 0xbb, 0x8f, 0x29, 0xc3, 0xb8, 0x40, 0xd9, 0x42, 0x9c, 0x0b, 0x34, 0x88, 0x78, 0xe8, 0xab, 0xd4, - 0xc4, 0xfc, 0xa6, 0x08, 0x7b, 0x48, 0xd1, 0x67, 0x6b, 0x3e, 0x9d, 0x8a, 0x4b, 0x3e, 0x8a, 0x97, - 0xa3, 0x79, 0x5e, 0x92, 0xd8, 0xa3, 0xc8, 0x02, 0x38, 0x42, 0xcc, 0x5a, 0xda, 0x29, 0x94, 0xf0, - 0xac, 0xa7, 0x27, 0x75, 0x18, 0x59, 0xe5, 0x3d, 0xc4, 0xa8, 0xd8, 0x30, 0x99, 0x72, 0xaa, 0xa0, - 0x36, 0xf4, 0x72, 0xf5, 0xcf, 0x62, 0x62, 0xb7, 0x06, 0xed, 0x9d, 0xf3, 0xd3, 0x14, 0x30, 0x14, - 0x5f, 0x98, 0x2b, 0x61, 0xf8, 0xf7, 0x31, 0x8a, 0x77, 0x04, 0xce, 0xed, 0xc8, 0xe5, 0x72, 0x2c, - 0xcd, 0x19, 0x27, 0xdd, 0x8e, 0xf2, 0x29, 0xe1, 0x39, 0x0e, 0x0f, 0x2b, 0x53, 0x53, 0xeb, 0x69, - 0xe8, 0x66, 0xc7, 0xf7, 0x8e, 0x0c, 0x8b, 0x4a, 0x67, 0x6c, 0x88, 0x61, 0x50, 0x8f, 0x3a, 0xe9, - 0xf7, 0x61, 0xef, 0xae, 0x8c, 0x08, 0x34, 0x28, 0x42, 0x92, 0xf1, 0xde, 0x8e, 0x1d, 0x38, 0xcd, - 0xcf, 0xc9, 0xef, 0x11, 0x4f, 0x38, 0x3f, 0x81, 0x04, 0x72, 0x84, 0x14, 0x8c, 0xbb, 0xfd, 0xc1, - 0xe1, 0xe1, 0xd7, 0x0e, 0x1e, 0xb6, 0x2d, 0x9f, 0x3e, 0xa8, 0x7a, 0x67, 0x7c, 0xe0, 0x63, 0x14, - 0x95, 0x07, 0x6e, 0xff, 0x38, 0xa8, 0x06, 0x0a, 0x16, 0xf1, 0x83, 0xdb, 0x63, 0x0c, 0x2f, 0x31, - 0xe2, 0xcd, 0xbe, 0x33, 0xdd, 0x87, 0x8a, 0xc4, 0xb6, 0x51, 0x26, 0x9c, 0x1b, 0x38, 0x3d, 0xde, - 0xb9, 0x35, 0x73, 0xfb, 0x2f, 0xb4, 0xdb, 0x2f, 0x88, 0x3e, 0x69, 0xbe, 0xdf, 0x60, 0xae, 0x3f, - 0x6a, 0xe3, 0x2e, 0x80, 0xee, 0x36, 0xe5, 0x8a, 0xfe, 0xcc, 0x50, 0x23, 0x77, 0x94, 0x02, 0x33, - 0x8f, 0x63, 0xa4, 0xa8, 0x43, 0x47, 0x66, 0x7c, 0x8f, 0x96, 0xb3, 0x22, 0x6d, 0xb6, 0x6a, 0x34, - 0x0d, 0x8a, 0xb2, 0x4a, 0x25, 0xa2, 0x18, 0x5a, 0x75, 0xa1, 0x10, 0xed, 0xd8, 0x3d, 0x2d, 0xeb, - 0xc8, 0xe2, 0xb2, 0x5e, 0x2d, 0x20, 0x77, 0xdd, 0x5c, 0x92, 0xa7, 0x33, 0x8a, 0xce, 0x4c, 0xb1, - 0xe5, 0x28, 0xe1, 0x95, 0x2b, 0x20, 0xf3, 0x55, 0x4b, 0x8c, 0x2e, 0x8c, 0xf6, 0x6d, 0x8b, 0x2c, - 0x96, 0x78, 0x70, 0x8b, 0xf7, 0xbb, 0xf3, 0x3e, 0xc5, 0x88, 0x3d, 0x90, 0x41, 0xab, 0x0f, 0x48, - 0x3c, 0x21, 0x52, 0x71, 0x36, 0xf9, 0xf3, 0xd3, 0xd3, 0xdd, 0xd8, 0x55, 0x12, 0xf9, 0x0b, 0x6e, - 0x5b, 0x19, 0xc0, 0x9a, 0xe2, 0x73, 0x89, 0xfa, 0x26, 0xa2, 0x99, 0x83, 0xfe, 0x50, 0xb4, 0x84, - 0xbe, 0xa6, 0x8a, 0x3e, 0x97, 0xcd, 0xd7, 0xa3, 0xb7, 0xb7, 0x7a, 0x7b, 0xc2, 0xa0, 0xe5, 0x8a, - 0xa5, 0x15, 0xaf, 0x62, 0x97, 0xdb, 0xa6, 0xa8, 0x64, 0xa4, 0x57, 0xb4, 0x16, 0x6e, 0x11, 0x5f, - 0xbb, 0x0c, 0x3d, 0x37, 0x5f, 0x43, 0xbe, 0x89, 0xe9, 0x20, 0x25, 0xbe, 0xc9, 0x22, 0xf3, 0x6b, - 0x17, 0xb8, 0xd8, 0x1f, 0x5c, 0xc8, 0x2f, 0x7b, 0x88, 0xfc, 0x3a, 0x54, 0x7d, 0x8a, 0x7f, 0xc8, - 0x53, 0x04, 0x40, 0xb9, 0xb2, 0xba, 0x45, 0x08, 0x3e, 0xe5, 0x84, 0x38, 0x3c, 0x34, 0x23, 0x4a, - 0x44, 0x51, 0x15, 0xf0, 0x08, 0xd1, 0x12, 0xd3, 0x0e, 0x74, 0x7f, 0xba, 0xea, 0xb5, 0xf4, 0x9a, - 0x01, 0x4a, 0xfe, 0x91, 0xb1, 0x18, 0x48, 0xae, 0x6e, 0xb7, 0xcb, 0xa9, 0xae, 0x03, 0x49, 0xea, - 0x16, 0x4c, 0xf2, 0x88, 0x1f, 0x75, 0x78, 0x29, 0x24, 0x5d, 0x6c, 0x43, 0x3e, 0xa5, 0x07, 0x87, - 0x87, 0xc5, 0x4b, 0x68, 0x95, 0x51, 0xc7, 0x78, 0x94, 0xe1, 0xd0, 0x2a, 0x3f, 0xc2, 0x29, 0x63, - 0x4d, 0xe8, 0xb0, 0x79, 0x7a, 0xd2, 0x39, 0x0b, 0x66, 0x3f, 0x42, 0xea, 0xf0, 0x11, 0x45, 0x3f, - 0x4a, 0xb7, 0x20, 0xcd, 0xa6, 0x52, 0xd6, 0xb0, 0x31, 0x3f, 0x7e, 0xcb, 0x0b, 0xd9, 0x43, 0x6d, - 0x3c, 0x39, 0xc7, 0x10, 0xad, 0x38, 0x28, 0x34, 0x6d, 0xd8, 0x55, 0x02, 0x7b, 0xd4, 0xa3, 0xc5, - 0x03, 0xb9, 0x05, 0xe5, 0xb9, 0x21, 0xa5, 0x8c, 0x97, 0x5e, 0xcf, 0xb5, 0x8e, 0xf0, 0x8a, 0x3c, - 0xba, 0x83, 0xca, 0x10, 0x5f, 0xb4, 0x67, 0x54, 0x43, 0xd5, 0x6f, 0xcf, 0x49, 0x55, 0x46, 0x1b, - 0xc8, 0x87, 0x67, 0xca, 0x8e, 0x7c, 0x9b, 0x78, 0x57, 0xb6, 0x32, 0xea, 0xbd, 0xcc, 0xf7, 0xbf, - 0xce, 0x7b, 0x80, 0xe5, 0xfd, 0x38, 0x1b, 0x1b, 0xe7, 0x3d, 0x74, 0xe1, 0x83, 0x7f, 0x57, 0xd9, - 0x3a, 0x18, 0x1b, 0xff, 0x0f, 0x49, 0xe3, 0x72, 0x63, 0xcd, 0x85, 0x01, 0x00 + 0xd3, 0x39, 0xdc, 0x1d, 0x57, 0xfd, 0xff, 0x7a, 0xfb, 0xd6, 0xee, 0xb6, 0x6d, 0x65, 0xd1, 0xef, + 0xe7, 0x57, 0xd0, 0x6c, 0xeb, 0x88, 0x35, 0x2d, 0x51, 0xb2, 0x9d, 0x26, 0x92, 0x29, 0xad, 0x24, + 0x4d, 0x77, 0x73, 0x6f, 0x9a, 0x7a, 0xd7, 0xe9, 0xd9, 0xbb, 0x2b, 0xc7, 0xeb, 0x88, 0x92, 0x20, + 0x8b, 0xdb, 0x14, 0xc9, 0x90, 0x94, 0x1f, 0xd7, 0xe6, 0x7f, 0xbf, 0x33, 0x03, 0x80, 0x04, 0xf8, + 0x90, 0x94, 0xb4, 0x7b, 0x77, 0x35, 0x32, 0x09, 0xe2, 0x8d, 0xc1, 0x60, 0x66, 0x30, 0x0f, 0x7e, + 0xd8, 0x60, 0x5e, 0x9c, 0x5f, 0x71, 0xeb, 0x36, 0x5a, 0x28, 0x91, 0x30, 0x5e, 0x3f, 0xbc, 0x5b, + 0x74, 0xd0, 0xd4, 0xe4, 0xce, 0xb4, 0x44, 0x37, 0xc5, 0xed, 0x29, 0x9a, 0xb6, 0xb1, 0xfb, 0x89, + 0x29, 0x55, 0xcf, 0x39, 0x15, 0x5a, 0x2f, 0x2b, 0x00, 0xaa, 0x5e, 0x9a, 0x7f, 0xd8, 0x5d, 0x01, + 0x80, 0xf8, 0x5d, 0xe2, 0xc5, 0x0d, 0x35, 0xc0, 0x97, 0xdd, 0xc5, 0x3f, 0xcf, 0xd3, 0xe3, 0xa6, + 0xce, 0xd3, 0x96, 0xa9, 0x14, 0x1f, 0x95, 0x32, 0xd0, 0x62, 0x52, 0xf8, 0x4e, 0x42, 0xef, 0x64, + 0x75, 0xae, 0xce, 0x84, 0x83, 0x62, 0x76, 0x4c, 0x39, 0x4c, 0x74, 0x6c, 0xe1, 0x8c, 0x82, 0xf3, + 0x42, 0x6c, 0x16, 0x1c, 0x1d, 0x59, 0xe9, 0xa7, 0xe0, 0xaa, 0xd2, 0x72, 0x58, 0x6d, 0xb3, 0x53, + 0xab, 0x1a, 0xea, 0x5d, 0x2d, 0xe0, 0x60, 0xd9, 0x51, 0xd2, 0x96, 0xcb, 0x99, 0xcd, 0x80, 0xdf, + 0x85, 0xaf, 0xfd, 0xd3, 0xf8, 0xde, 0xe0, 0x3f, 0x8e, 0x78, 0x22, 0x97, 0xc3, 0xf0, 0x3c, 0x18, + 0xc0, 0xcf, 0xa9, 0x78, 0x40, 0x67, 0x38, 0xa2, 0xe8, 0x4c, 0x14, 0x7d, 0x09, 0x9f, 0x1c, 0xe3, + 0x07, 0xfc, 0x95, 0x45, 0x1c, 0xca, 0xef, 0xa8, 0x99, 0xa1, 0x57, 0x76, 0xb5, 0x17, 0xca, 0xe7, + 0x75, 0x46, 0x9f, 0x1d, 0x6a, 0xf6, 0x4c, 0x6b, 0x27, 0x3b, 0x9e, 0x99, 0x76, 0x09, 0x94, 0x84, + 0xf2, 0x70, 0xf2, 0x20, 0x87, 0xff, 0xff, 0x30, 0xfe, 0x30, 0xc5, 0x56, 0xbc, 0x84, 0xc1, 0x7b, + 0xd7, 0xb4, 0x13, 0xde, 0x65, 0x6c, 0xdd, 0x31, 0xef, 0xe0, 0x68, 0xf8, 0xdd, 0x07, 0xc8, 0x37, + 0xed, 0xff, 0x73, 0xf9, 0xeb, 0x87, 0x2e, 0x37, 0x0e, 0xf1, 0x97, 0x0f, 0x1d, 0xa8, 0x4b, 0x75, + 0x58, 0x97, 0x5d, 0x07, 0x3f, 0x33, 0x8c, 0xed, 0x55, 0x01, 0x66, 0x84, 0x51, 0xf7, 0xa0, 0x21, + 0xd1, 0x2e, 0xf7, 0x94, 0x56, 0x0b, 0xdf, 0x5e, 0xbc, 0x9e, 0x72, 0x5b, 0xb9, 0x6d, 0xfb, 0x6d, + 0xc2, 0xf1, 0xf9, 0x50, 0x7c, 0x6f, 0xab, 0xf5, 0x3d, 0x01, 0x91, 0xda, 0x3d, 0x0e, 0x56, 0x4a, + 0xd7, 0x04, 0x9c, 0x35, 0x55, 0x20, 0xf6, 0x3c, 0x50, 0x4e, 0x6c, 0xd2, 0xd1, 0xf6, 0xb0, 0xf9, + 0x0d, 0x63, 0xea, 0x12, 0xcc, 0x8f, 0xd1, 0x6b, 0x27, 0x5d, 0x66, 0xab, 0x89, 0x03, 0x4c, 0x5c, + 0x2c, 0x16, 0x5a, 0xe2, 0x09, 0x26, 0xce, 0x66, 0x33, 0x2d, 0xf1, 0x14, 0x13, 0x3d, 0xcf, 0xd3, + 0x12, 0xcf, 0x30, 0xf1, 0xe5, 0xcb, 0x97, 0x5a, 0xe2, 0xf3, 0xa6, 0xc4, 0x17, 0x98, 0xf8, 0xe2, + 0xc5, 0x0b, 0x2d, 0x71, 0x86, 0x89, 0xa7, 0xa7, 0xa7, 0x5a, 0xe2, 0x1c, 0x13, 0x4f, 0x4e, 0x4e, + 0xb4, 0x44, 0x64, 0x88, 0xbe, 0xe9, 0xf7, 0xfb, 0x5a, 0xe2, 0x02, 0x13, 0x07, 0x83, 0x81, 0x96, + 0x98, 0x60, 0xe2, 0xfc, 0x54, 0x4f, 0x8c, 0x4c, 0x71, 0xbd, 0x3f, 0x70, 0x4e, 0x6d, 0xa3, 0xfc, + 0x71, 0xba, 0x2f, 0x2d, 0x2d, 0x63, 0x3a, 0x13, 0xb3, 0x74, 0x52, 0x49, 0x5e, 0x89, 0xf4, 0xe7, + 0x5a, 0x7a, 0x36, 0x6b, 0xa9, 0x18, 0x50, 0x45, 0x87, 0x60, 0xdb, 0xb2, 0x2a, 0x05, 0x3c, 0x59, + 0xa2, 0xff, 0x83, 0x63, 0x1b, 0xe5, 0x4f, 0x7b, 0x89, 0xd5, 0x5e, 0x6d, 0xd4, 0xf1, 0x9b, 0xbf, + 0xbe, 0x2e, 0xd1, 0x1b, 0x17, 0x0e, 0xb9, 0x40, 0x9a, 0xa2, 0xee, 0x4e, 0xc7, 0xe9, 0xbe, 0x80, + 0x42, 0xc3, 0x2a, 0xcc, 0x54, 0x67, 0x98, 0x60, 0x06, 0x75, 0x28, 0x6a, 0x30, 0x53, 0x9d, 0xf6, + 0x93, 0xa6, 0x55, 0x3b, 0x6d, 0x5a, 0x5f, 0x82, 0x99, 0xb3, 0xb3, 0xb3, 0x3a, 0xcc, 0x3c, 0x7f, + 0xfe, 0x7c, 0x4f, 0x98, 0xa9, 0x02, 0x27, 0xc1, 0x0c, 0x3a, 0xfc, 0xae, 0xc1, 0x4c, 0x75, 0x17, + 0x2c, 0x9a, 0x00, 0x9e, 0x60, 0xe6, 0xc5, 0x49, 0xbf, 0x19, 0x66, 0x4e, 0x60, 0xae, 0xe5, 0xbf, + 0x16, 0x80, 0x81, 0x29, 0x6a, 0x04, 0x18, 0x48, 0x3f, 0x6b, 0x01, 0x18, 0xb5, 0xd6, 0x7d, 0xa0, + 0xc5, 0x19, 0xa0, 0x37, 0x58, 0xf9, 0xb3, 0x07, 0xb4, 0x9c, 0xf5, 0x6d, 0x43, 0xfe, 0xfb, 0x2a, + 0x50, 0xd9, 0x84, 0xc8, 0xa5, 0x29, 0xd8, 0x06, 0xbd, 0x4d, 0xbe, 0xbe, 0x46, 0x6c, 0x03, 0x74, + 0x30, 0x90, 0x07, 0xf5, 0x7a, 0x66, 0xd7, 0x26, 0x9a, 0xb1, 0x2f, 0xaa, 0x7e, 0x3a, 0xa1, 0x7e, + 0x93, 0x2e, 0xc5, 0xc2, 0x6e, 0x9a, 0xcc, 0x5d, 0x66, 0x9b, 0x80, 0x30, 0x99, 0x25, 0x0f, 0xd5, + 0xd4, 0x95, 0x74, 0x13, 0xba, 0xdc, 0x04, 0x7e, 0xa3, 0xdf, 0xb7, 0x07, 0xa7, 0xf6, 0xa9, 0x4d, + 0x21, 0x6d, 0xd3, 0x61, 0xaf, 0xe7, 0xf9, 0xc9, 0x3c, 0x8a, 0xa2, 0x1b, 0x9f, 0x75, 0xaf, 0x7d, + 0x60, 0xd7, 0x67, 0x5d, 0x3f, 0xea, 0xdd, 0xaf, 0xbd, 0xb4, 0x1b, 0x87, 0xd7, 0xa8, 0xab, 0xe3, + 0xd8, 0x03, 0xbb, 0xff, 0x83, 0xdd, 0x2f, 0x8b, 0xf8, 0x6b, 0x38, 0x30, 0x84, 0x8d, 0xfa, 0x1c, + 0x38, 0x82, 0x04, 0xd9, 0xfd, 0x75, 0xef, 0xf4, 0x65, 0x1f, 0xff, 0xf5, 0x07, 0x27, 0xdd, 0x7f, + 0xc5, 0x54, 0x74, 0xe0, 0x0c, 0x06, 0xf6, 0x09, 0x96, 0x1e, 0xec, 0x68, 0x90, 0x01, 0x51, 0xc7, + 0x12, 0xd9, 0x24, 0x94, 0x3b, 0x81, 0x72, 0x2f, 0xbf, 0xbc, 0xd8, 0x29, 0x14, 0x39, 0xe9, 0x7f, + 0x51, 0xb9, 0x2b, 0x9b, 0x47, 0x2a, 0x0e, 0xd4, 0x48, 0xc5, 0x42, 0xf5, 0xd0, 0x71, 0xdd, 0xe0, + 0x93, 0x77, 0xf5, 0xc9, 0xb9, 0x9a, 0x10, 0xd7, 0xfb, 0x13, 0xd0, 0x97, 0x7f, 0x30, 0x0f, 0xbd, + 0x7f, 0x8a, 0x74, 0xd4, 0x40, 0x12, 0x33, 0xdc, 0x89, 0x6c, 0x4a, 0x04, 0x16, 0x8e, 0xfe, 0x72, + 0xab, 0xe4, 0xe2, 0x6b, 0x02, 0xcb, 0x84, 0xa7, 0x2c, 0xbd, 0xf8, 0xe4, 0x73, 0x11, 0x9f, 0xac, + 0x23, 0xca, 0x8c, 0x86, 0xcb, 0xe9, 0x18, 0xb5, 0x76, 0xd2, 0x73, 0x8c, 0x77, 0x2d, 0xd6, 0x93, + 0xbe, 0x9d, 0x5e, 0x59, 0x79, 0xd8, 0xe0, 0x65, 0x14, 0xa1, 0x06, 0x68, 0x4a, 0x77, 0xfc, 0xc8, + 0x97, 0x5a, 0x11, 0x22, 0x54, 0x8f, 0xfd, 0xd9, 0x35, 0xb4, 0x9e, 0x7e, 0xf0, 0x3e, 0x74, 0x52, + 0x8b, 0x62, 0x62, 0x77, 0x9f, 0xa3, 0xfa, 0x10, 0x07, 0x4b, 0xe1, 0x4e, 0xd8, 0x4d, 0x8b, 0x94, + 0x99, 0x37, 0xbf, 0xb9, 0x26, 0x71, 0xc3, 0x3b, 0x5c, 0x6b, 0x77, 0x8a, 0x5a, 0x10, 0xdf, 0x3e, + 0x52, 0x9f, 0x72, 0x6b, 0x0a, 0x80, 0xc8, 0xf5, 0xf3, 0x4a, 0x08, 0x8e, 0x42, 0xf4, 0x74, 0x8a, + 0xf7, 0xdd, 0x00, 0xe4, 0xc0, 0x0f, 0xb8, 0xd5, 0x88, 0x6a, 0x45, 0xd8, 0x34, 0xd4, 0x4b, 0x42, + 0x1e, 0xdb, 0xb1, 0x3b, 0xc4, 0x7b, 0xbb, 0x1a, 0x19, 0x72, 0x2d, 0xc9, 0x10, 0x48, 0x7d, 0xc7, + 0x85, 0x4f, 0x22, 0x1b, 0x94, 0x5f, 0xc7, 0x00, 0xf1, 0x3f, 0x41, 0xfd, 0x06, 0x32, 0xa2, 0x5d, + 0xe3, 0x22, 0x60, 0xe4, 0xb1, 0x2b, 0x84, 0xc5, 0x34, 0xfe, 0xf1, 0xfe, 0xed, 0x8f, 0xc6, 0xbb, + 0x8b, 0x03, 0xb3, 0x8d, 0xb0, 0xe1, 0x35, 0xda, 0x54, 0x9b, 0x65, 0x49, 0xaa, 0xbd, 0xb9, 0xf5, + 0x92, 0x08, 0xb2, 0x90, 0x88, 0xc7, 0xf9, 0x74, 0xd7, 0x2c, 0xb9, 0x66, 0x3f, 0x32, 0x16, 0xe3, + 0x1b, 0xa7, 0x8d, 0x68, 0xc6, 0x51, 0x92, 0x67, 0xd9, 0xc4, 0x71, 0x5f, 0xfc, 0x9e, 0xf9, 0x01, + 0x4a, 0xc4, 0x0a, 0x8a, 0xc2, 0x16, 0x5b, 0x5b, 0x21, 0x61, 0xae, 0x31, 0xe8, 0x9a, 0x55, 0xd0, + 0xbd, 0x4d, 0xbb, 0x7d, 0x9e, 0x02, 0x71, 0x5b, 0x86, 0x1f, 0x6e, 0x50, 0x0f, 0x40, 0xd9, 0x64, + 0x6d, 0xb1, 0xb8, 0xd6, 0xa2, 0x08, 0xca, 0x64, 0xe0, 0xff, 0x96, 0x39, 0xe2, 0x62, 0x82, 0xcb, + 0x20, 0xca, 0xd0, 0x96, 0x64, 0x43, 0x9c, 0xd3, 0x47, 0x6f, 0x86, 0xd1, 0xd4, 0x52, 0x4c, 0xa1, + 0x8e, 0x8b, 0x7e, 0x13, 0x97, 0xda, 0x05, 0x46, 0x4a, 0xd5, 0x50, 0x56, 0xb5, 0x19, 0xa4, 0xd9, + 0x4c, 0x87, 0x84, 0x9e, 0x82, 0x11, 0x6f, 0x9f, 0xc2, 0x0b, 0x20, 0x4f, 0x2d, 0xbb, 0xf4, 0x88, + 0xda, 0xe9, 0x68, 0x57, 0x00, 0x3a, 0xe3, 0xc6, 0x25, 0xa9, 0xf6, 0xe0, 0x0c, 0xf1, 0x68, 0x1d, + 0xda, 0x6f, 0x0b, 0xf6, 0x50, 0x6a, 0x77, 0x37, 0xb3, 0x8d, 0x58, 0x8d, 0xa4, 0x70, 0x1b, 0x66, + 0xf6, 0xb6, 0xc0, 0xc6, 0x12, 0xec, 0x1d, 0xdb, 0xcc, 0x12, 0x0a, 0x1d, 0xdd, 0x3c, 0x10, 0xe0, + 0xe6, 0x4d, 0x74, 0x60, 0x14, 0x5d, 0x03, 0xf3, 0x7d, 0x41, 0x32, 0x10, 0x94, 0xdd, 0x8f, 0xf8, + 0xa6, 0x6b, 0x60, 0x51, 0x9a, 0x6f, 0x9c, 0x8a, 0x05, 0x0f, 0x8c, 0x68, 0x69, 0xa4, 0x56, 0xd0, + 0x30, 0x46, 0x2e, 0xde, 0x12, 0x8b, 0xf4, 0x9a, 0x84, 0x66, 0x78, 0x99, 0x6f, 0x37, 0xe5, 0x55, + 0xc5, 0xdb, 0xbc, 0x6f, 0xbc, 0xc0, 0x96, 0xdc, 0x5c, 0xe1, 0x5c, 0xcd, 0x5b, 0x6e, 0xe0, 0x0a, + 0x60, 0x14, 0x62, 0xd1, 0x85, 0x1e, 0xa3, 0xf1, 0x8d, 0x54, 0xdb, 0x82, 0x2a, 0x45, 0x5e, 0xb3, + 0x1c, 0x5a, 0x68, 0xd0, 0xed, 0x67, 0xd8, 0x2d, 0xb4, 0xbb, 0x5c, 0xe5, 0xb9, 0x9b, 0x30, 0x60, + 0xaa, 0xe6, 0x50, 0xd4, 0xf0, 0x84, 0x7d, 0x96, 0x09, 0x85, 0xb9, 0x58, 0x09, 0xdd, 0x0e, 0x7f, + 0x62, 0x57, 0x65, 0xee, 0x23, 0xb7, 0xc8, 0xa6, 0xe2, 0x99, 0x98, 0x85, 0xd0, 0x49, 0x64, 0xd6, + 0xd1, 0x30, 0xe5, 0x91, 0x17, 0x3e, 0x3c, 0x3c, 0xc8, 0x50, 0xd7, 0x9d, 0x24, 0x14, 0x70, 0x08, + 0xfe, 0xef, 0x1b, 0x5e, 0x0f, 0x8e, 0xbf, 0xcb, 0x07, 0xdc, 0x31, 0xd3, 0x75, 0x14, 0xa1, 0xa7, + 0x7b, 0x84, 0x0f, 0xc8, 0x50, 0x17, 0x00, 0xc0, 0x39, 0xef, 0x9b, 0x36, 0xaf, 0xa4, 0xb6, 0x53, + 0x98, 0xca, 0xfa, 0xa4, 0xab, 0xe8, 0xee, 0x63, 0xe4, 0xa5, 0x59, 0xd1, 0x0f, 0xd4, 0x27, 0x69, + 0x80, 0xb6, 0x28, 0x0c, 0x01, 0x0d, 0x16, 0x20, 0x57, 0xdb, 0xaa, 0x9c, 0x36, 0x12, 0xa6, 0x90, + 0xf5, 0xf2, 0x19, 0xb6, 0x01, 0xdf, 0x43, 0x25, 0xb8, 0x3a, 0xb3, 0xd5, 0xe9, 0xcd, 0x26, 0x26, + 0xc3, 0xcb, 0x65, 0x60, 0x87, 0xb0, 0x53, 0xc0, 0xf0, 0x01, 0x4e, 0x4c, 0xe4, 0x76, 0x13, 0xa2, + 0x34, 0xd4, 0x4b, 0xe1, 0x1d, 0xf0, 0x42, 0x38, 0xbc, 0xf9, 0x8d, 0x0d, 0xe7, 0x67, 0xeb, 0x1f, + 0xb8, 0x05, 0x16, 0x2f, 0xe8, 0xb6, 0x6c, 0xdd, 0x9d, 0x0b, 0xcc, 0xfb, 0x62, 0x9a, 0xb4, 0xa1, + 0x5f, 0xa2, 0x2f, 0x3f, 0x6d, 0xee, 0xe8, 0x3e, 0x9c, 0x4f, 0x20, 0xe0, 0x94, 0x62, 0x32, 0xcd, + 0x37, 0x30, 0x5f, 0x4c, 0x70, 0x70, 0x91, 0x41, 0xfc, 0x9d, 0xb1, 0xf4, 0x00, 0xe1, 0x2f, 0x0e, + 0x4c, 0xdc, 0x08, 0x0a, 0x7f, 0x86, 0xc3, 0xd4, 0xaa, 0x69, 0x9d, 0x3d, 0xa5, 0xaf, 0x7b, 0xe4, + 0x29, 0xc7, 0xc0, 0xe7, 0x95, 0x06, 0x51, 0x86, 0x36, 0x67, 0xd9, 0x6f, 0x9b, 0x10, 0x67, 0xe7, + 0x32, 0x4b, 0xca, 0x4d, 0x52, 0x04, 0x61, 0x26, 0x87, 0x7c, 0xa5, 0x63, 0xdb, 0x4e, 0xd6, 0x7b, + 0x81, 0x7e, 0x02, 0xd1, 0x23, 0xa5, 0x92, 0xda, 0xc9, 0x8e, 0x29, 0xf9, 0xfb, 0xd0, 0xea, 0x9d, + 0x3c, 0x27, 0x0f, 0x8c, 0xcd, 0x9f, 0x8f, 0xf1, 0xeb, 0xf7, 0xa9, 0xd5, 0x7b, 0xce, 0xe3, 0x89, + 0x4c, 0x78, 0x74, 0x84, 0x4e, 0xdf, 0x45, 0xc9, 0xc4, 0xc2, 0xc3, 0x00, 0x11, 0xf0, 0x0b, 0x5b, + 0x90, 0x1c, 0x53, 0x0c, 0x4d, 0xb3, 0x0c, 0x63, 0xe5, 0xa2, 0xff, 0xb5, 0x49, 0x5a, 0x14, 0x48, + 0x27, 0xe6, 0x2a, 0xda, 0x20, 0xa0, 0xe0, 0x1f, 0x28, 0x02, 0xb9, 0x6d, 0x8c, 0xf4, 0x9b, 0x02, + 0xe8, 0x42, 0x76, 0xac, 0x00, 0x68, 0x82, 0xf1, 0xd9, 0x4b, 0xd8, 0x4d, 0x21, 0x4f, 0x0b, 0xa0, + 0x34, 0x5d, 0x2a, 0xd9, 0xd9, 0x39, 0x76, 0x05, 0xb0, 0x20, 0x7d, 0x57, 0xf2, 0x8b, 0x74, 0x4c, + 0xc9, 0x8e, 0xd1, 0xd5, 0x25, 0x14, 0x49, 0x19, 0xf2, 0x0b, 0x9e, 0xa2, 0x91, 0x13, 0x02, 0x86, + 0x88, 0xee, 0xb8, 0x3a, 0x19, 0x5e, 0x16, 0x8a, 0x7b, 0xb4, 0xe9, 0x79, 0x96, 0x8c, 0xcf, 0xb3, + 0x05, 0xd7, 0x85, 0x70, 0xcd, 0x1b, 0xf6, 0x90, 0x2d, 0xcc, 0xf1, 0xb7, 0x8f, 0x2c, 0x3f, 0xef, + 0x65, 0x0b, 0xf5, 0xd3, 0xad, 0x17, 0xf0, 0x4f, 0x59, 0x0e, 0x84, 0x88, 0xf8, 0xdc, 0x83, 0xe2, + 0x53, 0x6d, 0x75, 0xde, 0x2b, 0xc2, 0xec, 0x8b, 0xc2, 0x25, 0x54, 0xbf, 0x3c, 0x6d, 0x51, 0x85, + 0x8d, 0x24, 0xcb, 0x56, 0xc6, 0xe3, 0x70, 0x1e, 0x1d, 0x15, 0x7e, 0x7f, 0xc7, 0x83, 0x33, 0x87, + 0xcc, 0x95, 0xe1, 0xaf, 0xa5, 0x2a, 0xa4, 0x01, 0xea, 0x9c, 0xdf, 0xfc, 0x0e, 0x55, 0x36, 0xe3, + 0x45, 0x02, 0xa5, 0x69, 0x8c, 0xdd, 0xf6, 0x17, 0x53, 0x8b, 0x5f, 0x95, 0x8c, 0x0e, 0xa8, 0x19, + 0xb2, 0x49, 0x73, 0xb8, 0x07, 0x74, 0x68, 0x70, 0xd2, 0x52, 0xee, 0xce, 0x83, 0xd9, 0xb0, 0x94, + 0x6d, 0x6e, 0x9a, 0xc3, 0x7d, 0xb3, 0x4e, 0x0f, 0xbf, 0x79, 0x09, 0xcc, 0xdc, 0xc8, 0xf8, 0x15, + 0x38, 0x50, 0xd4, 0xad, 0xf3, 0xc3, 0x6b, 0xe3, 0xdb, 0xc7, 0x98, 0xd0, 0x74, 0x66, 0xe5, 0x07, + 0xca, 0x14, 0xf1, 0xc4, 0xf2, 0xd2, 0x8b, 0xdf, 0x14, 0x00, 0x88, 0x14, 0xde, 0x8f, 0x79, 0xaf, + 0x01, 0x13, 0x23, 0x0c, 0x00, 0x68, 0x17, 0xaf, 0xe8, 0xb5, 0xa4, 0xac, 0xc7, 0x8b, 0xfd, 0xff, + 0xf6, 0x02, 0x79, 0xb5, 0x29, 0x73, 0x89, 0x2b, 0x4d, 0x80, 0x43, 0x5e, 0x7f, 0x4d, 0x57, 0xbc, + 0xc8, 0x58, 0x5c, 0x9c, 0x75, 0xef, 0xc8, 0x19, 0x07, 0xfc, 0x0e, 0x3b, 0x0b, 0x38, 0x45, 0x33, + 0x06, 0x69, 0xa1, 0x5d, 0x3c, 0xc6, 0xe5, 0xe3, 0xe7, 0xa0, 0x2a, 0x92, 0xca, 0x54, 0xac, 0xfc, + 0x39, 0x90, 0x83, 0xab, 0x0c, 0xe5, 0xf0, 0xb0, 0x18, 0xc5, 0xe7, 0x60, 0xa2, 0x3c, 0xa3, 0xa0, + 0xbf, 0x5c, 0xe4, 0xf8, 0xf5, 0xfc, 0xa6, 0x00, 0x99, 0x06, 0x16, 0x6c, 0x7e, 0x83, 0xd4, 0x60, + 0x97, 0x13, 0x54, 0x74, 0x35, 0x86, 0xb6, 0x6d, 0xf4, 0x06, 0xe5, 0xe9, 0xca, 0x03, 0xe8, 0xae, + 0x97, 0xf4, 0x1f, 0xd2, 0x1e, 0xe8, 0xf5, 0xe6, 0x4d, 0xb4, 0x5e, 0x03, 0x99, 0x82, 0x47, 0x41, + 0xfc, 0x80, 0xb4, 0x90, 0x8a, 0xec, 0x62, 0x9f, 0x2d, 0x10, 0xd1, 0xcd, 0x03, 0x3f, 0x9e, 0x45, + 0x5e, 0x02, 0x58, 0x4e, 0x19, 0x4e, 0x4c, 0x4b, 0xc3, 0x55, 0x87, 0x8a, 0x05, 0xc3, 0x5b, 0x28, + 0x80, 0x8d, 0x11, 0xba, 0x83, 0xef, 0x84, 0xdb, 0x48, 0x2f, 0x14, 0x66, 0x72, 0x82, 0x71, 0xdc, + 0x77, 0x68, 0x29, 0x11, 0x81, 0x16, 0xbe, 0xd7, 0x73, 0x4e, 0xbe, 0x3c, 0x3b, 0x5f, 0xf8, 0xb7, + 0x72, 0x8f, 0xa5, 0xec, 0xda, 0x98, 0x9b, 0xe3, 0x67, 0xa3, 0xf4, 0x08, 0xaf, 0xda, 0xff, 0x88, + 0x36, 0xc6, 0xca, 0xbb, 0x65, 0x46, 0x18, 0x89, 0xce, 0xa4, 0xc6, 0x03, 0xcb, 0x0e, 0x00, 0x85, + 0x5c, 0x46, 0x49, 0xf2, 0x60, 0x1b, 0x40, 0xd1, 0x26, 0xcc, 0xb8, 0x43, 0x1d, 0x26, 0xd8, 0xe4, + 0x69, 0xba, 0x61, 0x86, 0x08, 0x9c, 0x60, 0x3c, 0x00, 0x92, 0x91, 0xa5, 0x00, 0x79, 0xe3, 0xf9, + 0x08, 0xb5, 0x9a, 0xe7, 0x33, 0xd8, 0xf0, 0xf0, 0xcf, 0xb4, 0x79, 0x1b, 0x3f, 0xc3, 0x7e, 0x05, + 0xa8, 0x95, 0x55, 0xf9, 0xa9, 0x81, 0x67, 0xe4, 0x26, 0x16, 0x45, 0x0d, 0x38, 0x83, 0x3d, 0x24, + 0x2a, 0x3c, 0x4c, 0xb8, 0xf5, 0xa3, 0x4d, 0xca, 0x15, 0xad, 0x02, 0xae, 0x55, 0x61, 0x78, 0xb7, + 0x70, 0x3c, 0xe0, 0xf5, 0x65, 0x17, 0x6b, 0xfd, 0x9f, 0xd0, 0x30, 0x8c, 0xce, 0xa5, 0x77, 0x8b, + 0x3d, 0xf0, 0x64, 0x1d, 0x77, 0x7e, 0x10, 0x18, 0x2b, 0x38, 0xd4, 0xc9, 0x01, 0x1f, 0x74, 0x75, + 0x61, 0x44, 0x62, 0xa7, 0x60, 0x12, 0x13, 0x4d, 0x5a, 0x30, 0xae, 0x9f, 0x45, 0x27, 0x3c, 0xd9, + 0x0d, 0xa4, 0x67, 0x20, 0x07, 0x5e, 0x3a, 0x18, 0x37, 0x61, 0x74, 0x07, 0x48, 0x26, 0x8a, 0x16, + 0x06, 0x59, 0x82, 0x0e, 0x69, 0x10, 0xcf, 0xce, 0x33, 0x76, 0x0f, 0x64, 0x18, 0xf3, 0x0c, 0x7f, + 0xe1, 0x12, 0x94, 0x20, 0x62, 0x12, 0x69, 0xe3, 0xa2, 0x5b, 0xe7, 0xb3, 0x4d, 0x96, 0xd1, 0xc9, + 0x45, 0x73, 0x3d, 0xcb, 0x42, 0x03, 0xfe, 0x1d, 0xc7, 0x26, 0xf0, 0x4e, 0x00, 0x00, 0xf3, 0x1b, + 0xd7, 0x14, 0x10, 0x68, 0x8e, 0x01, 0x34, 0x1e, 0x34, 0xc0, 0x38, 0xef, 0xf1, 0xd2, 0xe3, 0x67, + 0x96, 0x4d, 0xd3, 0xd8, 0x83, 0x65, 0x1b, 0x37, 0xca, 0xfe, 0xd1, 0x1b, 0xbf, 0xa9, 0xa2, 0x87, + 0xd4, 0x6e, 0x26, 0x4e, 0x08, 0x9e, 0xc5, 0xb5, 0x6e, 0x58, 0x11, 0x46, 0x70, 0xb4, 0x90, 0x16, + 0xbb, 0xc1, 0xec, 0x89, 0xa5, 0xec, 0xfe, 0x0b, 0x36, 0x8f, 0x39, 0x02, 0xb8, 0x23, 0x44, 0x39, + 0x45, 0x36, 0x1b, 0xb8, 0xec, 0x6f, 0x1f, 0x89, 0xad, 0xca, 0xb5, 0x6c, 0x53, 0xcb, 0x5e, 0x32, + 0x02, 0x37, 0xfb, 0x71, 0xcd, 0xb2, 0x55, 0xb4, 0xe0, 0xea, 0x11, 0xb9, 0x45, 0x11, 0x14, 0xa0, + 0xf8, 0xb8, 0x03, 0x64, 0xf8, 0xcd, 0xd3, 0x53, 0x95, 0x26, 0x80, 0xad, 0x85, 0x15, 0x74, 0x80, + 0xb1, 0x2a, 0xb2, 0x3e, 0xf2, 0xfb, 0x40, 0x66, 0xc7, 0x11, 0xe9, 0xd4, 0xb0, 0xa2, 0x8f, 0x50, + 0x1f, 0x07, 0x6b, 0x4d, 0x53, 0x43, 0xa5, 0xd1, 0x90, 0x86, 0xc6, 0xfb, 0xc9, 0x08, 0xe0, 0x24, + 0x88, 0x50, 0xd0, 0x62, 0xab, 0xbb, 0x4b, 0xa8, 0x70, 0xe0, 0x50, 0xb1, 0x59, 0x19, 0xbe, 0x21, + 0xfe, 0xfb, 0x7b, 0xf7, 0xd3, 0x55, 0x79, 0x4d, 0x25, 0x1b, 0xfe, 0xfb, 0xfb, 0x72, 0x5e, 0x4c, + 0x94, 0xbd, 0x40, 0x46, 0xb9, 0xd5, 0x1c, 0xeb, 0x91, 0x21, 0x4c, 0xc4, 0x72, 0x9d, 0xb9, 0x8c, + 0xd9, 0x1c, 0xff, 0x1d, 0xef, 0x3e, 0x68, 0x6e, 0xcf, 0x7b, 0x31, 0x6c, 0x31, 0xbe, 0x9d, 0x1d, + 0x9d, 0x74, 0x86, 0x8a, 0xc8, 0x48, 0x1b, 0xaa, 0x98, 0x56, 0xe0, 0xe5, 0xfe, 0x3e, 0x45, 0x78, + 0x31, 0xe2, 0x34, 0x4b, 0x4d, 0x82, 0x34, 0x38, 0x0c, 0xc2, 0x4f, 0xce, 0x55, 0xfe, 0x39, 0x98, + 0x29, 0x30, 0x44, 0x04, 0x2d, 0x99, 0x06, 0x8b, 0xcf, 0xd6, 0x08, 0x4f, 0xcd, 0x10, 0x2d, 0x4a, + 0x0a, 0x28, 0x9a, 0xda, 0x47, 0x47, 0xd9, 0xf8, 0x94, 0xb0, 0x82, 0x63, 0x33, 0xb1, 0x2f, 0x01, + 0xbb, 0xc1, 0x41, 0x45, 0x9e, 0x42, 0x8a, 0x14, 0xbb, 0x79, 0x34, 0xc0, 0xe6, 0xc8, 0xcd, 0x4d, + 0xc3, 0xc9, 0x1b, 0x00, 0xf1, 0x73, 0xa0, 0x81, 0xa1, 0x72, 0x9c, 0x56, 0x57, 0x90, 0x91, 0xc3, + 0xde, 0x0e, 0x5f, 0x60, 0x85, 0xb1, 0xde, 0x8e, 0xdd, 0x2c, 0x79, 0x30, 0x70, 0x84, 0xee, 0x5c, + 0x8d, 0xa4, 0x22, 0x87, 0x5d, 0x68, 0x8d, 0x43, 0x6f, 0x12, 0x54, 0x58, 0xe6, 0x27, 0x3e, 0xd0, + 0xd1, 0x69, 0x94, 0x64, 0x9d, 0xf9, 0x3a, 0xbe, 0x90, 0xfc, 0xdb, 0x41, 0x7f, 0x24, 0xd6, 0x99, + 0xbb, 0x20, 0xc6, 0x05, 0x17, 0x4b, 0x42, 0x88, 0x27, 0xa4, 0x05, 0xa1, 0x43, 0xce, 0x4f, 0x85, + 0x3a, 0xb3, 0x87, 0xbe, 0xe7, 0xca, 0xb0, 0x17, 0x28, 0xb3, 0x63, 0x25, 0x0d, 0xe8, 0x41, 0x57, + 0x78, 0xed, 0x91, 0x8b, 0x39, 0xe1, 0x9c, 0x19, 0x45, 0x70, 0x04, 0x01, 0x90, 0xf0, 0x30, 0xbb, + 0xcc, 0x8e, 0x30, 0x04, 0x4e, 0xe1, 0x3a, 0x21, 0xc3, 0xd5, 0xae, 0xa0, 0x61, 0x9c, 0xdc, 0x62, + 0x99, 0x59, 0x1e, 0x99, 0xb0, 0x66, 0xc5, 0xbd, 0x45, 0xec, 0x93, 0xbe, 0x57, 0xa5, 0x18, 0xa4, + 0x4a, 0xd2, 0x09, 0x91, 0xc3, 0xb4, 0xb1, 0x62, 0x8c, 0x50, 0x6f, 0xc4, 0xf8, 0xdb, 0x02, 0x33, + 0x2c, 0xb7, 0xb0, 0x16, 0x49, 0x27, 0x88, 0xca, 0x38, 0x06, 0xf3, 0x65, 0x45, 0x3e, 0x6e, 0x26, + 0x83, 0x1d, 0xe3, 0x5f, 0x63, 0x19, 0x24, 0x40, 0x6d, 0x48, 0x1d, 0x86, 0x4f, 0xec, 0xa8, 0xef, + 0x38, 0x57, 0xc0, 0x96, 0xdc, 0xc7, 0x48, 0x90, 0xe6, 0x7c, 0x14, 0xd0, 0x34, 0x83, 0x4c, 0xf8, + 0x2d, 0x57, 0x5a, 0xe6, 0xa5, 0x3a, 0xf2, 0x0b, 0x34, 0x7d, 0xf8, 0xcd, 0x3d, 0x3b, 0x79, 0x79, + 0x36, 0x3a, 0xef, 0xf9, 0xa2, 0x55, 0x7d, 0x00, 0x40, 0x8d, 0xca, 0x0a, 0x8b, 0xfa, 0xc6, 0x65, + 0x27, 0xf9, 0x13, 0xc2, 0xee, 0x14, 0x68, 0xee, 0x03, 0x27, 0x87, 0x85, 0xdb, 0x07, 0x49, 0x66, + 0x76, 0x0a, 0xcc, 0x24, 0x8a, 0x33, 0x0e, 0x5c, 0xf8, 0x73, 0x78, 0xe8, 0x88, 0xbf, 0x9d, 0xf6, + 0x5b, 0x32, 0x94, 0x6e, 0xa0, 0x08, 0xc4, 0xb2, 0x25, 0x04, 0xa2, 0xfa, 0xc1, 0x96, 0xfc, 0xb5, + 0x1b, 0x35, 0x0e, 0x96, 0x85, 0x20, 0x05, 0x7e, 0x4b, 0x2f, 0xcb, 0x80, 0x1b, 0x92, 0x52, 0x28, + 0x49, 0x06, 0x01, 0x1c, 0xd0, 0x02, 0xf4, 0xb6, 0x5c, 0x99, 0x6e, 0xa0, 0x63, 0xf9, 0x4c, 0xd2, + 0x2b, 0xb1, 0x4a, 0xdc, 0x14, 0x50, 0x43, 0x73, 0x8e, 0x35, 0xe2, 0x5c, 0xed, 0xc5, 0x2b, 0xc0, + 0xb1, 0x2a, 0x3a, 0xab, 0xef, 0x4d, 0x54, 0x6d, 0x51, 0x95, 0xa3, 0xc8, 0x87, 0xea, 0x32, 0x61, + 0x6c, 0xc5, 0xbc, 0xb8, 0xd7, 0x67, 0x27, 0x23, 0x60, 0x15, 0x0b, 0x55, 0xa5, 0xbe, 0xdc, 0x4e, + 0xa8, 0x85, 0xbd, 0x48, 0xbb, 0xf1, 0x5d, 0x82, 0x41, 0xe4, 0x3f, 0x70, 0x6d, 0xe7, 0x39, 0xd5, + 0xb8, 0x30, 0x47, 0xe9, 0x18, 0x0a, 0x4e, 0x02, 0xb7, 0x93, 0xc2, 0xff, 0x3d, 0x17, 0x5e, 0xac, + 0xa2, 0x0a, 0xf8, 0x46, 0x91, 0xe5, 0x78, 0x24, 0x38, 0x73, 0x98, 0x8e, 0x91, 0x6a, 0xa1, 0xbc, + 0x67, 0xce, 0xf7, 0x8a, 0x02, 0x54, 0xda, 0x03, 0xea, 0x1c, 0x33, 0xad, 0x5f, 0x09, 0xd6, 0xd9, + 0x13, 0x78, 0x98, 0x75, 0x37, 0x24, 0xf9, 0x26, 0x55, 0x94, 0x4f, 0xc0, 0x6a, 0x5c, 0xc1, 0x06, + 0xae, 0x60, 0x02, 0xcc, 0x63, 0x85, 0xa4, 0x6b, 0x7c, 0xe4, 0x4a, 0xbe, 0x04, 0xb2, 0xa2, 0x2c, + 0x17, 0x93, 0xad, 0xa1, 0x9e, 0x2e, 0x77, 0xb2, 0xf9, 0x7f, 0x37, 0x9b, 0x95, 0x77, 0xb3, 0x31, + 0x81, 0x02, 0x04, 0xe2, 0xa1, 0x4b, 0x92, 0x97, 0xf4, 0x1f, 0x7e, 0xb6, 0xea, 0x98, 0x4e, 0xb7, + 0x3f, 0xe8, 0x9a, 0x5c, 0x5b, 0xd8, 0xfc, 0xd9, 0xbf, 0xf1, 0x12, 0x1f, 0x31, 0x67, 0x77, 0x1e, + 0x0a, 0x05, 0xe2, 0x79, 0xc8, 0x37, 0xe3, 0x2d, 0x80, 0x2c, 0x96, 0xce, 0x0d, 0xf3, 0xdb, 0xc7, + 0x28, 0x2f, 0xa8, 0xa1, 0x73, 0x32, 0x87, 0x29, 0x76, 0x17, 0xb4, 0x9e, 0x99, 0x08, 0xce, 0xdf, + 0x3e, 0x7a, 0x39, 0xfd, 0x91, 0x1d, 0x32, 0x5f, 0x6f, 0xfc, 0x00, 0x85, 0xbe, 0xdd, 0x5b, 0xb4, + 0xd6, 0xd4, 0xbf, 0x5d, 0x02, 0x8d, 0xed, 0x91, 0x2b, 0x44, 0x82, 0x19, 0xcc, 0x75, 0xe7, 0x2f, + 0xfd, 0x6e, 0x4a, 0xe9, 0x47, 0xe6, 0x77, 0x06, 0x59, 0xe9, 0x52, 0x5a, 0x02, 0x14, 0xb9, 0x6d, + 0x1a, 0x8b, 0xd7, 0x6b, 0xcb, 0xac, 0xd6, 0xf3, 0x7b, 0x8c, 0x0c, 0x2e, 0xa9, 0xec, 0xaa, 0xcc, + 0x6e, 0x77, 0x43, 0xe9, 0x56, 0x35, 0xfb, 0x4f, 0x00, 0x14, 0x06, 0x42, 0x05, 0xc0, 0x08, 0x54, + 0x79, 0xf3, 0x9a, 0x57, 0xa8, 0x66, 0x79, 0x9b, 0x66, 0x28, 0x5e, 0x00, 0x6a, 0x57, 0x28, 0x28, + 0x99, 0x76, 0x50, 0xcb, 0xf4, 0x53, 0x02, 0x28, 0x27, 0x35, 0x7a, 0xc8, 0x3e, 0x46, 0x21, 0x0d, + 0x92, 0x60, 0x69, 0x19, 0xa7, 0xd5, 0x26, 0x7f, 0x79, 0xf5, 0xc6, 0xf0, 0x16, 0x8b, 0x84, 0xe2, + 0xe4, 0xb1, 0xee, 0xda, 0x9b, 0xd7, 0x3a, 0xe5, 0x07, 0x2c, 0x7d, 0x48, 0x61, 0xef, 0x61, 0x86, + 0x65, 0xda, 0xdd, 0x1c, 0x99, 0x3d, 0x1c, 0x3d, 0x3c, 0x66, 0x47, 0xd8, 0x4b, 0x9c, 0x0c, 0x3d, + 0x80, 0xf4, 0xf7, 0x3c, 0x63, 0x8f, 0x67, 0xb2, 0xc8, 0x3b, 0x66, 0xb5, 0xde, 0xb7, 0xe1, 0xad, + 0x9f, 0x44, 0xe1, 0x9a, 0xc6, 0xc0, 0xba, 0x5e, 0x32, 0x5f, 0x11, 0x87, 0x8d, 0x4a, 0x1f, 0x09, + 0x83, 0x47, 0x9a, 0xe2, 0xe0, 0xce, 0x8f, 0xd1, 0x52, 0x90, 0x4a, 0x03, 0x31, 0x88, 0xab, 0x0b, + 0x08, 0xa9, 0x8e, 0x88, 0x6e, 0x6e, 0x75, 0x2c, 0x54, 0xdf, 0x87, 0x97, 0xec, 0x9a, 0x44, 0x6f, + 0xea, 0x5e, 0x1c, 0xa9, 0x8a, 0x5c, 0xba, 0xf6, 0x16, 0x57, 0xda, 0x1a, 0xe9, 0x86, 0x65, 0x1d, + 0x44, 0x44, 0xd7, 0xdc, 0xfd, 0x8b, 0x6a, 0x62, 0x26, 0xab, 0x01, 0x16, 0x58, 0xee, 0x5e, 0x48, + 0x42, 0x8b, 0x33, 0xc4, 0x34, 0x41, 0x79, 0xa4, 0xa1, 0x3b, 0x34, 0x6b, 0x24, 0x14, 0xd3, 0x3e, + 0x05, 0x57, 0x2e, 0x7a, 0xea, 0x82, 0x0d, 0xee, 0xaa, 0xad, 0x13, 0xae, 0x54, 0x3a, 0x13, 0x1c, + 0xf5, 0xe1, 0x94, 0x1b, 0x63, 0x8f, 0xf0, 0x13, 0x76, 0x2c, 0x68, 0x3c, 0x93, 0x4c, 0x81, 0xe8, + 0x89, 0xb8, 0x90, 0xe9, 0xc4, 0x72, 0x1b, 0xe9, 0x7c, 0x75, 0x13, 0x88, 0xef, 0xc6, 0x61, 0x38, + 0x4b, 0xe3, 0x11, 0x7f, 0x3e, 0x27, 0x51, 0xa9, 0xc1, 0x65, 0xac, 0x94, 0x77, 0x16, 0xdd, 0x2b, + 0x27, 0x43, 0x90, 0x03, 0x9b, 0x46, 0x07, 0x0d, 0x77, 0x4c, 0x02, 0xa9, 0xd8, 0x83, 0x0e, 0x7e, + 0xb1, 0x4c, 0x58, 0x51, 0x74, 0x4c, 0x12, 0x4c, 0x78, 0x51, 0x0c, 0xd0, 0x0d, 0x27, 0x95, 0x68, + 0xe6, 0x3c, 0x05, 0x4c, 0xaa, 0x75, 0x63, 0xed, 0x25, 0xbc, 0x2b, 0x78, 0xd2, 0xe0, 0x57, 0xd1, + 0xe1, 0x1e, 0xf5, 0xb8, 0xf1, 0x98, 0xaa, 0x9d, 0xb0, 0xd8, 0xfa, 0xdb, 0x7b, 0xd1, 0xbe, 0x68, + 0x49, 0xac, 0xad, 0x81, 0x89, 0xa2, 0xc6, 0x2f, 0x3c, 0x6c, 0x83, 0x96, 0x83, 0x36, 0x68, 0x3c, + 0x64, 0x83, 0xfd, 0x0e, 0xd8, 0x86, 0x06, 0xe8, 0x45, 0x6f, 0x85, 0x1a, 0x11, 0x35, 0x68, 0xe8, + 0x0b, 0xbe, 0x65, 0x72, 0x84, 0x28, 0xdf, 0xe1, 0x4f, 0x86, 0x22, 0xcb, 0xc1, 0x1c, 0x40, 0xab, + 0x50, 0x58, 0x78, 0xe3, 0xfd, 0xdb, 0x1f, 0x49, 0x98, 0xb3, 0x25, 0x5b, 0x14, 0x57, 0x72, 0x91, + 0xe0, 0x67, 0x8f, 0x16, 0x04, 0x94, 0x88, 0xc4, 0x30, 0x22, 0x8d, 0x35, 0x03, 0x97, 0x47, 0x07, + 0x15, 0x53, 0x00, 0x52, 0xb8, 0x59, 0xcf, 0x58, 0x42, 0x32, 0x2f, 0xd7, 0x74, 0xe0, 0xaf, 0x77, + 0xef, 0x02, 0xa6, 0x96, 0xca, 0x92, 0xc7, 0x7d, 0x18, 0x3e, 0x67, 0x98, 0x4c, 0x82, 0x20, 0x1c, + 0x00, 0xcd, 0x34, 0xb5, 0xe3, 0x9a, 0xfc, 0x74, 0x7d, 0x0f, 0x0c, 0x8b, 0x98, 0xec, 0xed, 0x23, + 0xdb, 0xb3, 0x7b, 0x6c, 0xcf, 0xee, 0x55, 0x3b, 0x17, 0xc5, 0xfb, 0xf6, 0xad, 0x9c, 0x4f, 0x89, + 0xac, 0xfe, 0xcc, 0xba, 0xfe, 0x0d, 0x30, 0x6a, 0x0c, 0x14, 0xce, 0x8e, 0x65, 0xc5, 0xeb, 0x17, + 0x2d, 0xd3, 0x5f, 0xbc, 0xaa, 0xd7, 0x49, 0xdc, 0x38, 0x71, 0x7d, 0x31, 0x71, 0x83, 0xb3, 0x33, + 0x6d, 0xc2, 0x20, 0xff, 0xbf, 0x7f, 0x2d, 0xd3, 0x78, 0xbe, 0x75, 0x35, 0xab, 0x9d, 0x82, 0xfc, + 0x7f, 0x76, 0x11, 0x95, 0xed, 0xbd, 0x32, 0x66, 0xb1, 0xd6, 0x1d, 0x38, 0x0d, 0x54, 0xea, 0xb9, + 0x0d, 0xeb, 0x00, 0x39, 0x87, 0x02, 0xc5, 0x02, 0xff, 0x4f, 0x4c, 0x6f, 0x9e, 0xd5, 0xd1, 0x01, + 0x64, 0xd3, 0xb9, 0x0a, 0x40, 0x70, 0x17, 0x77, 0x89, 0x8a, 0x79, 0x9c, 0x17, 0xcb, 0x16, 0xcc, + 0x43, 0xca, 0xa4, 0xa8, 0x75, 0x68, 0xf8, 0x40, 0xc3, 0xdc, 0xa5, 0x05, 0xa8, 0xf1, 0x89, 0x55, + 0x9a, 0x99, 0x01, 0x79, 0x55, 0x9b, 0x68, 0x3f, 0xd5, 0xb1, 0x3d, 0xb6, 0xfd, 0x3a, 0xf1, 0x25, + 0xc2, 0xaf, 0xcc, 0xe0, 0xc7, 0xc4, 0xf3, 0xb9, 0x3b, 0x51, 0x4b, 0x9d, 0x78, 0x09, 0x1f, 0xea, + 0xd5, 0x9d, 0xba, 0x1a, 0xd0, 0x32, 0x8c, 0xb8, 0x27, 0x7b, 0x56, 0xeb, 0xbe, 0x50, 0x1b, 0xd4, + 0xa7, 0xb4, 0x7c, 0x6c, 0x9b, 0xde, 0x79, 0xb8, 0xc4, 0x7f, 0xc7, 0x69, 0x31, 0x9b, 0xf3, 0x0a, + 0x0a, 0xe7, 0xe3, 0xd1, 0x51, 0xb8, 0x53, 0x4e, 0x64, 0x5b, 0xc5, 0x0b, 0x3c, 0x03, 0x45, 0x95, + 0x8b, 0x4a, 0x95, 0x0b, 0xf5, 0x40, 0xe4, 0x6b, 0x73, 0xf2, 0x83, 0x5a, 0x65, 0xc3, 0x71, 0x9c, + 0xb0, 0x5b, 0xf5, 0x40, 0x36, 0x7e, 0x43, 0xd9, 0x1d, 0x70, 0x19, 0x0b, 0xe9, 0x32, 0x48, 0x6e, + 0x8f, 0x9d, 0xa7, 0x33, 0xd4, 0x54, 0x59, 0x2f, 0xa8, 0x4b, 0x3d, 0x9d, 0x21, 0x43, 0xe3, 0xe9, + 0xbc, 0xff, 0xf1, 0xac, 0x9f, 0xcf, 0x7b, 0x8d, 0xe7, 0x17, 0x1f, 0x19, 0x25, 0x83, 0x2d, 0x97, + 0x30, 0x9c, 0xbd, 0xc7, 0xb2, 0xf6, 0x2b, 0x43, 0xf9, 0xc5, 0x57, 0x47, 0xb2, 0xf6, 0xff, 0xd2, + 0x81, 0x34, 0xf2, 0xba, 0x0d, 0xf2, 0x17, 0x84, 0xa2, 0x3a, 0x97, 0xab, 0x52, 0x68, 0x63, 0x97, + 0xeb, 0xfa, 0x4f, 0x3a, 0x8d, 0xa5, 0x37, 0x99, 0xaf, 0x4b, 0x70, 0x9e, 0x69, 0x3d, 0x5e, 0x99, + 0xe3, 0x5f, 0xbc, 0x7b, 0x7f, 0xbd, 0x59, 0x1b, 0x1c, 0x93, 0xd1, 0xb5, 0xb6, 0xa0, 0x56, 0x61, + 0x66, 0x3d, 0x18, 0xd2, 0xa2, 0x2b, 0xc6, 0xf1, 0x4c, 0x35, 0xa8, 0x70, 0xac, 0x61, 0xf1, 0x86, + 0x66, 0xf8, 0x8a, 0x02, 0x82, 0x6a, 0x76, 0xa1, 0xdc, 0x98, 0x93, 0x96, 0xaf, 0x8b, 0xf0, 0x4a, + 0x2a, 0xbe, 0x25, 0x16, 0x0c, 0x8a, 0x7b, 0x5a, 0xda, 0xd0, 0xf5, 0x1b, 0x93, 0x12, 0x65, 0x4c, + 0x31, 0xb2, 0xaf, 0x20, 0x78, 0xcf, 0x07, 0x8d, 0x12, 0x51, 0xdc, 0x25, 0xe6, 0x11, 0x36, 0x53, + 0xd5, 0x03, 0x16, 0x7a, 0xb7, 0x0d, 0x7a, 0xda, 0x49, 0x3a, 0xcb, 0xc2, 0x9a, 0xae, 0xb3, 0x6c, + 0x68, 0xdc, 0x97, 0xfe, 0xc2, 0xa5, 0xee, 0x6e, 0x9d, 0xc2, 0x7f, 0x4b, 0xd0, 0xa6, 0x10, 0xf8, + 0x15, 0x99, 0x3c, 0xf2, 0x18, 0xe8, 0xae, 0x79, 0xac, 0x41, 0x22, 0x0a, 0x98, 0x4d, 0x3d, 0x93, + 0x69, 0xd0, 0xcd, 0xe5, 0x2a, 0x0a, 0xd0, 0xc5, 0x94, 0x79, 0x29, 0x12, 0x0b, 0xd4, 0xc7, 0x73, + 0x49, 0xac, 0xd7, 0x6b, 0x41, 0x1d, 0x3c, 0xd7, 0xf1, 0x1c, 0x6d, 0x99, 0x03, 0x42, 0x23, 0xaa, + 0x84, 0x9a, 0x52, 0x2f, 0xd5, 0x8a, 0x38, 0x36, 0x12, 0x68, 0x9d, 0x83, 0xe4, 0x33, 0xbc, 0x25, + 0x59, 0xf9, 0x4b, 0xf4, 0x21, 0x8e, 0x6b, 0xc8, 0x95, 0xda, 0x9c, 0x51, 0x56, 0x06, 0xde, 0x02, + 0x9e, 0xc3, 0x22, 0xc7, 0x0f, 0xe8, 0xd3, 0xa6, 0xe0, 0x33, 0x80, 0xe9, 0xea, 0xdb, 0x48, 0x3a, + 0x93, 0x53, 0x88, 0x1c, 0xab, 0x21, 0x79, 0x5d, 0xb4, 0x46, 0xb7, 0x56, 0x16, 0x45, 0x50, 0xe4, + 0x15, 0x63, 0x31, 0x87, 0x67, 0x35, 0x2f, 0x23, 0x40, 0xbe, 0x78, 0xf3, 0x4d, 0xce, 0xe7, 0x80, + 0xd5, 0x9c, 0xdf, 0x3c, 0x98, 0x79, 0xd9, 0x74, 0x43, 0xcc, 0x2f, 0xe0, 0x42, 0xae, 0x51, 0x31, + 0x02, 0xc1, 0xc8, 0x4f, 0x49, 0x46, 0xf3, 0x73, 0xb6, 0x0e, 0x3a, 0xe6, 0xf2, 0x1e, 0xd8, 0x3a, + 0xd4, 0xad, 0xf1, 0x17, 0xfc, 0x2f, 0x36, 0x61, 0xe3, 0xa6, 0xfe, 0x27, 0x5e, 0x05, 0xf3, 0x34, + 0x6a, 0xa9, 0x09, 0x18, 0x96, 0xf7, 0x68, 0xcb, 0xb8, 0x8b, 0xa5, 0xbb, 0x10, 0xd6, 0x2e, 0x24, + 0xf7, 0xfc, 0x4f, 0x4e, 0xd4, 0x8f, 0xd2, 0xc9, 0x5a, 0x6d, 0xaa, 0xfe, 0xf3, 0x80, 0xf7, 0x6f, + 0x01, 0xbb, 0x2d, 0x2b, 0x4e, 0xc2, 0xb3, 0x14, 0x57, 0x1d, 0xa6, 0xff, 0x02, 0x10, 0xff, 0x9b, + 0x14, 0x16, 0x80, 0xaf, 0xb4, 0x35, 0x6a, 0x85, 0x07, 0x61, 0x99, 0xd4, 0x06, 0x14, 0x17, 0xf2, + 0xb3, 0xc6, 0xd3, 0x06, 0x50, 0x43, 0x4c, 0x27, 0x1c, 0x61, 0x05, 0xa2, 0x1d, 0x0a, 0x29, 0xe5, + 0x54, 0x85, 0xa1, 0x46, 0xbc, 0x8d, 0x17, 0x8a, 0xb2, 0xe2, 0x16, 0x50, 0x02, 0x32, 0x2c, 0xf1, + 0xee, 0xc4, 0x48, 0x3a, 0x52, 0x32, 0xd8, 0x64, 0x2e, 0xf1, 0x8d, 0x56, 0x9f, 0xd1, 0xc5, 0xbe, + 0x99, 0x5b, 0xa1, 0xed, 0x91, 0xcf, 0x20, 0x02, 0x56, 0x17, 0xaf, 0xdf, 0x60, 0x98, 0xe4, 0xbc, + 0x91, 0xa7, 0x54, 0xad, 0x26, 0x8a, 0xb1, 0x5a, 0x23, 0x44, 0xe6, 0x29, 0x47, 0x84, 0x95, 0x79, + 0x46, 0x4b, 0x46, 0xf5, 0x9a, 0x5e, 0x5b, 0x03, 0x12, 0xae, 0xab, 0x16, 0x60, 0xa5, 0x56, 0x45, + 0x99, 0xf6, 0x89, 0x5d, 0x8d, 0xc8, 0x86, 0x56, 0xde, 0x30, 0x4b, 0x87, 0x82, 0x06, 0xb7, 0xe8, + 0xe8, 0x53, 0xd0, 0x07, 0xe1, 0x5b, 0x80, 0xec, 0x2f, 0x5d, 0x74, 0xad, 0x65, 0x57, 0xdc, 0xff, + 0xa2, 0x80, 0x4f, 0x7c, 0x47, 0x71, 0x2d, 0x85, 0x24, 0x12, 0xda, 0x37, 0x42, 0xf0, 0xcf, 0x67, + 0xd2, 0x19, 0xb1, 0x52, 0xdf, 0x8e, 0xe1, 0xa4, 0x70, 0xf3, 0xb6, 0xd4, 0x45, 0x25, 0x25, 0x2e, + 0x1e, 0xb1, 0x3d, 0x3b, 0xb2, 0x13, 0xbc, 0x40, 0x80, 0x8e, 0xe9, 0xed, 0xa4, 0x96, 0x95, 0xb8, + 0x68, 0xaf, 0x8b, 0xe1, 0x63, 0xbe, 0x47, 0x89, 0x6c, 0xe0, 0xa2, 0x4b, 0x03, 0xdb, 0x83, 0x3f, + 0x83, 0x2b, 0x3b, 0x82, 0x3f, 0x27, 0x57, 0x14, 0xc1, 0xd7, 0xc0, 0x08, 0xbe, 0x89, 0xe9, 0xba, + 0xa9, 0x15, 0x60, 0x7f, 0xbe, 0xd7, 0xa2, 0x75, 0x40, 0x81, 0x7a, 0x5a, 0x54, 0x4f, 0x2b, 0xaa, + 0x2a, 0x0c, 0x19, 0x25, 0x4c, 0x60, 0xb3, 0xc7, 0xfd, 0x11, 0xb4, 0x2f, 0xbf, 0xc0, 0x00, 0x70, + 0x66, 0x3c, 0x3d, 0xa5, 0x4f, 0xbd, 0x52, 0x53, 0x06, 0x57, 0xf9, 0x81, 0xf4, 0x24, 0x97, 0xb8, + 0xac, 0x27, 0xe7, 0xe3, 0x7b, 0x32, 0xc4, 0xe5, 0x9e, 0x6e, 0x3a, 0x53, 0x54, 0x36, 0xc4, 0x13, + 0xd6, 0x46, 0x59, 0xa5, 0x8d, 0x52, 0x4d, 0x0b, 0xa8, 0x9e, 0x24, 0xff, 0x6e, 0x2a, 0x8d, 0x57, + 0xa7, 0xa5, 0xd6, 0xd3, 0xd0, 0xe0, 0xae, 0xd5, 0x8e, 0xaf, 0x85, 0x6f, 0xb5, 0x4e, 0x16, 0x19, + 0x09, 0x39, 0xed, 0x43, 0xed, 0xd2, 0x7f, 0x45, 0x7e, 0x88, 0xd7, 0x79, 0xa3, 0xa9, 0x0e, 0x2d, + 0xf5, 0x7d, 0x49, 0x8a, 0x24, 0x36, 0x7a, 0x3c, 0x04, 0x9c, 0xec, 0x69, 0x1a, 0x25, 0x95, 0x7d, + 0x48, 0x97, 0x66, 0xcb, 0x7b, 0xfc, 0xc5, 0x1e, 0x9a, 0x74, 0xa3, 0x7c, 0x8c, 0xd4, 0x1b, 0xaa, + 0x92, 0x20, 0x8e, 0x79, 0xc3, 0x71, 0x0c, 0xee, 0xd1, 0x0e, 0xa6, 0x59, 0x8d, 0xf2, 0x28, 0xec, + 0x70, 0x04, 0x15, 0xa9, 0xf4, 0xa2, 0x86, 0x17, 0x29, 0x83, 0xc2, 0x2d, 0x60, 0xe5, 0x88, 0x27, + 0xf0, 0x99, 0xe5, 0x66, 0x93, 0x70, 0x89, 0x8a, 0x20, 0xd1, 0xb7, 0x45, 0xae, 0x54, 0x2d, 0x83, + 0x63, 0x22, 0xe1, 0x52, 0xf1, 0x19, 0x85, 0xa8, 0x61, 0x5e, 0x64, 0x56, 0x09, 0x47, 0xa3, 0x10, + 0x2d, 0x09, 0xdc, 0x53, 0x4e, 0xeb, 0x0c, 0x7b, 0x4d, 0xf7, 0xa4, 0x3c, 0x32, 0x87, 0x08, 0xca, + 0x61, 0x9c, 0x0c, 0x86, 0x62, 0x87, 0xbd, 0xbd, 0xbc, 0x38, 0x19, 0x98, 0x3c, 0xb4, 0xed, 0x0b, + 0x35, 0xf5, 0xc5, 0xe0, 0xf9, 0x73, 0x53, 0x2c, 0xae, 0x39, 0x51, 0x28, 0x9a, 0x59, 0xa8, 0xe9, + 0x5f, 0x98, 0xa8, 0x92, 0x8b, 0xea, 0xe8, 0x84, 0x2f, 0x27, 0xac, 0xeb, 0xc7, 0x43, 0xfe, 0x5c, + 0x3f, 0x13, 0xc9, 0x7e, 0x56, 0x75, 0xfb, 0x04, 0xeb, 0x9a, 0xe2, 0x0f, 0xd2, 0x7e, 0x18, 0xb3, + 0xb2, 0x1b, 0x92, 0xa3, 0x8b, 0x47, 0xf1, 0xc0, 0xcf, 0x3b, 0x2a, 0xe0, 0x8e, 0x79, 0xa5, 0xa4, + 0x6a, 0x1c, 0xb0, 0x37, 0xfc, 0x0c, 0xc4, 0x12, 0x1e, 0x4a, 0xab, 0xcb, 0xeb, 0x3c, 0x52, 0xf3, + 0x96, 0xe5, 0xeb, 0xca, 0xde, 0xe2, 0xcb, 0x27, 0x8f, 0x30, 0x4d, 0xc4, 0x8b, 0xa7, 0xe5, 0x65, + 0xc0, 0xb4, 0xf9, 0x06, 0xdf, 0xe3, 0xac, 0x16, 0x70, 0xdc, 0xca, 0x81, 0x55, 0x68, 0x3d, 0x0b, + 0xcd, 0x97, 0x67, 0xc5, 0x3d, 0x79, 0x04, 0xb3, 0x90, 0x3f, 0xe3, 0x97, 0xb2, 0x7c, 0xbe, 0x22, + 0x4b, 0xbd, 0x98, 0x9d, 0x42, 0x32, 0x2d, 0x4d, 0xc4, 0x43, 0xa5, 0xe4, 0x74, 0x3f, 0xe0, 0x43, + 0x6e, 0xc7, 0x75, 0x23, 0x14, 0xfb, 0x4f, 0xcc, 0x0f, 0xbd, 0x57, 0xe6, 0x90, 0x9e, 0x73, 0x3c, + 0xfd, 0xa6, 0x96, 0x0d, 0x54, 0x71, 0x9e, 0xc3, 0x34, 0x2c, 0xe6, 0xe7, 0xce, 0x24, 0x3c, 0x72, + 0xcd, 0x77, 0xc2, 0x1b, 0x8d, 0x81, 0xdb, 0x06, 0x35, 0x1a, 0xa4, 0x95, 0x77, 0xd7, 0x1c, 0xa2, + 0x56, 0x3b, 0xb7, 0x97, 0x37, 0x3f, 0x44, 0x46, 0x84, 0x9a, 0x17, 0x85, 0xf7, 0x9a, 0xd4, 0x58, + 0xe2, 0x46, 0xed, 0xa2, 0xb5, 0x01, 0x4a, 0x6a, 0x5b, 0x2e, 0x26, 0x08, 0xb2, 0xd2, 0x5c, 0x3e, + 0x15, 0xe2, 0xf1, 0x37, 0x5c, 0xbc, 0x5f, 0x54, 0x37, 0x44, 0x21, 0x39, 0x4d, 0xa4, 0x80, 0xc2, + 0x2d, 0xa2, 0xf0, 0x50, 0x3b, 0xec, 0x42, 0x5d, 0x21, 0x81, 0xc3, 0x47, 0xa9, 0x8e, 0x80, 0xf7, + 0xf4, 0x3d, 0x5a, 0xaf, 0x2d, 0xca, 0x08, 0x65, 0xa6, 0x2f, 0x53, 0x45, 0x28, 0x14, 0x74, 0x36, + 0xc1, 0xc2, 0x40, 0x8f, 0x3d, 0xd8, 0x03, 0x03, 0xbb, 0x60, 0x20, 0x7d, 0xc7, 0x75, 0x11, 0x9b, + 0x75, 0x14, 0x34, 0x70, 0x96, 0x56, 0xc9, 0xe4, 0x3f, 0xf4, 0xcb, 0x75, 0x14, 0x72, 0xab, 0xae, + 0x9f, 0x4b, 0x6c, 0x8e, 0xb4, 0xb7, 0x17, 0x7e, 0xa4, 0xc4, 0x96, 0xe1, 0xce, 0x4e, 0xbd, 0xb4, + 0xea, 0xe9, 0x01, 0x36, 0x9e, 0x27, 0x93, 0xd0, 0xc5, 0xea, 0x3d, 0xd7, 0xf9, 0x18, 0x62, 0x78, + 0xe4, 0xc0, 0xe5, 0xf7, 0x1e, 0x94, 0xd2, 0x4b, 0x65, 0x98, 0x1e, 0x45, 0xf4, 0x8f, 0x22, 0x7b, + 0x81, 0x1a, 0xfa, 0x43, 0xd8, 0x96, 0xdf, 0x2c, 0x1d, 0xc7, 0x54, 0xa3, 0x5e, 0x0f, 0x28, 0xd5, + 0x59, 0xea, 0xa9, 0x27, 0x3c, 0xd5, 0x59, 0xca, 0x54, 0xe1, 0xe0, 0x17, 0x93, 0xb9, 0xcd, 0xcc, + 0xfc, 0x78, 0x69, 0x99, 0x39, 0xdf, 0x98, 0xd3, 0xea, 0xb1, 0xf0, 0xd2, 0x59, 0xb0, 0x6b, 0x9b, + 0x10, 0x1b, 0xa1, 0xb0, 0xef, 0xa4, 0xa5, 0xcd, 0xfc, 0xf8, 0xd4, 0xe2, 0x29, 0xd6, 0x14, 0xa8, + 0x5e, 0xee, 0xed, 0x16, 0x67, 0xbb, 0x55, 0x4d, 0x59, 0x97, 0xcc, 0x60, 0x88, 0x8d, 0x9a, 0x32, + 0xae, 0xeb, 0xe5, 0xd5, 0x89, 0xe6, 0xfa, 0xd1, 0x25, 0x4f, 0x56, 0xb8, 0x41, 0x68, 0x6b, 0xf1, + 0xa3, 0x77, 0xcd, 0xdb, 0x8b, 0x36, 0x19, 0xf9, 0x28, 0x40, 0x85, 0x04, 0xbc, 0x3f, 0xce, 0x54, + 0x1d, 0x08, 0xcd, 0x99, 0x82, 0x6a, 0xaf, 0xa8, 0x28, 0x65, 0x73, 0xb6, 0xa0, 0xde, 0x5c, 0x85, + 0xf2, 0x92, 0xed, 0x34, 0x68, 0x3a, 0x73, 0x9b, 0x69, 0xb3, 0x06, 0x3d, 0xc8, 0x31, 0x73, 0x72, + 0xab, 0x85, 0x51, 0x66, 0x39, 0xec, 0x94, 0x9a, 0x52, 0xeb, 0xb6, 0xcc, 0x62, 0x24, 0x76, 0xb8, + 0x47, 0x76, 0x56, 0x64, 0x3f, 0x46, 0x4f, 0xde, 0xa6, 0x50, 0xf7, 0xb3, 0xe8, 0xee, 0x36, 0x04, + 0x56, 0x39, 0x75, 0x51, 0xbf, 0x15, 0x0e, 0x8d, 0xd4, 0x44, 0xff, 0xea, 0x21, 0x59, 0xaa, 0x98, + 0x7d, 0x4c, 0x41, 0x7c, 0x44, 0xd0, 0xde, 0x5a, 0xfb, 0x75, 0x12, 0xcb, 0xbe, 0x07, 0x7b, 0x74, + 0x86, 0xb2, 0xcb, 0xde, 0x7b, 0xfb, 0x0c, 0x36, 0x9e, 0x17, 0x05, 0x46, 0x02, 0x85, 0xc2, 0xf6, + 0x91, 0xf7, 0xc3, 0x44, 0x8e, 0xcd, 0x19, 0xec, 0xce, 0xb0, 0xd7, 0x09, 0x8e, 0x3c, 0x38, 0x78, + 0x0e, 0xb8, 0xc5, 0x4d, 0x84, 0x14, 0x67, 0x30, 0xee, 0x3f, 0x3d, 0x79, 0x63, 0xc7, 0xe2, 0x7a, + 0x70, 0x53, 0xa3, 0x83, 0xa4, 0x92, 0x71, 0xeb, 0x27, 0xd9, 0xc6, 0x0b, 0xac, 0x69, 0x03, 0x27, + 0x20, 0x1b, 0x86, 0x93, 0x4a, 0x53, 0xf7, 0x4c, 0x6b, 0xc0, 0x8a, 0xd7, 0xf9, 0x0d, 0x6a, 0x8b, + 0x95, 0x7d, 0xc0, 0xae, 0xcd, 0x9d, 0x5c, 0x66, 0x9b, 0x9e, 0xba, 0xdc, 0x7c, 0x03, 0x58, 0xac, + 0x6d, 0x8d, 0x90, 0x76, 0xd2, 0x5f, 0xd2, 0x0a, 0x80, 0x84, 0xe6, 0xcc, 0x02, 0x35, 0xab, 0xb6, + 0x68, 0xde, 0x6a, 0x79, 0xf3, 0x68, 0x4a, 0x1e, 0x1e, 0x0f, 0x8a, 0x6b, 0x2c, 0xed, 0xb3, 0xd0, + 0x98, 0xe8, 0xd4, 0xad, 0x9d, 0xca, 0x2e, 0x3c, 0x47, 0x73, 0xbe, 0xce, 0x5e, 0x8d, 0x7d, 0x0e, + 0x66, 0x53, 0x0a, 0x6d, 0xb8, 0xab, 0xbe, 0xda, 0xba, 0xfd, 0xfe, 0xae, 0x51, 0x6f, 0x9d, 0xd3, + 0x02, 0x17, 0x28, 0x6d, 0xd7, 0xb4, 0xd7, 0xd1, 0x0d, 0x09, 0x49, 0xde, 0xd1, 0x26, 0x02, 0xb5, + 0xb7, 0xdb, 0x8a, 0x7e, 0x08, 0xb4, 0x72, 0x61, 0xf0, 0x6a, 0xaf, 0x62, 0x97, 0x0f, 0xe1, 0x5c, + 0x2b, 0x28, 0x7d, 0x99, 0x68, 0xa5, 0xb7, 0xca, 0xdb, 0x04, 0xb6, 0x7d, 0x8d, 0x0a, 0x10, 0xd6, + 0x5e, 0x59, 0x2f, 0x63, 0xc6, 0x16, 0xfb, 0x66, 0x86, 0x0d, 0xca, 0xc2, 0xd4, 0xcf, 0x1e, 0xf6, + 0x2d, 0xf0, 0x0f, 0xcc, 0xc8, 0xfd, 0xae, 0x34, 0x4a, 0xfc, 0xee, 0x1a, 0xdd, 0x1c, 0x08, 0x6b, + 0x7b, 0xd9, 0x04, 0x69, 0xcb, 0xf0, 0x47, 0x32, 0x78, 0x17, 0xcf, 0x18, 0x6a, 0x59, 0x41, 0xb1, + 0xa2, 0xf0, 0x6f, 0xa8, 0x5a, 0x2a, 0x9d, 0x4e, 0xd4, 0x84, 0x85, 0xf8, 0xb1, 0x68, 0x8e, 0x02, + 0x2f, 0xc0, 0x56, 0x59, 0xa3, 0xd6, 0x0c, 0x05, 0xbf, 0x70, 0x88, 0x8b, 0x8d, 0x92, 0x89, 0x49, + 0xdf, 0x90, 0x92, 0xf8, 0xa3, 0xe3, 0xc4, 0xf7, 0xa8, 0x9a, 0xaa, 0xa4, 0xa0, 0xa7, 0x65, 0xcb, + 0x14, 0x7c, 0x2b, 0x96, 0x8d, 0x27, 0xf4, 0x8b, 0xfa, 0xff, 0xa1, 0xd4, 0x44, 0x1c, 0x90, 0xd3, + 0x24, 0xd3, 0x40, 0x67, 0x71, 0x86, 0x79, 0x14, 0x36, 0x59, 0x43, 0x05, 0xba, 0xfa, 0xc1, 0x94, + 0x6c, 0xe8, 0x7c, 0x94, 0xde, 0x02, 0x26, 0x23, 0x25, 0x5a, 0xec, 0x17, 0xde, 0x07, 0x77, 0x83, + 0x75, 0x4e, 0xac, 0x13, 0x1e, 0xc9, 0x4d, 0xe4, 0x1b, 0x0d, 0x0d, 0x2f, 0x44, 0x6b, 0xb3, 0x29, + 0x07, 0x27, 0x46, 0xa6, 0x79, 0x32, 0x50, 0xb4, 0xaf, 0x05, 0xd9, 0xae, 0xba, 0xee, 0xe4, 0xa4, + 0xe3, 0x39, 0xa7, 0xe4, 0x27, 0xc7, 0xfd, 0x61, 0x5f, 0xc9, 0xbf, 0x8e, 0x2f, 0xf4, 0xcc, 0xa8, + 0x6a, 0x17, 0x4e, 0xf8, 0x9f, 0x2a, 0x2f, 0x40, 0x89, 0xb6, 0x08, 0x06, 0xf1, 0x48, 0x3e, 0x5b, + 0xfd, 0xb9, 0x74, 0x3f, 0xeb, 0x5c, 0x8d, 0x51, 0x56, 0xa0, 0x4a, 0x57, 0x4a, 0xcb, 0x34, 0x32, + 0xf0, 0x71, 0xe0, 0x7c, 0x03, 0xfa, 0xec, 0xf1, 0x6b, 0x2c, 0x7c, 0xbc, 0x97, 0x8e, 0xa9, 0xba, + 0xe1, 0x29, 0x0c, 0x72, 0x15, 0x55, 0xd3, 0xa7, 0xa7, 0x8e, 0xf2, 0xa6, 0x5a, 0xdd, 0xe8, 0x9a, + 0xb1, 0xf6, 0x09, 0x3b, 0xb1, 0xa4, 0xaa, 0x15, 0x8f, 0x9f, 0xe0, 0xb6, 0x4b, 0x21, 0xe1, 0x58, + 0xdb, 0x29, 0x5e, 0x02, 0xa6, 0x3f, 0x9b, 0x08, 0x72, 0x3a, 0xf5, 0xcd, 0x21, 0x2b, 0x5e, 0x50, + 0xc3, 0x19, 0x96, 0xa9, 0xa7, 0x2a, 0xfc, 0x46, 0x35, 0x1a, 0x1b, 0x4f, 0xb1, 0x29, 0xef, 0x51, + 0x82, 0xfa, 0xdc, 0x71, 0x94, 0xe2, 0xc5, 0x20, 0xd2, 0xd6, 0x64, 0x38, 0x09, 0xa4, 0x25, 0xfa, + 0xf6, 0xed, 0xa2, 0xe6, 0x90, 0x6a, 0xe3, 0x82, 0x33, 0x00, 0xfc, 0xd6, 0x5d, 0xc7, 0x42, 0x5d, + 0x32, 0xb4, 0x8f, 0xa9, 0xa8, 0xc6, 0xa1, 0xfb, 0x4a, 0x4e, 0xb2, 0x47, 0x05, 0xc9, 0x8e, 0xce, + 0xe4, 0x3d, 0xb4, 0x37, 0x1e, 0x3e, 0xa2, 0xa9, 0x10, 0xe0, 0x82, 0xec, 0x18, 0x99, 0x24, 0x68, + 0x10, 0x2d, 0x2e, 0x7d, 0xce, 0x73, 0x51, 0x8f, 0x47, 0xc6, 0x7c, 0x85, 0x47, 0x7a, 0xe6, 0xfe, + 0xfe, 0xf1, 0xa7, 0xe3, 0x17, 0x66, 0x6e, 0xa3, 0x67, 0xc3, 0x61, 0xfa, 0x15, 0xba, 0xc7, 0x21, + 0xd0, 0xf5, 0x78, 0x1a, 0xa9, 0x86, 0x55, 0xca, 0x6a, 0x59, 0xea, 0x42, 0xf2, 0x45, 0xa9, 0x19, + 0x27, 0xd9, 0x5f, 0x03, 0x38, 0xce, 0x0f, 0x00, 0x38, 0xa1, 0xc6, 0x91, 0xbc, 0x5d, 0xc7, 0xd9, + 0x03, 0x80, 0x67, 0x1a, 0x03, 0xa3, 0xc0, 0x38, 0x1b, 0x72, 0x10, 0x76, 0xd3, 0xcd, 0x1c, 0x38, + 0x37, 0xe1, 0xfb, 0x18, 0x00, 0x83, 0x24, 0x65, 0xec, 0xe9, 0x09, 0xa3, 0xfa, 0x00, 0x68, 0x75, + 0xd0, 0x6b, 0x12, 0x9a, 0x90, 0x2d, 0x23, 0xd4, 0x6c, 0x42, 0x8d, 0x45, 0x52, 0x6e, 0x7c, 0x7f, + 0xf9, 0xf4, 0x04, 0x18, 0x07, 0x9e, 0x26, 0x0a, 0xc4, 0x29, 0xea, 0xdf, 0xf6, 0xcb, 0x97, 0xd6, + 0xb0, 0xaa, 0xac, 0x8b, 0x6d, 0x4a, 0xc7, 0x4b, 0xf0, 0xd7, 0xae, 0x5e, 0x63, 0x84, 0x5d, 0x7e, + 0x7d, 0x96, 0x96, 0x1a, 0x86, 0x85, 0xc0, 0x3b, 0xec, 0x4a, 0x99, 0x9e, 0x25, 0xe9, 0x26, 0xde, + 0x2f, 0x3b, 0x71, 0x39, 0xc3, 0xdd, 0x20, 0x54, 0xc7, 0x64, 0xe1, 0xef, 0x45, 0xc1, 0x55, 0x89, + 0x6d, 0xfe, 0x48, 0x6f, 0x33, 0xc4, 0x23, 0x42, 0x4c, 0xd5, 0xe6, 0xe6, 0xa7, 0xc4, 0xb4, 0x80, + 0xa7, 0x28, 0x18, 0x51, 0xff, 0x05, 0x72, 0x18, 0x78, 0xc8, 0x47, 0x02, 0x3d, 0x75, 0x60, 0xce, + 0x3b, 0xef, 0xe1, 0xd1, 0x02, 0x6c, 0x99, 0x90, 0x11, 0xb1, 0x4c, 0x14, 0x29, 0x0b, 0x80, 0xe2, + 0x0c, 0x3d, 0x70, 0x4b, 0x4f, 0x5e, 0x11, 0x57, 0x50, 0xbb, 0xbb, 0x2d, 0xdd, 0x69, 0x89, 0xa4, + 0x39, 0xbe, 0x68, 0xfe, 0xbf, 0x22, 0x84, 0x6d, 0xe9, 0x5c, 0x4b, 0xe4, 0x82, 0x37, 0xa0, 0xca, + 0xc8, 0xa9, 0x95, 0x5c, 0x19, 0x1b, 0x96, 0x0d, 0xdf, 0x5d, 0x31, 0xc5, 0xe8, 0x67, 0xbc, 0x6d, + 0x69, 0xb4, 0x65, 0x68, 0xa5, 0x05, 0x88, 0x47, 0xae, 0xe2, 0xe4, 0x08, 0x45, 0x05, 0xa8, 0x60, + 0x29, 0xac, 0xb4, 0x69, 0x26, 0xc9, 0x4f, 0xdf, 0xf8, 0x87, 0x1f, 0x9c, 0xaa, 0xd3, 0x9b, 0xc2, + 0xbb, 0x56, 0x24, 0x7c, 0x9e, 0x1d, 0x1e, 0x6a, 0x6a, 0xa2, 0x91, 0x65, 0x6b, 0xa7, 0x5f, 0x84, + 0xe1, 0x76, 0x79, 0xb4, 0x2c, 0xe0, 0x1e, 0x9f, 0x9e, 0xa8, 0xdf, 0x8a, 0x30, 0x17, 0x8e, 0x4d, + 0x72, 0xa9, 0x46, 0x5a, 0x64, 0x5b, 0x69, 0x08, 0x61, 0x9e, 0x40, 0x37, 0xef, 0xe4, 0x7e, 0x2d, + 0xed, 0x86, 0x01, 0x96, 0xe2, 0x7e, 0xd1, 0xe8, 0x6d, 0xb1, 0x49, 0x84, 0x77, 0x34, 0x7a, 0xcd, + 0x78, 0x56, 0xf2, 0x92, 0x46, 0x09, 0x4b, 0x78, 0x2a, 0xdd, 0xb2, 0xa5, 0xdd, 0xcd, 0x22, 0x86, + 0xce, 0xc1, 0x73, 0xc5, 0x5b, 0x1a, 0xcc, 0x7f, 0xda, 0xb4, 0x51, 0x1f, 0x3e, 0x12, 0x5b, 0x45, + 0x06, 0xd9, 0x74, 0x8b, 0x8b, 0x39, 0x83, 0x31, 0x7a, 0x3f, 0x6b, 0xc8, 0x3c, 0x4f, 0x95, 0x5e, + 0xcf, 0xe7, 0xe1, 0xb2, 0xbb, 0xf6, 0xc3, 0xe6, 0x9c, 0xac, 0x96, 0xd3, 0xbb, 0x6f, 0xce, 0x99, + 0x55, 0x73, 0x22, 0x3a, 0xed, 0xf5, 0x5b, 0x7a, 0x90, 0xa9, 0xd9, 0x09, 0xf4, 0x7d, 0xc2, 0x8b, + 0x7d, 0x47, 0x84, 0x58, 0x43, 0xb7, 0x8f, 0xce, 0xa8, 0xa6, 0x61, 0x98, 0x5a, 0x15, 0x09, 0x38, + 0x4a, 0xf3, 0x2b, 0x7a, 0x83, 0x24, 0x0b, 0x47, 0x39, 0x33, 0x69, 0x0a, 0xb2, 0x2b, 0xd4, 0xa2, + 0x83, 0x04, 0x77, 0xce, 0xd9, 0xfc, 0x7c, 0x7e, 0x74, 0x44, 0x3c, 0x7d, 0xec, 0xf2, 0x1c, 0x3e, + 0x17, 0xdb, 0xc7, 0xd2, 0xd7, 0xa5, 0x82, 0xcc, 0x3e, 0x44, 0x52, 0x01, 0x2e, 0x15, 0x12, 0x15, + 0x3a, 0x9f, 0x4b, 0xd2, 0x78, 0x54, 0x88, 0xa3, 0x5d, 0x72, 0x23, 0x44, 0xbd, 0xbf, 0xde, 0x69, + 0x2e, 0xaf, 0x0c, 0x62, 0x30, 0x62, 0x63, 0x1c, 0xc9, 0xf1, 0xb1, 0xc5, 0x3b, 0xdb, 0x6e, 0x30, + 0x6f, 0x1e, 0x51, 0x1b, 0x5c, 0x38, 0x7e, 0x64, 0xda, 0xca, 0x7b, 0xbf, 0xf2, 0x3e, 0xb8, 0x42, + 0xdd, 0xce, 0x92, 0xac, 0xe4, 0xde, 0xfc, 0xe0, 0x4b, 0xc9, 0x45, 0x16, 0x79, 0x31, 0x80, 0xbd, + 0xad, 0x98, 0xe0, 0xa3, 0x9f, 0xbe, 0xa6, 0x9b, 0x43, 0x8d, 0x18, 0x16, 0x8b, 0x27, 0xea, 0xc5, + 0x22, 0x57, 0xf6, 0x7e, 0x45, 0xe2, 0x6e, 0x7a, 0x6f, 0xef, 0x41, 0x3d, 0x17, 0xd9, 0xfd, 0x7b, + 0x3b, 0xa8, 0x48, 0x16, 0xa6, 0xdc, 0x7c, 0x9d, 0xcb, 0xae, 0x97, 0xf7, 0xe6, 0xd5, 0xa7, 0x42, + 0xa6, 0x1d, 0x77, 0x97, 0xf7, 0xb9, 0x79, 0x35, 0x2d, 0xb7, 0xc2, 0x01, 0x87, 0xa9, 0x8d, 0x1b, + 0xd4, 0x6e, 0x86, 0xa4, 0x7f, 0x42, 0xe0, 0x07, 0x37, 0x87, 0x87, 0x1b, 0x45, 0x4e, 0xc1, 0x1d, + 0xb6, 0x4a, 0x5a, 0x84, 0x72, 0x60, 0x25, 0xeb, 0x5a, 0x25, 0x53, 0xba, 0x5e, 0xfa, 0xa4, 0x88, + 0xec, 0x8b, 0x1e, 0x90, 0x4f, 0x68, 0xa5, 0x4e, 0x6f, 0xb1, 0x50, 0x2b, 0x54, 0xbd, 0x23, 0x62, + 0x19, 0xdb, 0xdb, 0x36, 0x4a, 0x79, 0xcb, 0xa7, 0x0d, 0x15, 0x12, 0xab, 0x63, 0xb5, 0x3b, 0x1b, + 0xd7, 0xdb, 0x32, 0x50, 0x6b, 0xd7, 0x38, 0xeb, 0xdd, 0x68, 0x18, 0x61, 0xd9, 0x70, 0xeb, 0xe8, + 0xe0, 0x94, 0x58, 0x77, 0xd3, 0x79, 0x12, 0x05, 0x01, 0xac, 0x6a, 0xf4, 0xdf, 0x3e, 0xbb, 0xeb, + 0x3c, 0xce, 0xd8, 0xca, 0xbb, 0xf5, 0x31, 0x5c, 0x98, 0x34, 0x75, 0x27, 0x34, 0x0e, 0x58, 0x1c, + 0xc8, 0x11, 0xa0, 0x67, 0x79, 0xe0, 0x12, 0x32, 0x6b, 0x26, 0xfb, 0x06, 0xf1, 0xcc, 0xc9, 0x86, + 0x25, 0xe9, 0x15, 0x73, 0xf1, 0x5f, 0xf1, 0x81, 0x8b, 0xfd, 0x9c, 0x21, 0x7c, 0x2c, 0x85, 0xa1, + 0x14, 0x0b, 0xd0, 0x58, 0x16, 0x0a, 0xd6, 0x07, 0x9a, 0xe0, 0xaf, 0xdf, 0xc7, 0xdc, 0xa8, 0xf8, + 0xcf, 0xc2, 0x68, 0x73, 0xbd, 0x32, 0xd2, 0xd8, 0x9b, 0x33, 0x34, 0x66, 0x4b, 0xd1, 0x94, 0x90, + 0xdb, 0x23, 0x54, 0x8a, 0x0c, 0xb0, 0xc8, 0xc7, 0x15, 0x93, 0x84, 0x37, 0x5b, 0x14, 0xe6, 0x7f, + 0x11, 0x4b, 0xa9, 0x51, 0x76, 0x8f, 0xd3, 0xa0, 0x17, 0x7b, 0x89, 0xc5, 0x5e, 0x29, 0x3d, 0x31, + 0xa8, 0xdb, 0xc6, 0xca, 0x4b, 0x8d, 0x68, 0x0e, 0xc8, 0x1d, 0xa5, 0xdd, 0xb9, 0x4a, 0x3e, 0xd1, + 0x67, 0xf3, 0x48, 0x8c, 0xef, 0xc8, 0x1c, 0xc2, 0xcb, 0x92, 0xac, 0x25, 0x4a, 0xac, 0x93, 0xff, + 0x69, 0x51, 0xad, 0xf0, 0x14, 0x81, 0xfc, 0x7b, 0x21, 0x97, 0x79, 0x8c, 0xc2, 0x21, 0x77, 0x23, + 0x8a, 0xbf, 0x78, 0x61, 0x5f, 0x22, 0xe6, 0x12, 0x6d, 0xf4, 0x9d, 0xef, 0x77, 0x60, 0x74, 0xf4, + 0xd7, 0xa1, 0x30, 0x27, 0xb5, 0x56, 0x3f, 0x04, 0x9a, 0x45, 0x7d, 0x87, 0x5c, 0x96, 0xc2, 0x8f, + 0x35, 0x99, 0x22, 0x15, 0x91, 0x08, 0x97, 0x0a, 0x5d, 0xe3, 0x0f, 0xb4, 0xcf, 0xe4, 0x16, 0xf6, + 0x64, 0x1f, 0x49, 0xd8, 0x19, 0x98, 0x3b, 0x3c, 0x48, 0xc7, 0x40, 0x01, 0x00, 0xd1, 0x3f, 0x34, + 0xa3, 0xe5, 0xd2, 0xcc, 0x29, 0x15, 0x8f, 0x53, 0x48, 0xbc, 0x25, 0x87, 0xcb, 0xde, 0x32, 0x83, + 0xbf, 0xfc, 0x03, 0x1c, 0xc3, 0x39, 0xea, 0xcd, 0x91, 0x70, 0x79, 0x3a, 0x34, 0x79, 0x2b, 0x0b, + 0x46, 0xed, 0xa0, 0xca, 0x3f, 0x5e, 0x25, 0xa8, 0x7d, 0x86, 0x32, 0x43, 0x9c, 0x0d, 0xe8, 0x54, + 0x9e, 0xd7, 0xfa, 0x8f, 0x32, 0x08, 0x7d, 0x04, 0xa5, 0x43, 0x55, 0xf9, 0x64, 0x4d, 0xcc, 0x5f, + 0xe9, 0xd2, 0x82, 0xba, 0x8f, 0x06, 0xa1, 0x64, 0xa3, 0x19, 0xb2, 0xec, 0x2e, 0x4a, 0x6e, 0xf8, + 0x70, 0x80, 0xb5, 0x30, 0x30, 0x3f, 0x02, 0x1e, 0x59, 0x7d, 0x02, 0x21, 0xd3, 0x85, 0xae, 0x7f, + 0xc4, 0x67, 0x3e, 0x6c, 0xb2, 0x03, 0xdd, 0x5d, 0x8f, 0x11, 0x44, 0xe1, 0x35, 0x64, 0xc2, 0xda, + 0xba, 0xa6, 0x74, 0x1b, 0xf3, 0x88, 0x54, 0xc4, 0xf0, 0x11, 0xc9, 0x88, 0xa1, 0xec, 0x57, 0x9e, + 0x8f, 0x14, 0x8a, 0x8f, 0x98, 0x1f, 0xa2, 0x35, 0x12, 0xa4, 0xff, 0x8a, 0xce, 0xef, 0x58, 0x40, + 0xa4, 0x40, 0x6f, 0x71, 0x3b, 0xc3, 0xa9, 0x4a, 0x7e, 0x66, 0xf1, 0xb7, 0x89, 0x75, 0x17, 0xf9, + 0x6a, 0xa4, 0x1d, 0xe6, 0xaf, 0xfa, 0x3b, 0x2c, 0x5c, 0xdd, 0x4c, 0x6a, 0x77, 0x24, 0xb2, 0x1e, + 0x58, 0xba, 0xe2, 0xd9, 0x1c, 0x6d, 0x6f, 0x2f, 0x99, 0xf3, 0x56, 0x30, 0x0a, 0xe4, 0x0c, 0xfd, + 0x90, 0xce, 0x02, 0x2f, 0xbc, 0xd9, 0x22, 0x58, 0xaa, 0xca, 0xb1, 0xb0, 0x87, 0x8a, 0x48, 0x89, + 0x7b, 0x6b, 0xa9, 0xce, 0x04, 0x91, 0x96, 0x38, 0x0b, 0x44, 0xc2, 0x4a, 0x07, 0x2c, 0xe2, 0x22, + 0xc8, 0xee, 0x48, 0xef, 0xbb, 0xfc, 0xaf, 0x55, 0x21, 0x49, 0x25, 0xc9, 0xda, 0xe8, 0x93, 0x0b, + 0xd2, 0x1b, 0x84, 0x30, 0xbc, 0xa2, 0xbd, 0x44, 0x2f, 0xad, 0x23, 0x7d, 0x57, 0x19, 0x28, 0xaf, + 0xb1, 0x1c, 0x6a, 0x6d, 0xbb, 0x8a, 0x6b, 0x2d, 0x49, 0x56, 0xab, 0x23, 0x2f, 0xbd, 0x0a, 0x8b, + 0x87, 0x86, 0x56, 0x43, 0x8d, 0xba, 0x57, 0xc7, 0x42, 0x25, 0xfe, 0xdc, 0x60, 0x24, 0xeb, 0xa0, + 0x0e, 0x48, 0x54, 0xab, 0x2c, 0x5e, 0xb1, 0x3e, 0xca, 0x35, 0x5d, 0x39, 0xcc, 0xb5, 0x77, 0x83, + 0x04, 0x66, 0x81, 0x07, 0xe9, 0x32, 0x57, 0x53, 0x42, 0xdc, 0x22, 0xd7, 0xe5, 0xca, 0x7b, 0x4a, + 0xe6, 0xe3, 0x7e, 0x79, 0x89, 0x30, 0xca, 0xce, 0x25, 0xd7, 0xc5, 0x43, 0xcc, 0x73, 0x03, 0xde, + 0xb0, 0xd5, 0xbc, 0xa4, 0xc1, 0x10, 0x32, 0x64, 0x77, 0x65, 0x06, 0xe3, 0x03, 0xbb, 0x93, 0x0a, + 0x8c, 0x86, 0xde, 0x6e, 0xdd, 0x3a, 0xa3, 0xb0, 0xea, 0xae, 0x19, 0x4f, 0x14, 0xd6, 0x12, 0x85, + 0x2a, 0x7b, 0x9b, 0x12, 0xbd, 0xaa, 0xe5, 0xbe, 0xaf, 0x79, 0xc4, 0x7e, 0xf6, 0x11, 0xaa, 0x2a, + 0xfd, 0x8e, 0x56, 0xf6, 0xd3, 0x5b, 0x57, 0xe7, 0xe2, 0xeb, 0xac, 0x25, 0x58, 0xab, 0x1a, 0xbb, + 0x5a, 0x77, 0x45, 0xcd, 0xfe, 0x2f, 0xe9, 0xef, 0xd7, 0x98, 0x4f, 0x28, 0x69, 0x5f, 0xdc, 0x69, + 0xd5, 0x8c, 0x41, 0x55, 0xc4, 0xd7, 0x35, 0xf1, 0xdb, 0x7a, 0x4b, 0x1a, 0xf9, 0xca, 0x24, 0xb2, + 0x9c, 0x2e, 0xc4, 0xbe, 0x44, 0x8b, 0x1c, 0x08, 0xa0, 0x60, 0xa9, 0xa9, 0x92, 0xab, 0x0d, 0x34, + 0x6a, 0x95, 0x6b, 0xc3, 0x19, 0x19, 0x8a, 0x4a, 0xee, 0xa8, 0x41, 0xdd, 0xbc, 0xaa, 0x82, 0x3c, + 0x1d, 0xed, 0xa7, 0x40, 0xac, 0x06, 0xc1, 0x2a, 0x5b, 0x78, 0xdc, 0x57, 0xfb, 0xb8, 0xd9, 0x81, + 0x02, 0x99, 0xc5, 0x1f, 0xfb, 0xca, 0xb0, 0x0a, 0x9c, 0x83, 0xd0, 0xa2, 0x4f, 0x15, 0x65, 0x45, + 0xdd, 0x42, 0x1a, 0x54, 0xff, 0x85, 0x47, 0x83, 0x7a, 0xb5, 0x58, 0xc8, 0x8d, 0x5f, 0x68, 0x62, + 0xe0, 0x0e, 0x7f, 0xa6, 0xe3, 0xb1, 0x8b, 0x52, 0xb5, 0x65, 0x8a, 0x76, 0x7d, 0xad, 0x5a, 0x91, + 0x71, 0x76, 0x9f, 0x19, 0x02, 0x34, 0x15, 0x23, 0xee, 0x0c, 0xb3, 0x78, 0x1b, 0xf4, 0x82, 0xb7, + 0x8e, 0xf1, 0xe6, 0xd3, 0x25, 0x02, 0x0b, 0xe1, 0x90, 0x73, 0xd7, 0xee, 0xc9, 0x40, 0xd9, 0x30, + 0x40, 0x85, 0x49, 0x2b, 0x6c, 0x6e, 0x69, 0xa1, 0x29, 0x59, 0xbe, 0x25, 0xa7, 0x77, 0xa4, 0xf7, + 0xd2, 0xed, 0x9a, 0x3d, 0xe9, 0x67, 0x42, 0x85, 0xb1, 0xb9, 0xea, 0x75, 0xc0, 0x20, 0x11, 0xda, + 0x70, 0x4b, 0xaf, 0x53, 0xad, 0xd7, 0x65, 0xa7, 0x94, 0x3e, 0x15, 0x1e, 0x56, 0x72, 0x65, 0x58, + 0x9f, 0x83, 0xa6, 0x51, 0xf5, 0x4a, 0x1b, 0x08, 0x1d, 0xee, 0xc7, 0xc0, 0x9b, 0x23, 0x27, 0xc0, + 0x48, 0x96, 0x09, 0xa7, 0x15, 0xd2, 0x58, 0x4a, 0x3f, 0xf9, 0xfc, 0x5b, 0x65, 0xe9, 0x5d, 0x7a, + 0xfb, 0x7c, 0xaa, 0xcc, 0x5f, 0x0b, 0x97, 0x1e, 0xc0, 0xc4, 0xac, 0x0c, 0x29, 0xbf, 0xfe, 0x1d, + 0x38, 0x05, 0x21, 0xe7, 0x11, 0x69, 0x5c, 0x13, 0xa5, 0x5d, 0xab, 0x9f, 0x06, 0x35, 0x4f, 0xb3, + 0x6b, 0xcd, 0x7e, 0x10, 0x5e, 0xdf, 0xa4, 0xc2, 0x3e, 0x5e, 0x36, 0x09, 0xd5, 0x4b, 0xc5, 0x7e, + 0xae, 0xd5, 0xbf, 0xa7, 0x4a, 0xbf, 0x54, 0xf0, 0x6a, 0x58, 0xb3, 0x38, 0x1a, 0xa8, 0x66, 0xff, + 0x03, 0x3e, 0xc4, 0x57, 0x17, 0xef, 0xf0, 0x82, 0x04, 0x3d, 0xc9, 0xc8, 0x93, 0xa7, 0xf4, 0x3a, + 0xa2, 0xa3, 0x42, 0xa5, 0xb4, 0x17, 0xfb, 0x9a, 0x2b, 0x12, 0x6a, 0xb9, 0x61, 0x4d, 0xe2, 0xa8, + 0xaf, 0xb6, 0xd9, 0xe7, 0x6d, 0xee, 0xb6, 0x97, 0x78, 0xc7, 0xc3, 0xa3, 0x19, 0xb3, 0x44, 0x3a, + 0xaa, 0x17, 0x36, 0x44, 0xdb, 0xa7, 0xd6, 0x9f, 0xd1, 0xd4, 0x8a, 0x99, 0x13, 0x18, 0x65, 0x4f, + 0x5b, 0x08, 0x55, 0x35, 0x6e, 0x77, 0x07, 0x2f, 0x11, 0xce, 0xe4, 0x89, 0x3e, 0x43, 0x81, 0xcf, + 0x7e, 0x3d, 0x4c, 0xff, 0x9a, 0x1e, 0x36, 0x4e, 0x36, 0x6c, 0x4a, 0xea, 0x16, 0xf0, 0x25, 0xef, + 0x7e, 0x34, 0x1a, 0x4f, 0x33, 0x75, 0xae, 0x16, 0xd5, 0xc3, 0xab, 0x38, 0x8e, 0x4a, 0x9f, 0x54, + 0x02, 0x28, 0xf1, 0x38, 0x1b, 0x9c, 0x39, 0x74, 0xbc, 0xf5, 0xc5, 0x9e, 0xe5, 0x80, 0xca, 0x86, + 0x75, 0xcf, 0x58, 0xf9, 0xb8, 0xad, 0x7b, 0x34, 0x8a, 0x66, 0x5c, 0xeb, 0xd7, 0x5c, 0xd6, 0x20, + 0x53, 0x7f, 0x21, 0xdd, 0x46, 0x6c, 0xc7, 0xb6, 0xf2, 0x08, 0x11, 0x9b, 0x87, 0x66, 0x81, 0xef, + 0xae, 0x14, 0x3d, 0x0a, 0x95, 0xd2, 0x01, 0xb3, 0xd4, 0x87, 0x2b, 0xf7, 0xf7, 0xb3, 0xbd, 0xbb, + 0xb4, 0x60, 0xc1, 0x45, 0xe7, 0xd9, 0x11, 0x3b, 0x7a, 0xb6, 0xb3, 0x4b, 0xd2, 0xe2, 0xe9, 0x47, + 0xe1, 0x48, 0x84, 0x9a, 0x2f, 0x7d, 0xed, 0x0c, 0x9f, 0xed, 0xe1, 0xb4, 0x47, 0x75, 0xfc, 0x69, + 0x8e, 0xdf, 0x90, 0xa6, 0x7a, 0x59, 0x45, 0xde, 0xba, 0xe9, 0xd0, 0x8d, 0x97, 0x44, 0x24, 0x33, + 0x6e, 0xc1, 0x6b, 0xcc, 0x95, 0xa5, 0xc7, 0xef, 0xb8, 0x18, 0x6a, 0x05, 0x72, 0x2a, 0x74, 0x84, + 0x0a, 0x70, 0x84, 0xc3, 0x95, 0x4e, 0x81, 0xb0, 0xa6, 0x69, 0xe5, 0xe4, 0x6a, 0x3d, 0x69, 0xe3, + 0xda, 0x39, 0xdb, 0xec, 0x8a, 0x84, 0x43, 0xc5, 0x2e, 0x12, 0x1a, 0x29, 0x68, 0x39, 0x89, 0x05, + 0x89, 0xb0, 0x83, 0x42, 0xfe, 0xf6, 0x91, 0x9f, 0xad, 0x8e, 0xf4, 0x35, 0x22, 0xd5, 0xe4, 0xb7, + 0xdf, 0xef, 0xc7, 0x0e, 0x7a, 0x87, 0xad, 0x10, 0x14, 0x5f, 0x32, 0xce, 0x2f, 0xa3, 0x27, 0x8a, + 0x05, 0xde, 0x8f, 0xa2, 0x78, 0x43, 0x5e, 0x9a, 0xab, 0x00, 0x55, 0xa1, 0x29, 0xf8, 0x91, 0xb2, + 0xcb, 0xa3, 0x1c, 0x9d, 0x44, 0xa5, 0x14, 0x72, 0xd4, 0x92, 0x2d, 0xea, 0x4f, 0x6b, 0x01, 0x17, + 0x76, 0x46, 0x6a, 0x10, 0x45, 0x07, 0x4d, 0x45, 0xa9, 0xc8, 0x50, 0xd4, 0xa0, 0xb8, 0x6f, 0x94, + 0x96, 0xec, 0x45, 0xbf, 0xd1, 0x8d, 0xc0, 0xf0, 0xd3, 0x55, 0x5e, 0xb1, 0xbe, 0xe0, 0xe6, 0x5a, + 0x64, 0x6c, 0x83, 0x37, 0x01, 0x5c, 0x5d, 0x1c, 0xf2, 0x06, 0xc3, 0x10, 0x03, 0x39, 0xa2, 0x03, + 0xb8, 0x52, 0x0e, 0xa2, 0x46, 0xde, 0x10, 0x96, 0xfa, 0x4c, 0xf7, 0x10, 0x4b, 0xad, 0xa0, 0x31, + 0x0b, 0x43, 0xd1, 0xee, 0xb0, 0x5d, 0x4d, 0x8b, 0x29, 0x93, 0x95, 0xe7, 0xe4, 0x54, 0x56, 0xa9, + 0x3a, 0x13, 0x55, 0xff, 0xdb, 0x55, 0xdc, 0x48, 0xa7, 0xed, 0x1c, 0xb8, 0xd2, 0x85, 0x1c, 0x0e, + 0xe9, 0xe8, 0x8b, 0x2b, 0x5a, 0x75, 0x34, 0xc8, 0xe6, 0x0d, 0x33, 0x1b, 0xed, 0xb5, 0x87, 0x61, + 0x9e, 0x8f, 0xb6, 0xa9, 0xe7, 0xfd, 0x47, 0x95, 0xdc, 0xe8, 0x06, 0x07, 0xcd, 0xa2, 0xdd, 0xc0, + 0xe6, 0xcf, 0xf0, 0xd9, 0xf5, 0x72, 0x75, 0x59, 0x52, 0x55, 0xab, 0xa9, 0x18, 0xea, 0x63, 0x69, + 0x68, 0x37, 0x51, 0xe4, 0xaf, 0xe8, 0x50, 0x2e, 0x64, 0xdc, 0xe7, 0x1d, 0x39, 0x96, 0x5b, 0x6f, + 0x82, 0xcc, 0x07, 0xa2, 0xb1, 0xb4, 0x1b, 0x84, 0x2f, 0xc2, 0xab, 0x13, 0x80, 0xdf, 0x01, 0x3a, + 0xd2, 0x2f, 0x3d, 0xdd, 0x5c, 0xf1, 0xa8, 0x47, 0xbc, 0xe6, 0xe3, 0x63, 0xbb, 0x0d, 0x3c, 0x70, + 0x22, 0x1d, 0xbe, 0xf4, 0xfa, 0xda, 0xa3, 0x89, 0x69, 0x3b, 0x58, 0x01, 0xed, 0xd0, 0x0e, 0x56, + 0xf0, 0x71, 0x2b, 0x58, 0xfd, 0xe2, 0x6f, 0xa9, 0x79, 0xed, 0xb7, 0x57, 0xbc, 0xf6, 0x77, 0x81, + 0x2b, 0x5a, 0x50, 0xb7, 0xd7, 0x1d, 0x85, 0xc3, 0x03, 0x69, 0x98, 0xcd, 0xae, 0x34, 0x89, 0x6a, + 0x69, 0x04, 0xdd, 0x5e, 0x1c, 0x68, 0xb7, 0xe1, 0x6e, 0xb0, 0x20, 0xf3, 0x49, 0xa9, 0xb4, 0x5a, + 0x69, 0xe2, 0x9f, 0x1d, 0xc6, 0xe3, 0xf9, 0x3d, 0xf2, 0x18, 0xad, 0x18, 0xd7, 0x56, 0x85, 0x34, + 0xfd, 0xbe, 0xe3, 0xd9, 0x37, 0x5c, 0x3b, 0xc5, 0xa8, 0x5e, 0x32, 0x0d, 0xc5, 0x1c, 0x3c, 0x93, + 0xed, 0x0c, 0xf7, 0x2e, 0x2a, 0x2f, 0x6d, 0xe0, 0x10, 0xac, 0x5d, 0x4c, 0x65, 0xf5, 0x40, 0x2f, + 0xb2, 0x1a, 0xf5, 0x82, 0x2a, 0x43, 0xf5, 0xa4, 0xad, 0x17, 0x37, 0xd5, 0x6a, 0xa6, 0x45, 0x35, + 0xd5, 0x0b, 0x1c, 0xb6, 0xeb, 0xf2, 0xa6, 0xbe, 0x14, 0xcb, 0xfb, 0xa1, 0xe2, 0x42, 0xb6, 0x3a, + 0xc3, 0xe2, 0xea, 0xfc, 0x0b, 0xe7, 0x59, 0xb7, 0xfb, 0x6a, 0xbc, 0xed, 0xda, 0x67, 0xce, 0xf7, + 0xa8, 0xe6, 0x4b, 0xe7, 0xbf, 0x62, 0x91, 0xf6, 0x27, 0x97, 0xa1, 0xc1, 0xbe, 0xed, 0x4f, 0xae, + 0x06, 0x0c, 0x6c, 0xc8, 0xaa, 0x8b, 0x80, 0xdb, 0xa8, 0xb8, 0xcc, 0xd9, 0xbe, 0x6b, 0xea, 0x0a, + 0x0c, 0xd6, 0xbf, 0xe3, 0xc2, 0x07, 0xb7, 0x37, 0x5e, 0xfe, 0x76, 0x9a, 0x36, 0x77, 0x7a, 0xbf, + 0xbb, 0x83, 0xda, 0xd5, 0xb1, 0xd5, 0x80, 0x7c, 0x8a, 0x0b, 0xe3, 0xc6, 0x26, 0xfc, 0x3d, 0x9a, + 0xa8, 0x5d, 0x39, 0x37, 0x35, 0xf3, 0x3e, 0xaa, 0x23, 0x38, 0x8c, 0xc4, 0xc6, 0xea, 0xd7, 0x43, + 0x6f, 0xfe, 0x28, 0x17, 0x21, 0x0e, 0x86, 0xc7, 0xfd, 0x7c, 0xb4, 0x8f, 0xc6, 0xc6, 0xe1, 0x61, + 0xa7, 0xc3, 0x4b, 0x38, 0x36, 0xea, 0x4f, 0x0c, 0x1f, 0x81, 0x49, 0xda, 0xd6, 0x7b, 0x55, 0x8f, + 0xc3, 0x42, 0xad, 0x9d, 0x1d, 0x99, 0x59, 0x99, 0x19, 0x55, 0x33, 0x86, 0xbb, 0x17, 0x58, 0x99, + 0x10, 0xeb, 0x6b, 0x41, 0x63, 0x2b, 0x6c, 0x08, 0x8f, 0x7e, 0x25, 0x99, 0x16, 0xa7, 0x30, 0xa3, + 0x23, 0xe5, 0x38, 0x7e, 0x2f, 0x5c, 0xb5, 0xc6, 0xd2, 0x07, 0xb0, 0x14, 0x37, 0x09, 0x37, 0x56, + 0xe4, 0xc1, 0xca, 0x6e, 0x25, 0xd3, 0x88, 0xf3, 0x83, 0xea, 0x3b, 0x07, 0x9d, 0xf8, 0xdd, 0x36, + 0xda, 0xa2, 0xe2, 0x18, 0x19, 0x63, 0x3a, 0xc4, 0xef, 0xce, 0xfb, 0xa8, 0x32, 0x0d, 0x05, 0xdb, + 0x18, 0x54, 0x8b, 0x42, 0x99, 0x74, 0xe2, 0x0f, 0x6d, 0x84, 0x71, 0x76, 0x9f, 0x15, 0x55, 0x62, + 0x55, 0x1f, 0x14, 0x6f, 0xc6, 0xf1, 0x3b, 0x69, 0xd3, 0xfc, 0xd8, 0x42, 0x50, 0x35, 0xd1, 0xd6, + 0x40, 0xa9, 0xfa, 0xb3, 0x56, 0xcf, 0xce, 0x33, 0x2d, 0x2f, 0xc6, 0xca, 0x68, 0xcd, 0x9b, 0xea, + 0x79, 0x4b, 0xca, 0x2f, 0x6c, 0x2b, 0xe1, 0xc5, 0x7e, 0x79, 0xb1, 0x91, 0x3c, 0x3c, 0x66, 0xaa, + 0x1f, 0xcc, 0x50, 0xfa, 0xed, 0x4d, 0x49, 0xf7, 0x86, 0x9c, 0x25, 0xbb, 0xa1, 0x2d, 0x55, 0x7d, + 0xcf, 0x07, 0x52, 0xbb, 0x06, 0x15, 0x68, 0x3a, 0x7b, 0x7b, 0x98, 0x96, 0x6e, 0xa3, 0xb5, 0x30, + 0x1a, 0xe4, 0xb7, 0x57, 0x91, 0x37, 0x19, 0x4b, 0x3f, 0x21, 0x1f, 0xf4, 0x14, 0x63, 0xc6, 0x07, + 0x4a, 0xec, 0xfe, 0xd7, 0x65, 0xc7, 0x7c, 0x34, 0xad, 0xf1, 0x71, 0xff, 0xcf, 0xb5, 0x7b, 0xf9, + 0x10, 0x66, 0xde, 0xbd, 0xb8, 0xb4, 0x07, 0xbe, 0x70, 0xbe, 0x01, 0xd2, 0x6d, 0x6d, 0xe0, 0xc0, + 0xd5, 0x1e, 0xf0, 0xb6, 0x1d, 0xd7, 0x55, 0x9a, 0xe7, 0x5d, 0x36, 0xad, 0xbf, 0x64, 0xe0, 0x09, + 0x5b, 0x02, 0xdc, 0xac, 0xe8, 0xf2, 0x37, 0xf6, 0xae, 0x99, 0x31, 0x63, 0xc0, 0xca, 0x00, 0x75, + 0x1a, 0x2d, 0xfc, 0xe5, 0x03, 0xee, 0x10, 0xba, 0x41, 0x16, 0xc2, 0x09, 0x2b, 0xcf, 0xba, 0x11, + 0x7a, 0x96, 0xcc, 0xba, 0x31, 0xee, 0x01, 0x37, 0x7e, 0x07, 0xb0, 0x00, 0x1b, 0xf7, 0x43, 0x11, + 0x11, 0xa2, 0xb1, 0x1b, 0x9f, 0x83, 0x62, 0x81, 0xd3, 0xc2, 0x5b, 0x2c, 0x59, 0x0d, 0x7c, 0x0e, + 0xdc, 0x54, 0xf3, 0x0c, 0x2d, 0x1c, 0x18, 0xe3, 0x86, 0xe4, 0x5b, 0x31, 0x7e, 0xd7, 0xb4, 0x17, + 0xa1, 0xd9, 0x68, 0xc2, 0x7d, 0x48, 0x7e, 0x8a, 0xdf, 0x5d, 0xb9, 0x99, 0xee, 0x10, 0x15, 0x92, + 0x78, 0x0f, 0xeb, 0xc9, 0x51, 0x3d, 0xe9, 0xb6, 0x9e, 0x44, 0xde, 0xfe, 0x86, 0x4a, 0x03, 0x8f, + 0x80, 0x33, 0x3f, 0xd8, 0xe8, 0xa9, 0xdb, 0x6c, 0x9b, 0x3a, 0xd4, 0xf3, 0x60, 0xc2, 0xd1, 0x72, + 0xc8, 0xee, 0x82, 0x07, 0xc2, 0x13, 0x0b, 0xb9, 0x96, 0x5d, 0x33, 0xb7, 0x09, 0x7c, 0xa5, 0xbb, + 0x57, 0x6a, 0x08, 0xc1, 0x99, 0x52, 0x71, 0x48, 0x9f, 0x03, 0xed, 0x1b, 0x4c, 0x0e, 0xa6, 0x59, + 0x56, 0xdd, 0xef, 0xaf, 0x16, 0x73, 0x45, 0xe3, 0x42, 0x2e, 0x6a, 0xe7, 0x49, 0x0c, 0xa9, 0x78, + 0xa0, 0xe8, 0xa3, 0x64, 0x57, 0x0d, 0xde, 0x84, 0x55, 0x46, 0x54, 0xaa, 0x6d, 0xa1, 0x75, 0x2c, + 0x46, 0x58, 0x65, 0xa3, 0xfd, 0x42, 0xb6, 0x6c, 0x33, 0x25, 0xcf, 0x14, 0x4d, 0xb4, 0x28, 0x21, + 0x61, 0x3e, 0x46, 0x0a, 0x4c, 0xd1, 0x8b, 0x85, 0x41, 0x3a, 0x5f, 0xa6, 0xad, 0xe4, 0x59, 0x7b, + 0xc9, 0x35, 0x5e, 0x58, 0x61, 0x70, 0x3f, 0x35, 0x9d, 0x82, 0x85, 0xba, 0xe6, 0x29, 0x06, 0x17, + 0x1c, 0x65, 0x5c, 0x4b, 0xac, 0x52, 0xed, 0x59, 0xbd, 0x5a, 0x35, 0x9b, 0xac, 0x79, 0xc0, 0x6b, + 0x56, 0x3f, 0x89, 0xca, 0xcf, 0x30, 0xae, 0xa0, 0x88, 0x0a, 0xc3, 0x83, 0x5a, 0xe2, 0x91, 0x52, + 0x69, 0x4c, 0xd7, 0xa6, 0xb3, 0xec, 0x2d, 0xb6, 0x18, 0x4d, 0x8a, 0x6d, 0x7b, 0x9b, 0x71, 0xb4, + 0x58, 0x60, 0xd8, 0x15, 0x5f, 0x08, 0x74, 0x0b, 0x8c, 0xd7, 0xff, 0x2b, 0xf4, 0x83, 0x58, 0xd8, + 0x19, 0xbf, 0x11, 0x96, 0x6f, 0x66, 0x42, 0xa1, 0x85, 0xf1, 0xdc, 0x02, 0x8a, 0x60, 0x05, 0x04, + 0x41, 0x0a, 0xff, 0x6e, 0x87, 0xe4, 0x7e, 0xb6, 0xab, 0x85, 0x69, 0x28, 0xdc, 0x8e, 0x0a, 0x23, + 0xfb, 0xa3, 0x33, 0xc7, 0x1a, 0x2d, 0xa2, 0x47, 0xd6, 0x5d, 0xa9, 0xd9, 0x4e, 0x9e, 0x57, 0xf2, + 0x59, 0x39, 0x0c, 0x30, 0x60, 0x1d, 0x4a, 0xf4, 0x66, 0xe8, 0x73, 0x74, 0x45, 0x61, 0x4b, 0x57, + 0xd6, 0x39, 0x56, 0xc1, 0x3b, 0x07, 0x89, 0x79, 0x75, 0x66, 0x19, 0x05, 0xcb, 0xe1, 0x11, 0x76, + 0x9c, 0x9a, 0xf9, 0x1e, 0x0d, 0x57, 0x50, 0x3f, 0x6a, 0xc9, 0xe4, 0x7a, 0x66, 0x37, 0x81, 0x24, + 0x9f, 0xbb, 0xdf, 0x90, 0xae, 0x16, 0x13, 0xcf, 0xba, 0x89, 0x36, 0xdf, 0x99, 0xdd, 0x6f, 0xb6, + 0x72, 0x12, 0x65, 0xff, 0x86, 0x4e, 0xe4, 0x65, 0xd1, 0xeb, 0x4a, 0xd1, 0xc1, 0xd6, 0xa2, 0xaf, + 0xd5, 0xa2, 0xb3, 0x4a, 0xd1, 0x93, 0xda, 0xd8, 0x78, 0x24, 0xc9, 0xfa, 0xd8, 0x56, 0xec, 0xfe, + 0x92, 0x6c, 0x02, 0x46, 0x58, 0x4f, 0xba, 0x99, 0x71, 0x0b, 0x01, 0xe9, 0x70, 0x36, 0xd3, 0x60, + 0x69, 0x94, 0x11, 0x46, 0x65, 0x47, 0x2e, 0xda, 0x42, 0x5e, 0x8a, 0x9c, 0xcf, 0xad, 0x26, 0x98, + 0x84, 0x8a, 0xe7, 0x05, 0x40, 0xb2, 0x96, 0x0c, 0xe1, 0xb2, 0x5d, 0x3f, 0x5f, 0x5a, 0x76, 0x9d, + 0x58, 0x8a, 0x74, 0x0c, 0x0a, 0xd1, 0xc5, 0x5c, 0xa3, 0x0c, 0x72, 0xdf, 0x1a, 0x9f, 0x5b, 0xa6, + 0xdd, 0x3f, 0x01, 0x18, 0xc5, 0x10, 0x3e, 0xdd, 0x1b, 0xf6, 0xf0, 0x86, 0x42, 0xdc, 0xa0, 0x21, + 0x0f, 0x4d, 0x53, 0xd9, 0x5c, 0x91, 0xd4, 0x1a, 0xb4, 0x40, 0x1d, 0xe6, 0x48, 0x9d, 0x2b, 0x25, + 0x66, 0x89, 0x32, 0xad, 0xcf, 0x2d, 0x1b, 0xe6, 0x8b, 0x28, 0x90, 0x2a, 0x6c, 0x9a, 0xdf, 0xa0, + 0x67, 0xd3, 0x32, 0xab, 0x63, 0xc3, 0xc4, 0x96, 0xf1, 0x04, 0xea, 0xd9, 0x97, 0x4b, 0xcf, 0xc3, + 0xa0, 0x98, 0x39, 0x37, 0x83, 0x54, 0x1b, 0xb7, 0x4a, 0xad, 0x59, 0xde, 0x19, 0x47, 0x01, 0xfc, + 0x41, 0x65, 0x80, 0x2a, 0xd8, 0x6f, 0x01, 0x72, 0x3e, 0x46, 0x7b, 0x2b, 0x30, 0x8b, 0x3c, 0xe1, + 0x36, 0xa8, 0x15, 0x73, 0x55, 0x1d, 0x8f, 0x70, 0x74, 0xc1, 0xd0, 0xc7, 0x45, 0x86, 0x3f, 0x61, + 0x6e, 0x4d, 0x5b, 0xb6, 0x6b, 0x91, 0xd8, 0x2e, 0xdb, 0xad, 0x9e, 0x17, 0x7d, 0x0a, 0x46, 0xa2, + 0x87, 0xee, 0x72, 0xdd, 0xad, 0x98, 0xf6, 0xf0, 0xb0, 0xd2, 0x47, 0x8c, 0x7f, 0x15, 0xb2, 0x00, + 0x16, 0x3d, 0xbd, 0x35, 0x6d, 0x13, 0xfe, 0x91, 0xa7, 0x8e, 0xad, 0x95, 0x54, 0x11, 0x09, 0xdf, + 0x34, 0xf6, 0x80, 0x02, 0x96, 0xe8, 0x6b, 0xb4, 0x13, 0xaf, 0x4b, 0x4f, 0x2a, 0x55, 0xdc, 0x24, + 0xc5, 0x9d, 0x90, 0x32, 0xfc, 0xf4, 0x29, 0x04, 0x1c, 0x14, 0x02, 0x32, 0x09, 0x01, 0x2b, 0xa8, + 0xf5, 0x5f, 0xd9, 0x9f, 0xf0, 0xff, 0xab, 0x3c, 0xc7, 0xc9, 0xc0, 0xa4, 0x89, 0x5e, 0x10, 0xbe, + 0x6e, 0x2b, 0x0b, 0x05, 0x87, 0x03, 0x5e, 0x90, 0xec, 0x86, 0x2b, 0x45, 0xb7, 0x95, 0x46, 0xb1, + 0x59, 0xeb, 0xf1, 0x92, 0xfe, 0x25, 0x8c, 0x7b, 0xca, 0xcf, 0xa5, 0xd5, 0x5c, 0x3d, 0x94, 0x30, + 0x98, 0xd5, 0xdf, 0x7e, 0x06, 0xe0, 0x16, 0x56, 0x18, 0xf8, 0xde, 0x29, 0x22, 0x17, 0x8a, 0x70, + 0x85, 0x18, 0x5a, 0xf1, 0x55, 0x11, 0xc4, 0xb0, 0x87, 0x26, 0x7a, 0xbd, 0x3b, 0xff, 0xc6, 0x87, + 0x8d, 0x25, 0x58, 0xf4, 0x04, 0xda, 0xd3, 0xc2, 0x33, 0x49, 0x6d, 0xb2, 0x4e, 0x67, 0x35, 0x3f, + 0x72, 0xfb, 0x2f, 0xac, 0xf1, 0x09, 0xc5, 0xe8, 0xc1, 0xd6, 0x2d, 0x7b, 0x35, 0x1f, 0x0f, 0xe4, + 0xeb, 0x89, 0x83, 0x3b, 0xfe, 0xf4, 0xd4, 0x75, 0x57, 0x73, 0x4a, 0x39, 0x72, 0x4f, 0x30, 0xc5, + 0x79, 0xa1, 0xa4, 0x40, 0x05, 0x8d, 0xf8, 0x11, 0x43, 0x8f, 0x49, 0x64, 0x46, 0xab, 0xed, 0x4e, + 0x57, 0x29, 0xc6, 0x09, 0x5c, 0xcd, 0x73, 0x8c, 0xa6, 0xe9, 0x7c, 0x67, 0x1b, 0x67, 0xce, 0x77, + 0x68, 0xdc, 0x6c, 0xd9, 0x2f, 0xfb, 0x22, 0x64, 0x1a, 0xa0, 0x40, 0x72, 0x9a, 0x53, 0x5a, 0xf2, + 0x85, 0xcb, 0xdf, 0x88, 0x55, 0xe5, 0x5e, 0xf6, 0xf1, 0x7b, 0xfb, 0x76, 0x27, 0x2a, 0x8d, 0x3c, + 0xae, 0x15, 0x51, 0x7b, 0xb4, 0x1e, 0x70, 0xff, 0x04, 0x36, 0x53, 0xc9, 0xfd, 0x37, 0x51, 0x08, + 0x4c, 0xcc, 0xda, 0xf8, 0x8d, 0xcd, 0xa2, 0x28, 0x33, 0xc9, 0xcc, 0xa0, 0xc3, 0xbb, 0x01, 0xbb, + 0xb6, 0x1a, 0xa7, 0x70, 0x05, 0x34, 0xad, 0x6b, 0xf6, 0xc4, 0x4d, 0xa4, 0xec, 0xf1, 0xa5, 0xd6, + 0xe5, 0x04, 0x5d, 0xd4, 0x6d, 0x41, 0x4a, 0xc2, 0x29, 0xdc, 0x48, 0x8e, 0xe7, 0xd2, 0xfa, 0xe2, + 0xce, 0xf2, 0xf6, 0xcb, 0xbe, 0x5e, 0x62, 0x67, 0x47, 0xb2, 0x2b, 0x76, 0xad, 0xa2, 0xe5, 0xb2, + 0x52, 0x11, 0xcd, 0x69, 0x21, 0x58, 0x97, 0x01, 0x79, 0xf8, 0x65, 0xcd, 0x23, 0xbf, 0x74, 0x70, + 0xb8, 0xac, 0x5c, 0xea, 0x1a, 0xd1, 0xc5, 0x0a, 0x30, 0x36, 0xca, 0x55, 0x0e, 0x86, 0x4e, 0x62, + 0xe2, 0x2a, 0x87, 0x55, 0xaf, 0x72, 0xb8, 0x9c, 0xbd, 0xfd, 0x22, 0xa7, 0x6e, 0xf6, 0x53, 0xf3, + 0xf4, 0xc4, 0xa7, 0x65, 0x67, 0x28, 0x46, 0xa8, 0xe5, 0x9e, 0x4f, 0x27, 0xb3, 0xf0, 0x6c, 0x62, + 0xae, 0x16, 0x7e, 0x71, 0x24, 0x6d, 0x2a, 0x29, 0xc7, 0xe1, 0x21, 0x79, 0x47, 0x77, 0x5d, 0xa9, + 0x03, 0x4a, 0xbe, 0xd2, 0x55, 0x46, 0x51, 0xed, 0x02, 0x50, 0x15, 0xb1, 0x1a, 0x16, 0x47, 0xfb, + 0xf6, 0x98, 0xa3, 0x13, 0x74, 0x6d, 0x0c, 0x8e, 0x16, 0x0f, 0x71, 0x8b, 0xb3, 0x7f, 0xec, 0x72, + 0xd5, 0xdf, 0xff, 0x63, 0x3c, 0x54, 0xeb, 0xb7, 0xa1, 0x63, 0x43, 0xb5, 0x97, 0xb9, 0x55, 0x27, + 0x67, 0x2d, 0x3d, 0xfc, 0x98, 0xd6, 0x19, 0xd5, 0x5f, 0x0e, 0x37, 0xdb, 0x84, 0xea, 0xef, 0x27, + 0xc8, 0x89, 0xb9, 0x18, 0xd2, 0x89, 0xdb, 0xb0, 0x85, 0x0d, 0x56, 0x9b, 0x61, 0x5e, 0xb8, 0x44, + 0x09, 0x75, 0x97, 0x28, 0x7f, 0xc2, 0xc6, 0xf2, 0x2b, 0x8d, 0x2b, 0xb5, 0x29, 0xaf, 0x47, 0x8c, + 0x52, 0x27, 0x2c, 0x84, 0xc5, 0xb2, 0xd9, 0x79, 0xd8, 0x5d, 0x4f, 0x6a, 0x73, 0x71, 0xd4, 0x87, + 0xd9, 0x18, 0x66, 0x7f, 0x5d, 0x3c, 0x18, 0xe5, 0x3c, 0x27, 0xc7, 0x73, 0x8a, 0x33, 0x10, 0xc2, + 0xf0, 0x40, 0x63, 0xfe, 0x1e, 0xc7, 0x2c, 0x79, 0x03, 0x9c, 0x30, 0xba, 0xe0, 0x12, 0xce, 0x3a, + 0xa4, 0xe9, 0x61, 0xbb, 0x23, 0x86, 0x9a, 0xa7, 0x3b, 0xc5, 0x2b, 0x49, 0x71, 0x03, 0x2b, 0x85, + 0x3b, 0xfd, 0xe2, 0x2a, 0x56, 0x38, 0x92, 0x2c, 0xec, 0xbe, 0xf5, 0xe6, 0xf4, 0xb7, 0xba, 0x23, + 0x38, 0xd5, 0xf3, 0x9b, 0x8f, 0x7a, 0xb8, 0xe7, 0x52, 0x7e, 0x34, 0xf2, 0xa5, 0x13, 0xa4, 0xd4, + 0x0d, 0xd1, 0x62, 0x2b, 0x6d, 0xf4, 0xf2, 0x46, 0x5e, 0xa7, 0x84, 0x1c, 0xe5, 0x23, 0xbb, 0xcf, + 0xf4, 0xe1, 0x17, 0xb2, 0x99, 0x0c, 0x05, 0x43, 0x93, 0xb4, 0x6a, 0x52, 0x6f, 0x0e, 0xd3, 0x46, + 0x9f, 0x9a, 0xca, 0xf5, 0xa1, 0xe6, 0xe5, 0x4f, 0x99, 0xec, 0x2f, 0x99, 0x56, 0xe1, 0x77, 0x45, + 0xd0, 0xf5, 0xa8, 0x5b, 0x2e, 0x9c, 0x06, 0xa2, 0x68, 0x61, 0x19, 0xcd, 0x37, 0x1a, 0x87, 0x2f, + 0x83, 0x66, 0x08, 0x7f, 0x3a, 0x68, 0x2c, 0xab, 0x5d, 0x37, 0x2a, 0x2f, 0x8d, 0x7c, 0x2d, 0xbb, + 0x36, 0xf1, 0xce, 0xa3, 0x62, 0xef, 0x5e, 0x16, 0xda, 0x79, 0x01, 0x4f, 0xee, 0xda, 0x95, 0x3a, + 0x14, 0x97, 0x00, 0x6a, 0x2d, 0x15, 0xa3, 0xd5, 0xa1, 0x4c, 0xe0, 0xaf, 0x36, 0x1b, 0x23, 0xa1, + 0x27, 0x10, 0x01, 0x3b, 0x86, 0x97, 0x56, 0x99, 0x67, 0x88, 0xbe, 0x31, 0xea, 0x7e, 0x2a, 0x94, + 0xd6, 0x9e, 0x9e, 0xc2, 0x03, 0x57, 0xb3, 0x8c, 0x9c, 0xa8, 0x8e, 0x39, 0x86, 0x1a, 0x9b, 0x82, + 0x22, 0xda, 0xf6, 0x79, 0x29, 0x4e, 0xa3, 0x16, 0x1d, 0x4f, 0x3d, 0x93, 0xcb, 0xf5, 0x40, 0x42, + 0x69, 0xdf, 0x2e, 0x43, 0xcc, 0x85, 0xd6, 0xa8, 0x65, 0x28, 0x8a, 0xd0, 0xd4, 0x4d, 0x6d, 0xc7, + 0x75, 0xd3, 0xba, 0x84, 0xb0, 0xc9, 0xed, 0x03, 0x2f, 0x5d, 0x11, 0xfe, 0xe2, 0xf9, 0x6a, 0x73, + 0x95, 0x8c, 0xd0, 0xca, 0x55, 0x5f, 0x1d, 0x21, 0xc1, 0x0d, 0x85, 0x05, 0x4d, 0xd2, 0x66, 0x7d, + 0x55, 0xe5, 0xc2, 0x67, 0x16, 0x6c, 0x92, 0x8e, 0xb5, 0xd3, 0x5e, 0x6f, 0x47, 0x36, 0xf5, 0xe2, + 0x84, 0x67, 0xcd, 0xb9, 0x07, 0xc2, 0xff, 0x7d, 0x53, 0xbf, 0x51, 0xeb, 0xa2, 0xa3, 0x5f, 0x0f, + 0x70, 0x43, 0x62, 0x5a, 0xf6, 0x07, 0xf7, 0x94, 0xfc, 0x13, 0xde, 0x89, 0x48, 0xa6, 0xae, 0x63, + 0xdf, 0x3b, 0xdc, 0x2e, 0x9d, 0x1b, 0x8c, 0x5d, 0x52, 0xd4, 0x08, 0x3e, 0x64, 0x85, 0xa6, 0xd9, + 0x84, 0xdc, 0xec, 0xbe, 0x74, 0xbe, 0xc0, 0x95, 0xb3, 0x16, 0x1f, 0x29, 0x74, 0x6c, 0x3a, 0xa9, + 0x26, 0xc0, 0x46, 0x1b, 0x2a, 0x9e, 0xdc, 0x56, 0x5e, 0xfa, 0x2e, 0x89, 0x68, 0x43, 0x62, 0x2d, + 0x65, 0x78, 0xe3, 0xba, 0x83, 0x49, 0x3c, 0xa5, 0xb9, 0x1b, 0x98, 0x32, 0x86, 0x0a, 0x94, 0x2d, + 0xc4, 0xb9, 0x40, 0x83, 0x88, 0x87, 0xbe, 0x4a, 0x4d, 0xcc, 0x6f, 0x8a, 0x70, 0x83, 0x14, 0xf5, + 0xb5, 0xe6, 0x9b, 0xa9, 0xb8, 0xe4, 0xa3, 0x60, 0x35, 0x9a, 0x07, 0x25, 0x89, 0x3d, 0x8a, 0x2c, + 0x80, 0x23, 0xc4, 0xac, 0xa5, 0x9d, 0x42, 0xf1, 0xce, 0x7a, 0x7a, 0x52, 0x87, 0x91, 0x55, 0xde, + 0x43, 0x8c, 0x46, 0x0d, 0x93, 0x29, 0xa7, 0x0a, 0x6a, 0x43, 0x6f, 0x55, 0xff, 0x2c, 0x26, 0x76, + 0x6b, 0xb0, 0xdc, 0x39, 0x3f, 0x4d, 0x01, 0x43, 0xf1, 0x85, 0xb9, 0x12, 0x06, 0x7c, 0x1f, 0xa3, + 0x78, 0x47, 0xc0, 0xda, 0x8e, 0x5c, 0x2e, 0xc7, 0xd2, 0x1c, 0x69, 0xd2, 0xed, 0x28, 0x9f, 0x12, + 0x9e, 0xe3, 0xf0, 0xb0, 0x32, 0x35, 0xb5, 0x9e, 0x86, 0x6e, 0x76, 0x7c, 0xef, 0xc8, 0x70, 0xa4, + 0x74, 0xc6, 0x86, 0x18, 0x7e, 0xf4, 0xa8, 0x93, 0x7e, 0x1f, 0xf6, 0xee, 0xca, 0x70, 0x3c, 0x83, + 0x22, 0x18, 0x18, 0xef, 0xed, 0xd8, 0x81, 0xd3, 0xfc, 0x9c, 0xfc, 0x17, 0xf1, 0x84, 0xf3, 0x13, + 0x48, 0x20, 0x87, 0x46, 0xc1, 0xb8, 0xdb, 0x1f, 0x1c, 0x1e, 0x7e, 0xed, 0xe0, 0x61, 0xdb, 0xf2, + 0xe9, 0x83, 0xaa, 0x77, 0xc6, 0xe5, 0x3d, 0x46, 0x51, 0x79, 0xe0, 0xf6, 0x8f, 0x83, 0x6a, 0x80, + 0x5e, 0x11, 0xb7, 0xb7, 0x3d, 0xb6, 0xef, 0x12, 0x83, 0xce, 0xec, 0x3b, 0xd3, 0x7d, 0xa8, 0x48, + 0x6c, 0x1b, 0x65, 0xc2, 0xb9, 0xa1, 0xd2, 0xe3, 0x9d, 0x5b, 0x33, 0x9b, 0xff, 0x42, 0xfb, 0xfb, + 0x82, 0xe8, 0x93, 0x66, 0xf8, 0x0d, 0x66, 0xf7, 0xa3, 0x36, 0xee, 0x02, 0xe8, 0x6e, 0x53, 0xae, + 0xe8, 0xcf, 0x0c, 0x75, 0x6f, 0x47, 0x29, 0x30, 0xf3, 0x38, 0x46, 0x8a, 0xfa, 0x73, 0x64, 0xc6, + 0xf7, 0x68, 0x01, 0x2b, 0xd2, 0x66, 0xab, 0x46, 0x13, 0x9f, 0x28, 0xab, 0x54, 0x22, 0x8a, 0xa1, + 0x75, 0x16, 0x0a, 0xd1, 0x8e, 0xdd, 0xd3, 0xb2, 0x8e, 0x2c, 0x2e, 0xeb, 0xd5, 0x02, 0x61, 0xd7, + 0xcd, 0x1e, 0x79, 0x3a, 0xa3, 0xa8, 0xc8, 0x14, 0xd5, 0x8d, 0x12, 0x5e, 0xb9, 0x02, 0x32, 0x5f, + 0xb5, 0x04, 0xc8, 0xc2, 0x28, 0xdb, 0xb6, 0xc8, 0x62, 0x89, 0x07, 0xb7, 0x78, 0xbf, 0x3b, 0xef, + 0x53, 0x6c, 0xd6, 0x03, 0x19, 0x2c, 0xfa, 0x80, 0xc4, 0x13, 0x22, 0x15, 0x67, 0x93, 0x3f, 0x3f, + 0x3d, 0xdd, 0x8d, 0x5d, 0x25, 0x91, 0xbf, 0xe0, 0xb6, 0x95, 0x81, 0xa3, 0x29, 0x38, 0x96, 0xa8, + 0x6f, 0x22, 0x9a, 0x39, 0xe8, 0x0f, 0x45, 0x4b, 0xe8, 0x33, 0xaa, 0xe8, 0x73, 0xd9, 0x7c, 0x3d, + 0x6a, 0x7a, 0xab, 0xd7, 0x26, 0x0c, 0x16, 0xae, 0x58, 0x4c, 0xf1, 0x2a, 0x76, 0xb9, 0x5f, 0x8a, + 0x4a, 0x46, 0x7a, 0x45, 0x6b, 0xe1, 0x16, 0x71, 0xad, 0xcb, 0xa0, 0x6f, 0xf3, 0x35, 0xe4, 0x9b, + 0x98, 0x0e, 0x52, 0xe2, 0x9b, 0x2c, 0x32, 0xbf, 0x76, 0x81, 0x8b, 0xfd, 0xc1, 0x85, 0xfc, 0xb2, + 0x87, 0xc8, 0xaf, 0x43, 0xd5, 0xa7, 0xf8, 0x87, 0x3c, 0x3e, 0x00, 0x94, 0x2b, 0xab, 0x5b, 0x04, + 0xbf, 0x53, 0x4e, 0x88, 0xc3, 0x43, 0x33, 0xa2, 0x44, 0x14, 0x55, 0x01, 0x8f, 0x10, 0x2d, 0x31, + 0xed, 0x40, 0xf7, 0x85, 0xab, 0x5e, 0x4b, 0xaf, 0x19, 0xa0, 0xe4, 0x1f, 0x19, 0x8b, 0x81, 0xe4, + 0xea, 0x76, 0xbb, 0x9c, 0xea, 0x3a, 0x90, 0xa4, 0x6e, 0xc1, 0x24, 0x8f, 0xf8, 0x51, 0x87, 0x97, + 0x42, 0xd2, 0x3b, 0x36, 0xe4, 0x53, 0x7a, 0x70, 0x78, 0x58, 0xbc, 0x84, 0x56, 0x19, 0xf2, 0x8b, + 0x47, 0xf7, 0x0d, 0xad, 0xf2, 0x23, 0x9c, 0x32, 0xd6, 0x84, 0x0e, 0x9b, 0xa7, 0x27, 0x9d, 0xb3, + 0x60, 0xf6, 0x23, 0xa4, 0x0e, 0x1f, 0x51, 0xf4, 0xa3, 0x74, 0x0b, 0xd2, 0x6c, 0x2a, 0x65, 0x0d, + 0x1b, 0xf3, 0xe3, 0xb7, 0xbc, 0x90, 0x3d, 0xd4, 0xc6, 0x93, 0x8b, 0xc0, 0xf3, 0x6d, 0x38, 0x28, + 0x34, 0x6d, 0xd8, 0x55, 0x02, 0x7b, 0xd4, 0xa3, 0xb4, 0x03, 0xb9, 0x05, 0xe5, 0xb9, 0x41, 0xa4, + 0x8c, 0x53, 0x5e, 0xcf, 0xb5, 0x8e, 0xf0, 0x8a, 0x3c, 0xba, 0x83, 0xca, 0x10, 0x5f, 0xb4, 0x67, + 0x54, 0x43, 0xc4, 0x6f, 0xcf, 0x49, 0x55, 0x46, 0x18, 0x7b, 0x1e, 0xcf, 0x94, 0x1d, 0xf9, 0x36, + 0xf1, 0xae, 0x6c, 0x65, 0xb4, 0x79, 0x99, 0xef, 0xbf, 0xce, 0x7b, 0x80, 0xe5, 0xfd, 0x38, 0x1b, + 0x1b, 0xe7, 0x3d, 0x74, 0xc5, 0x83, 0x7f, 0x57, 0xd9, 0x3a, 0x18, 0x1b, 0xff, 0x1f, 0x51, 0xf1, + 0x2d, 0x39, 0x45, 0x85, 0x01, 0x00 }; diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 01c62450..9e04ebe5 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -25,28 +25,28 @@ void onMqttConnect(bool sessionPresent) //(re)subscribe to required topics char subuf[38]; - if (mqttDeviceTopic[0] != 0) - { + if (mqttDeviceTopic[0] != 0) { strcpy(subuf, mqttDeviceTopic); mqtt->subscribe(subuf, 0); - strcat(subuf, "/col"); + strcat_P(subuf, PSTR("/col")); mqtt->subscribe(subuf, 0); strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/api"); + strcat_P(subuf, PSTR("/api")); mqtt->subscribe(subuf, 0); } - if (mqttGroupTopic[0] != 0) - { + if (mqttGroupTopic[0] != 0) { strcpy(subuf, mqttGroupTopic); mqtt->subscribe(subuf, 0); - strcat(subuf, "/col"); + strcat_P(subuf, PSTR("/col")); mqtt->subscribe(subuf, 0); strcpy(subuf, mqttGroupTopic); - strcat(subuf, "/api"); + strcat_P(subuf, PSTR("/api")); mqtt->subscribe(subuf, 0); } + usermods.onMqttConnect(sessionPresent); + doPublishMqtt = true; DEBUG_PRINTLN(F("MQTT ready")); } @@ -66,25 +66,24 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties size_t topicPrefixLen = strlen(mqttDeviceTopic); if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) { - topic += topicPrefixLen; + topic += topicPrefixLen; } else { - topicPrefixLen = strlen(mqttGroupTopic); - if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) { - topic += topicPrefixLen; - } else { - // Topic not used here. Probably a usermod subscribed to this topic. - return; - } + topicPrefixLen = strlen(mqttGroupTopic); + if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) { + topic += topicPrefixLen; + } else { + // Non-Wled Topic used here. Probably a usermod subscribed to this topic. + usermods.onMqttMessage(topic, payload); + return; + } } //Prefix is stripped from the topic at this point - if (strcmp(topic, "/col") == 0) - { + if (strcmp_P(topic, PSTR("/col")) == 0) { colorFromDecOrHexString(col, (char*)payload); colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE); - } else if (strcmp(topic, "/api") == 0) - { + } else if (strcmp_P(topic, PSTR("/api")) == 0) { if (payload[0] == '{') { //JSON API DynamicJsonDocument doc(JSON_BUFFER_SIZE); deserializeJson(doc, payload); @@ -94,8 +93,11 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties apireq += (char*)payload; handleSet(nullptr, apireq); } - } else if (strcmp(topic, "") == 0) - { + } else if (strlen(topic) != 0) { + // non standard topic, check with usermods + usermods.onMqttMessage(topic, payload); + } else { + // topmost topic (just wled/MAC) parseMQTTBriPayload(payload); } } @@ -110,24 +112,24 @@ void publishMqtt() char s[10]; char subuf[38]; - sprintf(s, "%u", bri); + sprintf_P(s, PSTR("%u"), bri); strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/g"); + strcat_P(subuf, PSTR("/g")); mqtt->publish(subuf, 0, true, s); - sprintf(s, "#%06X", (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2])); + sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2])); strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/c"); + strcat_P(subuf, PSTR("/c")); mqtt->publish(subuf, 0, true, s); strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/status"); + strcat_P(subuf, PSTR("/status")); mqtt->publish(subuf, 0, true, "online"); char apires[1024]; XML_response(nullptr, apires); strcpy(subuf, mqttDeviceTopic); - strcat(subuf, "/v"); + strcat_P(subuf, PSTR("/v")); mqtt->publish(subuf, 0, true, apires); } @@ -157,7 +159,7 @@ bool initMqtt() if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass); strcpy(mqttStatusTopic, mqttDeviceTopic); - strcat(mqttStatusTopic, "/status"); + strcat_P(mqttStatusTopic, PSTR("/status")); mqtt->setWill(mqttStatusTopic, 0, true, "offline"); mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME); mqtt->connect(); diff --git a/wled00/set.cpp b/wled00/set.cpp index 21179be8..9da32994 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -31,8 +31,8 @@ bool isAsterisksOnly(const char* str, byte maxLen) void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) { - //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX - if (subPage <1 || subPage >7) return; + //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods + if (subPage <1 || subPage >8) return; //WIFI SETTINGS if (subPage == 1) @@ -407,6 +407,57 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) } #endif + //USERMODS + if (subPage == 8) + { + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + JsonObject um = doc.createNestedObject("um"); + + size_t args = request->args(); + uint j=0; + for (size_t i=0; iargName(i); + String value = request->arg(i); + + // POST request parameters are combined as _ + uint8_t umNameEnd = name.indexOf("_"); + if (!umNameEnd) break; // parameter does not contain "_" -> wrong + + JsonObject mod = um[name.substring(0,umNameEnd)]; // get a usermod JSON object + if (mod.isNull()) { + mod = um.createNestedObject(name.substring(0,umNameEnd)); // if it does not exist create it + } + DEBUG_PRINT(name.substring(0,umNameEnd)); + DEBUG_PRINT(":"); + name = name.substring(umNameEnd+1); // remove mod name from string + + // check if parameters represent array + if (name.endsWith("[]")) { + name.replace("[]",""); + if (!mod[name].is()) { + JsonArray ar = mod.createNestedArray(name); + ar.add(value); + j=0; + } else { + mod[name].add(value); + j++; + } + DEBUG_PRINT(name); + DEBUG_PRINT("["); + DEBUG_PRINT(j); + DEBUG_PRINT("] = "); + DEBUG_PRINTLN(value); + } else { + mod.remove(name); // checkboxes get two fields (first is always "off", existence of second depends on checkmark and may be "on") + mod[name] = value; + DEBUG_PRINT(name); + DEBUG_PRINT(" = "); + DEBUG_PRINTLN(value); + } + } + usermods.readFromConfig(um); // force change of usermod parameters + } + if (subPage != 2 && (subPage != 6 || !doReboot)) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init) if (subPage == 4) alexaInit(); } diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 4d07226e..e516be17 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -14,6 +14,11 @@ void UsermodManager::addToJsonInfo(JsonObject& obj) { for (byte i = 0; i < n void UsermodManager::readFromJsonState(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromJsonState(obj); } void UsermodManager::addToConfig(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->addToConfig(obj); } void UsermodManager::readFromConfig(JsonObject& obj) { for (byte i = 0; i < numMods; i++) ums[i]->readFromConfig(obj); } +void UsermodManager::onMqttConnect(bool sessionPresent) { for (byte i = 0; i < numMods; i++) ums[i]->onMqttConnect(sessionPresent); } +bool UsermodManager::onMqttMessage(char* topic, char* payload) { + for (byte i = 0; i < numMods; i++) if (ums[i]->onMqttMessage(topic, payload)) return true; + return false; +} /* * Enables usermods to lookup another Usermod. diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index fb26c93e..1835148f 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -20,7 +20,10 @@ #include "../usermods/buzzer/usermod_v2_buzzer.h" #endif #ifdef USERMOD_SENSORSTOMQTT -#include "usermod_v2_SensorsToMqtt.h" +#include "../usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h" +#endif +#ifdef USERMOD_PIRSWITCH +#include "../usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h" #endif #ifdef USERMOD_MODE_SORT @@ -31,7 +34,7 @@ #ifdef USERMOD_BME280 #include "../usermods/BME280_v2/usermod_bme280.h" #endif -#ifdef USERMOD_FOUR_LINE_DISLAY +#ifdef USERMOD_FOUR_LINE_DISPLAY #include "../usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h" #endif #ifdef USERMOD_ROTARY_ENCODER_UI @@ -50,6 +53,14 @@ #include "../usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h" #endif +#ifdef USERMOD_ANIMATED_STAIRCASE +#include "../usermods/Animated_Staircase/Animated_Staircase.h" +#endif + +#ifdef USERMOD_MULTI_RELAY +#include "../usermods/multi_relay/usermod_multi_relay.h" +#endif + void registerUsermods() { /* @@ -72,28 +83,39 @@ void registerUsermods() #ifdef USERMOD_BME280 usermods.add(new UsermodBME280()); #endif -#ifdef USERMOD_SENSORSTOMQTT + #ifdef USERMOD_SENSORSTOMQTT usermods.add(new UserMod_SensorsToMQTT()); -#endif + #endif + #ifdef USERMOD_PIRSWITCH + usermods.add(new PIRsensorSwitch()); + #endif -#ifdef USERMOD_MODE_SORT + #ifdef USERMOD_MODE_SORT usermods.add(new ModeSortUsermod()); -#endif -#ifdef USERMOD_FOUR_LINE_DISLAY + #endif + #ifdef USERMOD_FOUR_LINE_DISPLAY usermods.add(new FourLineDisplayUsermod()); -#endif -#ifdef USERMOD_ROTARY_ENCODER_UI - usermods.add(new RotaryEncoderUIUsermod()); -#endif -#ifdef USERMOD_AUTO_SAVE - usermods.add(new AutoSaveUsermod()); -#endif + #endif + #ifdef USERMOD_ROTARY_ENCODER_UI + usermods.add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY + #endif + #ifdef USERMOD_AUTO_SAVE + usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY + #endif -#ifdef USERMOD_DHT -usermods.add(new UsermodDHT()); -#endif + #ifdef USERMOD_DHT + usermods.add(new UsermodDHT()); + #endif -#ifdef USERMOD_VL53L0X_GESTURES + #ifdef USERMOD_VL53L0X_GESTURES usermods.add(new UsermodVL53L0XGestures()); -#endif -} \ No newline at end of file + #endif + + #ifdef USERMOD_ANIMATED_STAIRCASE + usermods.add(new Animated_Staircase()); + #endif + + #ifdef USERMOD_MULTI_RELAY + usermods.add(new MultiRelay()); + #endif +} diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index b03c4a36..c02e7fb4 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -314,6 +314,7 @@ String settingsProcessor(const String& var) { if (var == "CSS") { char buf[2048]; + buf[0] = 0; getSettingsJS(optionType, buf); return String(buf); } @@ -365,6 +366,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) #ifdef WLED_ENABLE_DMX // include only if DMX is enabled else if (url.indexOf("dmx") > 0) subPage = 7; #endif + else if (url.indexOf("um") > 0) subPage = 8; } else subPage = 255; //welcome page if (subPage == 1 && wifiLock && otaLock) @@ -386,6 +388,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) case 5: strcpy_P(s, PSTR("Time")); break; case 6: strcpy_P(s, PSTR("Security")); strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break; case 7: strcpy_P(s, PSTR("DMX")); break; + case 8: strcpy_P(s, PSTR("Usermods")); break; } strcat_P(s, PSTR(" settings saved.")); @@ -412,6 +415,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) case 5: request->send_P(200, "text/html", PAGE_settings_time, settingsProcessor); break; case 6: request->send_P(200, "text/html", PAGE_settings_sec , settingsProcessor); break; case 7: request->send_P(200, "text/html", PAGE_settings_dmx , settingsProcessor); break; + case 8: request->send_P(200, "text/html", PAGE_settings_um , settingsProcessor); break; case 255: request->send_P(200, "text/html", PAGE_welcome); break; default: request->send_P(200, "text/html", PAGE_settings , settingsProcessor); }