From 41e13fa6f437cac86916a99cf45ef8ce1a627d44 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 May 2024 17:49:48 -0700 Subject: [PATCH 01/30] Replace random non-ascii-print characters with standard substitutes (#6840) --- esphome/components/api/custom_api_device.h | 2 +- esphome/components/ethernet/ethernet_component.cpp | 8 ++++---- esphome/components/feedback/feedback_cover.cpp | 4 ++-- esphome/components/max6956/max6956.h | 2 +- esphome/components/ntc/sensor.py | 2 +- esphome/components/wifi/wifi_component.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index 9f125a6149..845a35fc54 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -105,7 +105,7 @@ class CustomAPIDevice { /** Subscribe to the state (or attribute state) of an entity from Home Assistant. * * Usage: - *å + * * ```cpp * void setup() override { * subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast"); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 2a4e5cbad3..087a3b1750 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -576,11 +576,11 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { /* * Bit 7 is `RMII Reference Clock Select`. Default is `0`. * KSZ8081RNA: - * 0 - clock input to XI (Pin 8) is 25 MHz for RMII – 25 MHz clock mode. - * 1 - clock input to XI (Pin 8) is 50 MHz for RMII – 50 MHz clock mode. + * 0 - clock input to XI (Pin 8) is 25 MHz for RMII - 25 MHz clock mode. + * 1 - clock input to XI (Pin 8) is 50 MHz for RMII - 50 MHz clock mode. * KSZ8081RND: - * 0 - clock input to XI (Pin 8) is 50 MHz for RMII – 50 MHz clock mode. - * 1 - clock input to XI (Pin 8) is 25 MHz (driven clock only, not a crystal) for RMII – 25 MHz clock mode. + * 0 - clock input to XI (Pin 8) is 50 MHz for RMII - 50 MHz clock mode. + * 1 - clock input to XI (Pin 8) is 25 MHz (driven clock only, not a crystal) for RMII - 25 MHz clock mode. */ if ((phy_control_2 & (1 << 7)) != (1 << 7)) { phy_control_2 |= 1 << 7; diff --git a/esphome/components/feedback/feedback_cover.cpp b/esphome/components/feedback/feedback_cover.cpp index 117c626f58..fa3166ba65 100644 --- a/esphome/components/feedback/feedback_cover.cpp +++ b/esphome/components/feedback/feedback_cover.cpp @@ -244,7 +244,7 @@ void FeedbackCover::loop() { // update current position at requested interval, regardless of who started the movement // so that we also update UI if there was an external movement - // don´t save intermediate positions + // don't save intermediate positions if (now - this->last_publish_time_ > this->update_interval_) { this->publish_state(false); this->last_publish_time_ = now; @@ -274,7 +274,7 @@ void FeedbackCover::control(const CoverCall &call) { if (pos == this->position) { // already at target, - // for covers with built in end stop, if we don´t have sensors we should send the command again + // for covers with built in end stop, if we don't have sensors we should send the command again // to make sure the assumed state is not wrong if (this->has_built_in_endstop_ && ((pos == COVER_OPEN #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/max6956/max6956.h b/esphome/components/max6956/max6956.h index 141164ab30..759fa45b07 100644 --- a/esphome/components/max6956/max6956.h +++ b/esphome/components/max6956/max6956.h @@ -29,7 +29,7 @@ enum MAX6956GPIORegisters { MAX6956_PORT_CONFIG_START = 0x09, // Port Configuration P7, P6, P5, P4 MAX6956_CURRENT_START = 0x12, // Current054 MAX6956_1PORT_VALUE_START = 0x20, // Port 0 only (virtual port, no action) - MAX6956_8PORTS_VALUE_START = 0x44, // 8 ports 4–11 (data bits D0–D7) + MAX6956_8PORTS_VALUE_START = 0x44, // 8 ports 4-11 (data bits D0-D7) }; enum MAX6956GPIOFlag { FLAG_LED = 0x20 }; diff --git a/esphome/components/ntc/sensor.py b/esphome/components/ntc/sensor.py index 06fc55fc43..961511fe00 100644 --- a/esphome/components/ntc/sensor.py +++ b/esphome/components/ntc/sensor.py @@ -100,7 +100,7 @@ def process_calibration(value): elif isinstance(value, list): if len(value) != 3: raise cv.Invalid( - "Steinhart–Hart Calibration must consist of exactly three values" + "Steinhart-Hart Calibration must consist of exactly three values" ) value = cv.Schema([validate_calibration_parameter])(value) a, b, c = calc_steinhart_hart(value) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2f34f2b05b..1359e0b7c5 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -58,7 +58,7 @@ void WiFiComponent::setup() { void WiFiComponent::start() { ESP_LOGCONFIG(TAG, "Starting WiFi..."); - ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str()); + ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str()); this->last_connected_ = millis(); uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time()) : 88491487UL; From 2beb1f033611c0984c3c4d11734e967cc8a1416f Mon Sep 17 00:00:00 2001 From: Simone Rossetto Date: Sat, 1 Jun 2024 04:36:51 +0200 Subject: [PATCH 02/30] Wireguard support for bk72 microcontrollers (#6842) * Bump esp_wireguard to v0.4.1 * add support for bk72 microcontrollers (thanks to kuba2k2) * fix compilation error using esp-idf v5 (thanks to kbx81) * fix crash on vpn disconnection with alive tcp connection (thanks to jefftharris) * Disable ipv6 for bk72 wireguard test * Completely remove ipv6 entry from bk72 wg test --- esphome/components/wireguard/__init__.py | 2 +- platformio.ini | 8 +-- tests/components/wireguard/test.bk72xx.yaml | 59 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 tests/components/wireguard/test.bk72xx.yaml diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 7612c7d964..177ad6d356 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -122,7 +122,7 @@ async def to_code(config): # the '+1' modifier is relative to the device's own address that will # be automatically added to the provided list. cg.add_build_flag(f"-DCONFIG_WIREGUARD_MAX_SRC_IPS={len(allowed_ips) + 1}") - cg.add_library("droscy/esp_wireguard", "0.4.0") + cg.add_library("droscy/esp_wireguard", "0.4.1") await cg.register_component(var, config) diff --git a/platformio.ini b/platformio.ini index fd0ae7c6d8..6b34b2f05d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -94,7 +94,7 @@ lib_deps = ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -Wno-nonnull-compare @@ -124,7 +124,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) esphome/ESP32-audioI2S@2.0.7 ; i2s_audio crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_ESP32 @@ -143,7 +143,7 @@ framework = espidf lib_deps = ${common:idf.lib_deps} espressif/esp32-camera@1.0.0 ; esp32_camera - droscy/esp_wireguard@0.4.0 ; wireguard + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:idf.build_flags} -Wno-nonnull-compare @@ -174,6 +174,8 @@ build_flags = extends = common:arduino platform = libretiny framework = arduino +lib_deps = + droscy/esp_wireguard@0.4.1 ; wireguard build_flags = ${common:arduino.build_flags} -DUSE_LIBRETINY diff --git a/tests/components/wireguard/test.bk72xx.yaml b/tests/components/wireguard/test.bk72xx.yaml new file mode 100644 index 0000000000..85325139a9 --- /dev/null +++ b/tests/components/wireguard/test.bk72xx.yaml @@ -0,0 +1,59 @@ +wifi: + ssid: "MySSID1" + password: "password1" + +time: + - platform: sntp + +wireguard: + address: 172.16.34.100 + netmask: 255.255.255.0 + # NEVER use the following keys for your vpn, they are now public! + private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8= + peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc= + peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60= + peer_endpoint: wg.server.example + peer_persistent_keepalive: 25s + peer_allowed_ips: + - 172.16.34.0/24 + - 192.168.4.0/24 + +binary_sensor: + - platform: wireguard + status: + name: 'WireGuard Status' + enabled: + name: 'WireGuard Enabled' + +sensor: + - platform: wireguard + latest_handshake: + name: 'WireGuard Latest Handshake' + +text_sensor: + - platform: wireguard + address: + name: 'WireGuard Address' + +button: + - platform: template + name: 'Toggle WireGuard' + entity_category: config + on_press: + - if: + condition: wireguard.enabled + then: + - wireguard.disable: + else: + - wireguard.enable: + + - platform: template + name: 'Log WireGuard status' + entity_category: config + on_press: + - if: + condition: wireguard.peer_online + then: + - logger.log: 'wireguard remote peer is online' + else: + - logger.log: 'wireguard remote peer is offline' From 2353b2b5e1e66874a84f5f0e1e2ae0fff5780407 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sat, 1 Jun 2024 18:40:50 -0400 Subject: [PATCH 03/30] Add messages when WiFi and Ethernet components set 'warning' flag. (#6850) --- esphome/components/ethernet/ethernet_component.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 087a3b1750..7672dc2dcb 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -410,7 +410,7 @@ void EthernetComponent::start_connect_() { global_eth_component->ipv6_count_ = 0; #endif /* USE_NETWORK_IPV6 */ this->connect_begin_ = millis(); - this->status_set_warning(); + this->status_set_warning("waiting for IP configuration"); esp_err_t err; err = esp_netif_set_hostname(this->eth_netif_, App.get_name().c_str()); diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 1359e0b7c5..8c40f87879 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -135,7 +135,7 @@ void WiFiComponent::loop() { switch (this->state_) { case WIFI_COMPONENT_STATE_COOLDOWN: { - this->status_set_warning(); + this->status_set_warning("waiting to reconnect"); if (millis() - this->action_started_ > 5000) { if (this->fast_connect_ || this->retry_hidden_) { this->start_connecting(this->sta_[0], false); @@ -146,13 +146,13 @@ void WiFiComponent::loop() { break; } case WIFI_COMPONENT_STATE_STA_SCANNING: { - this->status_set_warning(); + this->status_set_warning("scanning for networks"); this->check_scanning_finished(); break; } case WIFI_COMPONENT_STATE_STA_CONNECTING: case WIFI_COMPONENT_STATE_STA_CONNECTING_2: { - this->status_set_warning(); + this->status_set_warning("associating to network"); this->check_connecting_finished(); break; } From b8d2a6f574e4f49d12d3e677220c9dd92a364aae Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 3 Jun 2024 05:23:49 +0200 Subject: [PATCH 04/30] [sntp] fix for ESP-IDF > 5.0 (#6769) * Make sntp work with ESP-IDF >= 5.0 * Set operatingmode on other than ESP-IDF --------- Co-authored-by: Keith Burzinski --- esphome/components/sntp/sntp_component.cpp | 23 +++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index 6a60e8d5c1..a0e791be75 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -1,16 +1,11 @@ #include "sntp_component.h" #include "esphome/core/log.h" -#if defined(USE_ESP32) || defined(USE_LIBRETINY) -#include "lwip/apps/sntp.h" #ifdef USE_ESP_IDF #include "esp_sntp.h" -#endif -#endif -#ifdef USE_ESP8266 +#elif USE_ESP8266 #include "sntp.h" -#endif -#ifdef USE_RP2040 +#else #include "lwip/apps/sntp.h" #endif @@ -27,14 +22,14 @@ static const char *const TAG = "sntp"; void SNTPComponent::setup() { #ifndef USE_HOST ESP_LOGCONFIG(TAG, "Setting up SNTP..."); -#if defined(USE_ESP32) || defined(USE_LIBRETINY) - if (sntp_enabled()) { - sntp_stop(); +#if defined(USE_ESP_IDF) + if (esp_sntp_enabled()) { + esp_sntp_stop(); } - sntp_setoperatingmode(SNTP_OPMODE_POLL); -#endif -#ifdef USE_ESP8266 + esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL); +#else sntp_stop(); + sntp_setoperatingmode(SNTP_OPMODE_POLL); #endif sntp_setservername(0, strdup(this->server_1_.c_str())); @@ -45,7 +40,7 @@ void SNTPComponent::setup() { sntp_setservername(2, strdup(this->server_3_.c_str())); } #ifdef USE_ESP_IDF - sntp_set_sync_interval(this->get_update_interval()); + esp_sntp_set_sync_interval(this->get_update_interval()); #endif sntp_init(); From 05491e756bb76c43c669009ac7afb5da877b5ee1 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 3 Jun 2024 18:34:47 -0700 Subject: [PATCH 05/30] Avoid unsafe git error when container user and file config volume permissions don't match (#6843) --- docker/Dockerfile | 3 +++ script/setup | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3c661b7e1c..f6234235f7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -100,6 +100,9 @@ RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "a --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ && /platformio_install_deps.py /platformio.ini --libraries +# Avoid unsafe git error when container user and file config volume permissions don't match +RUN git config --system --add safe.directory '/config/*' + # ======================= docker-type image ======================= FROM base AS docker diff --git a/script/setup b/script/setup index 1a18a6a9ea..aeb1b39bc1 100755 --- a/script/setup +++ b/script/setup @@ -13,11 +13,6 @@ if [ ! -n "$DEVCONTAINER" ] && [ ! -n "$VIRTUAL_ENV" ] && [ ! "$ESPHOME_NO_VENV" source $location fi -# Avoid unsafe git error when running inside devcontainer -if [ -n "$DEVCONTAINER" ]; then - git config --global --add safe.directory "$PWD" -fi - pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt -r requirements_dev.txt pip3 install setuptools wheel pip3 install -e ".[dev,test,displays]" --config-settings editable_mode=compat From 78b48209aa2456e05bc2c94357e58809d9c7403f Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 3 Jun 2024 19:57:05 -0700 Subject: [PATCH 06/30] Add Ethernet MAC address to ethernet_info (#6835) --- .../ethernet/ethernet_component.cpp | 54 +++++++++++++------ .../components/ethernet/ethernet_component.h | 4 ++ .../ethernet_info_text_sensor.cpp | 1 + .../ethernet_info/ethernet_info_text_sensor.h | 7 +++ .../components/ethernet_info/text_sensor.py | 11 ++++ tests/components/ethernet_info/common.yaml | 2 + 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 7672dc2dcb..6bb9732fef 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -28,6 +28,13 @@ EthernetComponent *global_eth_component; // NOLINT(cppcoreguidelines-avoid-non- return; \ } +#define ESPHL_ERROR_CHECK_RET(err, message, ret) \ + if ((err) != ESP_OK) { \ + ESP_LOGE(TAG, message ": (%d) %s", err, esp_err_to_name(err)); \ + this->mark_failed(); \ + return ret; \ + } + EthernetComponent::EthernetComponent() { global_eth_component = this; } void EthernetComponent::setup() { @@ -498,22 +505,9 @@ void EthernetComponent::dump_connect_params_() { } #endif /* USE_NETWORK_IPV6 */ - esp_err_t err; - - uint8_t mac[6]; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_MAC_ADDR, &mac); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_MAC error"); - ESP_LOGCONFIG(TAG, " MAC Address: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - eth_duplex_t duplex_mode; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_DUPLEX_MODE, &duplex_mode); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_DUPLEX_MODE error"); - ESP_LOGCONFIG(TAG, " Is Full Duplex: %s", YESNO(duplex_mode == ETH_DUPLEX_FULL)); - - eth_speed_t speed; - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_SPEED, &speed); - ESPHL_ERROR_CHECK(err, "ETH_CMD_G_SPEED error"); - ESP_LOGCONFIG(TAG, " Link Speed: %u", speed == ETH_SPEED_100M ? 100 : 10); + ESP_LOGCONFIG(TAG, " MAC Address: %s", this->get_eth_mac_address_pretty().c_str()); + ESP_LOGCONFIG(TAG, " Is Full Duplex: %s", YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL)); + ESP_LOGCONFIG(TAG, " Link Speed: %u", this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); } #ifdef USE_ETHERNET_SPI @@ -546,6 +540,34 @@ std::string EthernetComponent::get_use_address() const { void EthernetComponent::set_use_address(const std::string &use_address) { this->use_address_ = use_address; } +void EthernetComponent::get_eth_mac_address_raw(uint8_t *mac) { + esp_err_t err; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_MAC_ADDR, mac); + ESPHL_ERROR_CHECK(err, "ETH_CMD_G_MAC error"); +} + +std::string EthernetComponent::get_eth_mac_address_pretty() { + uint8_t mac[6]; + get_mac_address_raw(mac); + return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +eth_duplex_t EthernetComponent::get_duplex_mode() { + esp_err_t err; + eth_duplex_t duplex_mode; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_DUPLEX_MODE, &duplex_mode); + ESPHL_ERROR_CHECK_RET(err, "ETH_CMD_G_DUPLEX_MODE error", ETH_DUPLEX_HALF); + return duplex_mode; +} + +eth_speed_t EthernetComponent::get_link_speed() { + esp_err_t err; + eth_speed_t speed; + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_G_SPEED, &speed); + ESPHL_ERROR_CHECK_RET(err, "ETH_CMD_G_SPEED error", ETH_SPEED_10M); + return speed; +} + bool EthernetComponent::powerdown() { ESP_LOGI(TAG, "Powering down ethernet PHY"); if (this->phy_ == nullptr) { diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 3705e3e06a..e57aa5fe12 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -74,6 +74,10 @@ class EthernetComponent : public Component { network::IPAddress get_dns_address(uint8_t num); std::string get_use_address() const; void set_use_address(const std::string &use_address); + void get_eth_mac_address_raw(uint8_t *mac); + std::string get_eth_mac_address_pretty(); + eth_duplex_t get_duplex_mode(); + eth_speed_t get_link_speed(); bool powerdown(); protected: diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index c8b2b5885b..329fb9113a 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp @@ -10,6 +10,7 @@ static const char *const TAG = "ethernet_info"; void IPAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo IPAddress", this); } void DNSAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo DNS Address", this); } +void MACAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo MAC Address", this); } } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index 82a7dcf56e..94eed886e5 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.h +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.h @@ -59,6 +59,13 @@ class DNSAddressEthernetInfo : public PollingComponent, public text_sensor::Text std::string last_results_; }; +class MACAddressEthernetInfo : public Component, public text_sensor::TextSensor { + public: + void setup() override { this->publish_state(ethernet::global_eth_component->get_eth_mac_address_pretty()); } + std::string unique_id() override { return get_mac_address() + "-ethernetinfo-mac"; } + void dump_config() override; +}; + } // namespace ethernet_info } // namespace esphome diff --git a/esphome/components/ethernet_info/text_sensor.py b/esphome/components/ethernet_info/text_sensor.py index 292673c182..a545475870 100644 --- a/esphome/components/ethernet_info/text_sensor.py +++ b/esphome/components/ethernet_info/text_sensor.py @@ -4,6 +4,7 @@ from esphome.components import text_sensor from esphome.const import ( CONF_IP_ADDRESS, CONF_DNS_ADDRESS, + CONF_MAC_ADDRESS, ENTITY_CATEGORY_DIAGNOSTIC, ) @@ -19,6 +20,10 @@ DNSAddressEthernetInfo = ethernet_info_ns.class_( "DNSAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent ) +MACAddressEthernetInfo = ethernet_info_ns.class_( + "MACAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent +) + CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema( @@ -36,6 +41,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( DNSAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC ).extend(cv.polling_component_schema("1s")), + cv.Optional(CONF_MAC_ADDRESS): text_sensor.text_sensor_schema( + MACAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC + ), } ) @@ -51,3 +59,6 @@ async def to_code(config): if conf := config.get(CONF_DNS_ADDRESS): dns_info = await text_sensor.new_text_sensor(config[CONF_DNS_ADDRESS]) await cg.register_component(dns_info, config[CONF_DNS_ADDRESS]) + if conf := config.get(CONF_MAC_ADDRESS): + mac_info = await text_sensor.new_text_sensor(config[CONF_MAC_ADDRESS]) + await cg.register_component(mac_info, config[CONF_MAC_ADDRESS]) diff --git a/tests/components/ethernet_info/common.yaml b/tests/components/ethernet_info/common.yaml index dade4d7ca5..d9a6f515b1 100644 --- a/tests/components/ethernet_info/common.yaml +++ b/tests/components/ethernet_info/common.yaml @@ -17,3 +17,5 @@ text_sensor: name: IP Address dns_address: name: DNS Address + mac_address: + name: MAC Address From cdf83c5d8c1f8ff99d77b63b04177d253feecbb3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:09:46 +1000 Subject: [PATCH 07/30] Add host time platform; remove host support from sntp. (#6854) --- CODEOWNERS | 3 +- esphome/components/host/__init__.py | 2 +- esphome/components/host/time/__init__.py | 20 +++++++++++ esphome/components/host/time/host_time.h | 15 +++++++++ esphome/components/sntp/sntp_component.cpp | 4 +-- esphome/components/sntp/time.py | 39 ++++++++++++++++------ tests/components/host/common.yaml | 7 +--- tests/components/sntp/test.bk72xx.yaml | 1 + 8 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 esphome/components/host/time/__init__.py create mode 100644 esphome/components/host/time/host_time.h create mode 100644 tests/components/sntp/test.bk72xx.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 0dc5339193..82f61c3b80 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -167,7 +167,8 @@ esphome/components/homeassistant/* @OttoWinter esphome/components/honeywell_hih_i2c/* @Benichou34 esphome/components/honeywellabp/* @RubyBailey esphome/components/honeywellabp2_i2c/* @jpfaff -esphome/components/host/* @esphome/core +esphome/components/host/* @clydebarrow @esphome/core +esphome/components/host/time/* @clydebarrow esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M esphome/components/htu31d/* @betterengineering diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 3bd3b6b172..39e418c9ea 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -16,7 +16,7 @@ from .const import KEY_HOST # force import gpio to register pin schema from .gpio import host_pin_to_code # noqa -CODEOWNERS = ["@esphome/core"] +CODEOWNERS = ["@esphome/core", "@clydebarrow"] AUTO_LOAD = ["network"] diff --git a/esphome/components/host/time/__init__.py b/esphome/components/host/time/__init__.py new file mode 100644 index 0000000000..76a88d98a1 --- /dev/null +++ b/esphome/components/host/time/__init__.py @@ -0,0 +1,20 @@ +import esphome.codegen as cg +from esphome.const import CONF_ID +import esphome.config_validation as cv +from esphome.components import time as time_ + +CODEOWNERS = ["@clydebarrow"] + +time_ns = cg.esphome_ns.namespace("host") +HostTime = time_ns.class_("HostTime", time_.RealTimeClock) +CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HostTime), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await time_.register_time(var, config) diff --git a/esphome/components/host/time/host_time.h b/esphome/components/host/time/host_time.h new file mode 100644 index 0000000000..4f1473b809 --- /dev/null +++ b/esphome/components/host/time/host_time.h @@ -0,0 +1,15 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/time/real_time_clock.h" + +namespace esphome { +namespace host { + +class HostTime : public time::RealTimeClock { + public: + void update() override {} +}; + +} // namespace host +} // namespace esphome diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index a0e791be75..4ded98d483 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -20,7 +20,6 @@ namespace sntp { static const char *const TAG = "sntp"; void SNTPComponent::setup() { -#ifndef USE_HOST ESP_LOGCONFIG(TAG, "Setting up SNTP..."); #if defined(USE_ESP_IDF) if (esp_sntp_enabled()) { @@ -44,7 +43,6 @@ void SNTPComponent::setup() { #endif sntp_init(); -#endif } void SNTPComponent::dump_config() { ESP_LOGCONFIG(TAG, "SNTP Time:"); @@ -54,7 +52,7 @@ void SNTPComponent::dump_config() { ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str()); } void SNTPComponent::update() { -#if !defined(USE_ESP_IDF) && !defined(USE_HOST) +#if !defined(USE_ESP_IDF) // force resync if (sntp_enabled()) { sntp_stop(); diff --git a/esphome/components/sntp/time.py b/esphome/components/sntp/time.py index b1362f5421..7cc82e3dff 100644 --- a/esphome/components/sntp/time.py +++ b/esphome/components/sntp/time.py @@ -2,24 +2,41 @@ from esphome.components import time as time_ import esphome.config_validation as cv import esphome.codegen as cg from esphome.core import CORE -from esphome.const import CONF_ID, CONF_SERVERS - +from esphome.const import ( + CONF_ID, + CONF_SERVERS, + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_RTL87XX, + PLATFORM_BK72XX, +) DEPENDENCIES = ["network"] sntp_ns = cg.esphome_ns.namespace("sntp") SNTPComponent = sntp_ns.class_("SNTPComponent", time_.RealTimeClock) - DEFAULT_SERVERS = ["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org"] -CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(SNTPComponent), - cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): cv.All( - cv.ensure_list(cv.Any(cv.domain, cv.hostname)), cv.Length(min=1, max=3) - ), - } -).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.All( + time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SNTPComponent), + cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): cv.All( + cv.ensure_list(cv.Any(cv.domain, cv.hostname)), cv.Length(min=1, max=3) + ), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.only_on( + [ + PLATFORM_ESP32, + PLATFORM_ESP8266, + PLATFORM_RP2040, + PLATFORM_BK72XX, + PLATFORM_RTL87XX, + ] + ), +) async def to_code(config): diff --git a/tests/components/host/common.yaml b/tests/components/host/common.yaml index 3d14c190a6..fca0c5d597 100644 --- a/tests/components/host/common.yaml +++ b/tests/components/host/common.yaml @@ -1,15 +1,10 @@ time: - - platform: sntp + - platform: host id: esptime timezone: Australia/Sydney logger: level: VERBOSE - logs: - lvgl: INFO - display: DEBUG - sensor: INFO - vnc: DEBUG host: mac_address: "62:23:45:AF:B3:DD" diff --git a/tests/components/sntp/test.bk72xx.yaml b/tests/components/sntp/test.bk72xx.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/sntp/test.bk72xx.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 2d56d8d84feb8df4341725bfe0a409a44b5305a8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:10:44 -0500 Subject: [PATCH 08/30] [wireguard] Implement workaround for crash on IDF 5+ (#6846) --- esphome/components/wireguard/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 177ad6d356..5d5f620b51 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -7,7 +7,10 @@ from esphome.const import ( CONF_TIME_ID, CONF_ADDRESS, CONF_REBOOT_TIMEOUT, + KEY_CORE, + KEY_FRAMEWORK_VERSION, ) +from esphome.components.esp32 import CORE, add_idf_sdkconfig_option from esphome.components import time from esphome.core import TimePeriod from esphome import automation @@ -117,6 +120,13 @@ async def to_code(config): if config[CONF_REQUIRE_CONNECTION_TO_PROCEED]: cg.add(var.disable_auto_proceed()) + # Workaround for crash on IDF 5+ + # See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651 + if CORE.using_esp_idf and CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version( + 5, 0, 0 + ): + add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True) + # This flag is added here because the esp_wireguard library statically # set the size of its allowed_ips list at compile time using this value; # the '+1' modifier is relative to the device's own address that will From eb75778f84e32eed1f5a497471f86bb964906166 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:18:20 -0500 Subject: [PATCH 09/30] [improv_serial] Fix for IDF 4.4.7 (#6855) --- esphome/components/improv_serial/improv_serial_component.cpp | 1 + esphome/components/improv_serial/improv_serial_component.h | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 40297bee68..2937720496 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 default: diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index 8583d0762b..f737f93d86 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -17,6 +17,7 @@ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ defined(USE_ESP32_VARIANT_ESP32H2) #include +#include #endif #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include From 69d38f61371f4f0548b50bedd1ca48784fa51028 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:02:18 +1200 Subject: [PATCH 10/30] [ft5x06] Interrupt pin and code quality improvements (#6851) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- .../components/ft5x06/touchscreen/__init__.py | 8 +- .../ft5x06/touchscreen/ft5x06_touchscreen.cpp | 102 ++++++++++++++++++ .../ft5x06/touchscreen/ft5x06_touchscreen.h | 94 ++-------------- 3 files changed, 119 insertions(+), 85 deletions(-) create mode 100644 esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp diff --git a/esphome/components/ft5x06/touchscreen/__init__.py b/esphome/components/ft5x06/touchscreen/__init__.py index adeeac0d1a..4ceb50c709 100644 --- a/esphome/components/ft5x06/touchscreen/__init__.py +++ b/esphome/components/ft5x06/touchscreen/__init__.py @@ -1,8 +1,9 @@ +from esphome import pins import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, touchscreen -from esphome.const import CONF_ID +from esphome.const import CONF_ID, CONF_INTERRUPT_PIN from .. import ft5x06_ns FT5x06ButtonListener = ft5x06_ns.class_("FT5x06ButtonListener") @@ -16,6 +17,7 @@ FT5x06Touchscreen = ft5x06_ns.class_( CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(FT5x06Touchscreen), + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ).extend(i2c.i2c_device_schema(0x48)) @@ -24,3 +26,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await i2c.register_i2c_device(var, config) await touchscreen.register_touchscreen(var, config) + + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + pin = await cg.gpio_pin_expression(interrupt_pin) + cg.add(var.set_interrupt_pin(pin)) diff --git a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp new file mode 100644 index 0000000000..bd603fdc10 --- /dev/null +++ b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp @@ -0,0 +1,102 @@ +#include "ft5x06_touchscreen.h" + +#include "esphome/core/log.h" + +namespace esphome { +namespace ft5x06 { + +static const char *const TAG = "ft5x06.touchscreen"; + +void FT5x06Touchscreen::setup() { + ESP_LOGCONFIG(TAG, "Setting up FT5x06 Touchscreen..."); + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP); + this->interrupt_pin_->setup(); + this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE); + } + + // wait 200ms after reset. + this->set_timeout(200, [this] { this->continue_setup_(); }); +} + +void FT5x06Touchscreen::continue_setup_() { + uint8_t data[4]; + if (!this->set_mode_(FT5X06_OP_MODE)) + return; + + if (!this->err_check_(this->read_register(FT5X06_VENDOR_ID_REG, data, 1), "Read Vendor ID")) + return; + switch (data[0]) { + case FT5X06_ID_1: + case FT5X06_ID_2: + case FT5X06_ID_3: + this->vendor_id_ = (VendorId) data[0]; + ESP_LOGD(TAG, "Read vendor ID 0x%X", data[0]); + break; + + default: + ESP_LOGE(TAG, "Unknown vendor ID 0x%X", data[0]); + this->mark_failed(); + return; + } + // reading the chip registers to get max x/y does not seem to work. + if (this->display_ != nullptr) { + if (this->x_raw_max_ == this->x_raw_min_) { + this->x_raw_max_ = this->display_->get_native_width(); + } + if (this->y_raw_max_ == this->y_raw_min_) { + this->y_raw_max_ = this->display_->get_native_height(); + } + } + ESP_LOGCONFIG(TAG, "FT5x06 Touchscreen setup complete"); +} + +void FT5x06Touchscreen::update_touches() { + uint8_t touch_cnt; + uint8_t data[MAX_TOUCHES][6]; + + if (!this->read_byte(FT5X06_TD_STATUS, &touch_cnt) || touch_cnt > MAX_TOUCHES) { + ESP_LOGW(TAG, "Failed to read status"); + return; + } + if (touch_cnt == 0) + return; + + if (!this->read_bytes(FT5X06_TOUCH_DATA, (uint8_t *) data, touch_cnt * 6)) { + ESP_LOGW(TAG, "Failed to read touch data"); + return; + } + for (uint8_t i = 0; i != touch_cnt; i++) { + uint8_t status = data[i][0] >> 6; + uint8_t id = data[i][2] >> 3; + uint16_t x = encode_uint16(data[i][0] & 0x0F, data[i][1]); + uint16_t y = encode_uint16(data[i][2] & 0xF, data[i][3]); + + ESP_LOGD(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y); + if (status == 0 || status == 2) { + this->add_raw_touch_position_(id, x, y); + } + } +} + +void FT5x06Touchscreen::dump_config() { + ESP_LOGCONFIG(TAG, "FT5x06 Touchscreen:"); + ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_); + ESP_LOGCONFIG(TAG, " Vendor ID: 0x%X", (int) this->vendor_id_); +} + +bool FT5x06Touchscreen::err_check_(i2c::ErrorCode err, const char *msg) { + if (err != i2c::ERROR_OK) { + this->mark_failed(); + ESP_LOGE(TAG, "%s failed - err 0x%X", msg, err); + return false; + } + return true; +} +bool FT5x06Touchscreen::set_mode_(FTMode mode) { + return this->err_check_(this->write_register(FT5X06_MODE_REG, (uint8_t *) &mode, 1), "Set mode"); +} + +} // namespace ft5x06 +} // namespace esphome diff --git a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h index 7ddd2e44d7..23e5a0c49f 100644 --- a/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h +++ b/esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.h @@ -3,14 +3,12 @@ #include "esphome/components/i2c/i2c.h" #include "esphome/components/touchscreen/touchscreen.h" #include "esphome/core/component.h" +#include "esphome/core/gpio.h" #include "esphome/core/hal.h" -#include "esphome/core/log.h" namespace esphome { namespace ft5x06 { -static const char *const TAG = "ft5x06.touchscreen"; - enum VendorId { FT5X06_ID_UNKNOWN = 0, FT5X06_ID_1 = 0x51, @@ -39,91 +37,19 @@ static const size_t MAX_TOUCHES = 5; // max number of possible touches reported class FT5x06Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice { public: - void setup() override { - esph_log_config(TAG, "Setting up FT5x06 Touchscreen..."); - // wait 200ms after reset. - this->set_timeout(200, [this] { this->continue_setup_(); }); - } + void setup() override; + void dump_config() override; + void update_touches() override; - void continue_setup_(void) { - uint8_t data[4]; - if (!this->set_mode_(FT5X06_OP_MODE)) - return; - - if (!this->err_check_(this->read_register(FT5X06_VENDOR_ID_REG, data, 1), "Read Vendor ID")) - return; - switch (data[0]) { - case FT5X06_ID_1: - case FT5X06_ID_2: - case FT5X06_ID_3: - this->vendor_id_ = (VendorId) data[0]; - esph_log_d(TAG, "Read vendor ID 0x%X", data[0]); - break; - - default: - esph_log_e(TAG, "Unknown vendor ID 0x%X", data[0]); - this->mark_failed(); - return; - } - // reading the chip registers to get max x/y does not seem to work. - if (this->display_ != nullptr) { - if (this->x_raw_max_ == this->x_raw_min_) { - this->x_raw_max_ = this->display_->get_native_width(); - } - if (this->y_raw_max_ == this->y_raw_min_) { - this->y_raw_max_ = this->display_->get_native_height(); - } - } - esph_log_config(TAG, "FT5x06 Touchscreen setup complete"); - } - - void update_touches() override { - uint8_t touch_cnt; - uint8_t data[MAX_TOUCHES][6]; - - if (!this->read_byte(FT5X06_TD_STATUS, &touch_cnt) || touch_cnt > MAX_TOUCHES) { - esph_log_w(TAG, "Failed to read status"); - return; - } - if (touch_cnt == 0) - return; - - if (!this->read_bytes(FT5X06_TOUCH_DATA, (uint8_t *) data, touch_cnt * 6)) { - esph_log_w(TAG, "Failed to read touch data"); - return; - } - for (uint8_t i = 0; i != touch_cnt; i++) { - uint8_t status = data[i][0] >> 6; - uint8_t id = data[i][2] >> 3; - uint16_t x = encode_uint16(data[i][0] & 0x0F, data[i][1]); - uint16_t y = encode_uint16(data[i][2] & 0xF, data[i][3]); - - esph_log_d(TAG, "Read %X status, id: %d, pos %d/%d", status, id, x, y); - if (status == 0 || status == 2) { - this->add_raw_touch_position_(id, x, y); - } - } - } - - void dump_config() override { - esph_log_config(TAG, "FT5x06 Touchscreen:"); - esph_log_config(TAG, " Address: 0x%02X", this->address_); - esph_log_config(TAG, " Vendor ID: 0x%X", (int) this->vendor_id_); - } + void set_interrupt_pin(InternalGPIOPin *interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } protected: - bool err_check_(i2c::ErrorCode err, const char *msg) { - if (err != i2c::ERROR_OK) { - this->mark_failed(); - esph_log_e(TAG, "%s failed - err 0x%X", msg, err); - return false; - } - return true; - } - bool set_mode_(FTMode mode) { - return this->err_check_(this->write_register(FT5X06_MODE_REG, (uint8_t *) &mode, 1), "Set mode"); - } + void continue_setup_(); + bool err_check_(i2c::ErrorCode err, const char *msg); + bool set_mode_(FTMode mode); VendorId vendor_id_{FT5X06_ID_UNKNOWN}; + + InternalGPIOPin *interrupt_pin_{nullptr}; }; } // namespace ft5x06 From ac9f57600db0f44a9a1b048e5228d6b67df29d50 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:00:09 +1200 Subject: [PATCH 11/30] [voice_assistant] Half the microphone ringbuffer size (#6830) --- esphome/components/voice_assistant/voice_assistant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 59ba39c527..421bca9afb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -17,7 +17,7 @@ static const char *const TAG = "voice_assistant"; static const size_t SAMPLE_RATE_HZ = 16000; static const size_t INPUT_BUFFER_SIZE = 32 * SAMPLE_RATE_HZ / 1000; // 32ms * 16kHz / 1000ms -static const size_t BUFFER_SIZE = 1024 * SAMPLE_RATE_HZ / 1000; +static const size_t BUFFER_SIZE = 512 * SAMPLE_RATE_HZ / 1000; static const size_t SEND_BUFFER_SIZE = INPUT_BUFFER_SIZE * sizeof(int16_t); static const size_t RECEIVE_SIZE = 1024; static const size_t SPEAKER_BUFFER_SIZE = 16 * RECEIVE_SIZE; From ce4a3d995006a6f2b0a7afbee2f47c9807f54831 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 30 May 2024 20:01:39 +1200 Subject: [PATCH 12/30] [i2s_speaker] Add buffer allocation failure checks (#6829) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 95e63035fe..7f03a43da4 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -19,10 +19,27 @@ void I2SAudioSpeaker::setup() { ESP_LOGCONFIG(TAG, "Setting up I2S Audio Speaker..."); this->buffer_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(DataEvent)); + if (this->buffer_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create buffer queue"); + this->mark_failed(); + return; + } + this->event_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(TaskEvent)); + if (this->event_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create event queue"); + this->mark_failed(); + return; + } } -void I2SAudioSpeaker::start() { this->state_ = speaker::STATE_STARTING; } +void I2SAudioSpeaker::start() { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); + return; + } + this->state_ = speaker::STATE_STARTING; +} void I2SAudioSpeaker::start_() { if (!this->parent_->try_lock()) { return; // Waiting for another i2s component to return lock @@ -141,6 +158,8 @@ void I2SAudioSpeaker::player_task(void *params) { } void I2SAudioSpeaker::stop() { + if (this->is_failed()) + return; if (this->state_ == speaker::STATE_STOPPED) return; if (this->state_ == speaker::STATE_STARTING) { @@ -200,6 +219,10 @@ void I2SAudioSpeaker::loop() { } size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length) { + if (this->is_failed()) { + ESP_LOGE(TAG, "Cannot play audio, speaker failed to setup"); + return 0; + } if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) { this->start(); } From 388b2c2de0e92f4f5a8d18379e651a266b3750fa Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Mon, 3 Jun 2024 22:18:20 -0500 Subject: [PATCH 13/30] [improv_serial] Fix for IDF 4.4.7 (#6855) --- esphome/components/improv_serial/improv_serial_component.cpp | 1 + esphome/components/improv_serial/improv_serial_component.h | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 40297bee68..2937720496 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector &data) { #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) case logger::UART_SELECTION_USB_SERIAL_JTAG: usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS); + usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7 break; #endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3 default: diff --git a/esphome/components/improv_serial/improv_serial_component.h b/esphome/components/improv_serial/improv_serial_component.h index 8583d0762b..f737f93d86 100644 --- a/esphome/components/improv_serial/improv_serial_component.h +++ b/esphome/components/improv_serial/improv_serial_component.h @@ -17,6 +17,7 @@ #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \ defined(USE_ESP32_VARIANT_ESP32H2) #include +#include #endif #if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include From 664ee56dc5c3170bab8722dea504cbf072e95ccb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:51:29 +1200 Subject: [PATCH 14/30] Bump version to 2024.5.5 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index ad5858dcf3..658773b3db 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.4" +__version__ = "2024.5.5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 594856899a657ce5787f00d3432982869d29a8e9 Mon Sep 17 00:00:00 2001 From: Nate Clark Date: Wed, 5 Jun 2024 02:51:56 -0400 Subject: [PATCH 15/30] [ethernet] Add config option to set arbitrary PHY register values (#6836) --- esphome/components/ethernet/__init__.py | 29 ++++++++++ .../ethernet/ethernet_component.cpp | 58 +++++++------------ .../components/ethernet/ethernet_component.h | 12 +++- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index ade94cb9f5..697436415b 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -11,6 +11,7 @@ from esphome.components.esp32.const import ( from esphome.const import ( CONF_DOMAIN, CONF_ID, + CONF_VALUE, CONF_MANUAL_IP, CONF_STATIC_IP, CONF_TYPE, @@ -26,6 +27,8 @@ from esphome.const import ( CONF_INTERRUPT_PIN, CONF_RESET_PIN, CONF_SPI, + CONF_PAGE_ID, + CONF_ADDRESS, ) from esphome.core import CORE, coroutine_with_priority from esphome.components.network import IPAddress @@ -36,11 +39,13 @@ DEPENDENCIES = ["esp32"] AUTO_LOAD = ["network"] ethernet_ns = cg.esphome_ns.namespace("ethernet") +PHYRegister = ethernet_ns.struct("PHYRegister") CONF_PHY_ADDR = "phy_addr" CONF_MDC_PIN = "mdc_pin" CONF_MDIO_PIN = "mdio_pin" CONF_CLK_MODE = "clk_mode" CONF_POWER_PIN = "power_pin" +CONF_PHY_REGISTERS = "phy_registers" CONF_CLOCK_SPEED = "clock_speed" @@ -117,6 +122,13 @@ BASE_SCHEMA = cv.Schema( } ).extend(cv.COMPONENT_SCHEMA) +PHY_REGISTER_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.hex_int, + cv.Required(CONF_VALUE): cv.hex_int, + cv.Optional(CONF_PAGE_ID): cv.hex_int, + } +) RMII_SCHEMA = BASE_SCHEMA.extend( cv.Schema( { @@ -127,6 +139,7 @@ RMII_SCHEMA = BASE_SCHEMA.extend( ), cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31), cv.Optional(CONF_POWER_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_PHY_REGISTERS): cv.ensure_list(PHY_REGISTER_SCHEMA), } ) ) @@ -198,6 +211,15 @@ def manual_ip(config): ) +def phy_register(address: int, value: int, page: int): + return cg.StructInitializer( + PHYRegister, + ("address", address), + ("value", value), + ("page", page), + ) + + @coroutine_with_priority(60.0) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) @@ -225,6 +247,13 @@ async def to_code(config): cg.add(var.set_clk_mode(*CLK_MODES[config[CONF_CLK_MODE]])) if CONF_POWER_PIN in config: cg.add(var.set_power_pin(config[CONF_POWER_PIN])) + for register_value in config.get(CONF_PHY_REGISTERS, []): + reg = phy_register( + register_value.get(CONF_ADDRESS), + register_value.get(CONF_VALUE), + register_value.get(CONF_PAGE_ID), + ) + cg.add(var.add_phy_register(reg)) cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 6bb9732fef..75bdd29be7 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -195,9 +195,9 @@ void EthernetComponent::setup() { // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. this->ksz8081_set_clock_reference_(mac); } - if (this->type_ == ETHERNET_TYPE_RTL8201 && this->clk_mode_ == EMAC_CLK_EXT_IN) { - // Change in default behavior of RTL8201FI may require register setting to enable external clock - this->rtl8201_set_rmii_mode_(mac); + + for (const auto &phy_register : this->phy_registers_) { + this->write_phy_register_(mac, phy_register); } #endif @@ -527,6 +527,7 @@ void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_ this->clk_mode_ = clk_mode; this->clk_gpio_ = clk_gpio; } +void EthernetComponent::add_phy_register(PHYRegister register_value) { this->phy_registers_.push_back(register_value); } #endif void EthernetComponent::set_type(EthernetType type) { this->type_ = type; } void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; } @@ -613,44 +614,27 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str()); } } -constexpr uint8_t RTL8201_RMSR_REG_ADDR = 0x10; -void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) { + +void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) { esp_err_t err; - uint32_t phy_rmii_mode; - err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x07); - ESPHL_ERROR_CHECK(err, "Setting Page 7 failed"); + constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; - /* - * RTL8201 RMII Mode Setting Register (RMSR) - * Page 7 Register 16 - * - * bit 0 Reserved 0 - * bit 1 Rg_rmii_rxdsel 1 (default) - * bit 2 Rg_rmii_rxdv_sel: 0 (default) - * bit 3 RMII Mode: 1 (RMII Mode) - * bit 4~7 Rg_rmii_rx_offset: 1111 (default) - * bit 8~11 Rg_rmii_tx_offset: 1111 (default) - * bit 12 Rg_rmii_clkdir: 1 (Input) - * bit 13~15 Reserved 000 - * - * Binary: 0001 1111 1111 1010 - * Hex: 0x1FFA - * - */ + if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { + ESP_LOGD(TAG, "Select PHY Register Page: 0x%02" PRIX32, register_data.page); + err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, register_data.page); + ESPHL_ERROR_CHECK(err, "Select PHY Register page failed"); + } - err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); - ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04" PRIX32, phy_rmii_mode); + ESP_LOGD(TAG, "Writing to PHY Register Address: 0x%02" PRIX32, register_data.address); + ESP_LOGD(TAG, "Writing to PHY Register Value: 0x%04" PRIX32, register_data.value); + err = mac->write_phy_reg(mac, this->phy_addr_, register_data.address, register_data.value); + ESPHL_ERROR_CHECK(err, "Writing PHY Register failed"); - err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA); - ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed"); - - err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode)); - ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed"); - ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04" PRIX32, phy_rmii_mode); - - err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0); - ESPHL_ERROR_CHECK(err, "Setting Page 0 failed"); + if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { + ESP_LOGD(TAG, "Select PHY Register Page 0x%02" PRIX32, 0x0); + err = mac->write_phy_reg(mac, this->phy_addr_, eth_phy_psr_reg_addr, 0x0); + ESPHL_ERROR_CHECK(err, "Select PHY Register Page 0 failed"); + } } #endif diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index e57aa5fe12..f0fe6cab87 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -35,6 +35,12 @@ struct ManualIP { network::IPAddress dns2; ///< The second DNS server. 0.0.0.0 for default. }; +struct PHYRegister { + uint32_t address; + uint32_t value; + uint32_t page; +}; + enum class EthernetComponentState { STOPPED, CONNECTING, @@ -66,6 +72,7 @@ class EthernetComponent : public Component { void set_mdc_pin(uint8_t mdc_pin); void set_mdio_pin(uint8_t mdio_pin); void set_clk_mode(emac_rmii_clock_mode_t clk_mode, emac_rmii_clock_gpio_t clk_gpio); + void add_phy_register(PHYRegister register_value); #endif void set_type(EthernetType type); void set_manual_ip(const ManualIP &manual_ip); @@ -91,8 +98,8 @@ class EthernetComponent : public Component { void dump_connect_params_(); /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); - /// @brief Set `RMII Mode Setting Register` for RTL8201. - void rtl8201_set_rmii_mode_(esp_eth_mac_t *mac); + /// @brief Set arbitratry PHY registers from config. + void write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data); std::string use_address_; #ifdef USE_ETHERNET_SPI @@ -111,6 +118,7 @@ class EthernetComponent : public Component { uint8_t mdio_pin_{18}; emac_rmii_clock_mode_t clk_mode_{EMAC_CLK_EXT_IN}; emac_rmii_clock_gpio_t clk_gpio_{EMAC_CLK_IN_GPIO}; + std::vector phy_registers_{}; #endif EthernetType type_{ETHERNET_TYPE_UNKNOWN}; optional manual_ip_{}; From f36a96c8e20c3b593f7dc48ba9f74e2c1fafe97e Mon Sep 17 00:00:00 2001 From: svxa <59204027+svxa@users.noreply.github.com> Date: Wed, 5 Jun 2024 09:35:19 +0200 Subject: [PATCH 16/30] Add carrier_frequency option to remote_transmitter.transmit_aeha (#6792) --- esphome/components/remote_base/__init__.py | 14 +++++++++++++- esphome/components/remote_base/aeha_protocol.cpp | 1 - esphome/components/remote_base/aeha_protocol.h | 2 ++ .../remote_transmitter/common-buttons.yaml | 1 + tests/test1.yaml | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 9d49026aa3..3d1c10a092 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -1769,7 +1769,17 @@ def aeha_dumper(var, config): pass -@register_action("aeha", AEHAAction, AEHA_SCHEMA) +@register_action( + "aeha", + AEHAAction, + AEHA_SCHEMA.extend( + { + cv.Optional(CONF_CARRIER_FREQUENCY, default="38000Hz"): cv.All( + cv.frequency, cv.int_ + ), + } + ), +) async def aeha_action(var, config, args): template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) @@ -1777,6 +1787,8 @@ async def aeha_action(var, config, args): config[CONF_DATA], args, cg.std_vector.template(cg.uint8) ) cg.add(var.set_data(template_)) + templ = await cg.templatable(config[CONF_CARRIER_FREQUENCY], args, cg.uint32) + cg.add(var.set_carrier_frequency(templ)) # Haier diff --git a/esphome/components/remote_base/aeha_protocol.cpp b/esphome/components/remote_base/aeha_protocol.cpp index 40bdadf634..04fe731817 100644 --- a/esphome/components/remote_base/aeha_protocol.cpp +++ b/esphome/components/remote_base/aeha_protocol.cpp @@ -16,7 +16,6 @@ static const uint16_t BIT_ZERO_LOW_US = BITWISE; static const uint16_t TRAILER = BITWISE; void AEHAProtocol::encode(RemoteTransmitData *dst, const AEHAData &data) { - dst->set_carrier_frequency(38000); dst->reserve(2 + 32 + (data.data.size() * 2) + 1); dst->item(HEADER_HIGH_US, HEADER_LOW_US); diff --git a/esphome/components/remote_base/aeha_protocol.h b/esphome/components/remote_base/aeha_protocol.h index c41f3f8df1..51718eefcb 100644 --- a/esphome/components/remote_base/aeha_protocol.h +++ b/esphome/components/remote_base/aeha_protocol.h @@ -30,12 +30,14 @@ template class AEHAAction : public RemoteTransmitterActionBase, data) + TEMPLATABLE_VALUE(uint32_t, carrier_frequency); void set_data(const std::vector &data) { data_ = data; } void encode(RemoteTransmitData *dst, Ts... x) override { AEHAData data{}; data.address = this->address_.value(x...); data.data = this->data_.value(x...); + dst->set_carrier_frequency(this->carrier_frequency_.value(x...)); AEHAProtocol().encode(dst, data); } }; diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index e727017e85..c6a2453b20 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -118,6 +118,7 @@ button: on_press: remote_transmitter.transmit_aeha: address: 0x8008 + carrier_frequency: 36700Hz data: [ 0x00, diff --git a/tests/test1.yaml b/tests/test1.yaml index 2a20a1bb45..c49ff307e5 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2906,6 +2906,7 @@ switch: turn_on_action: remote_transmitter.transmit_aeha: address: 0x8008 + carrier_frequency: 36700Hz data: [ 0x00, From c52d5c02791850317bc9302ef86a18fec6b01dd2 Mon Sep 17 00:00:00 2001 From: Will Rouesnel Date: Wed, 5 Jun 2024 17:52:19 +1000 Subject: [PATCH 17/30] Add `invert_position_report` to `tuya.cover` (#6020) --- esphome/components/tuya/cover/__init__.py | 3 +++ esphome/components/tuya/cover/tuya_cover.cpp | 9 ++++++--- esphome/components/tuya/cover/tuya_cover.h | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/tuya/cover/__init__.py b/esphome/components/tuya/cover/__init__.py index f886c7030f..2dd66f814d 100644 --- a/esphome/components/tuya/cover/__init__.py +++ b/esphome/components/tuya/cover/__init__.py @@ -16,6 +16,7 @@ CONF_DIRECTION_DATAPOINT = "direction_datapoint" CONF_POSITION_DATAPOINT = "position_datapoint" CONF_POSITION_REPORT_DATAPOINT = "position_report_datapoint" CONF_INVERT_POSITION = "invert_position" +CONF_INVERT_POSITION_REPORT = "invert_position_report" TuyaCover = tuya_ns.class_("TuyaCover", cover.Cover, cg.Component) @@ -47,6 +48,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MIN_VALUE, default=0): cv.int_, cv.Optional(CONF_MAX_VALUE, default=100): cv.int_, cv.Optional(CONF_INVERT_POSITION, default=False): cv.boolean, + cv.Optional(CONF_INVERT_POSITION_REPORT, default=False): cv.boolean, cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum( RESTORE_MODES, upper=True ), @@ -71,6 +73,7 @@ async def to_code(config): cg.add(var.set_min_value(config[CONF_MIN_VALUE])) cg.add(var.set_max_value(config[CONF_MAX_VALUE])) cg.add(var.set_invert_position(config[CONF_INVERT_POSITION])) + cg.add(var.set_invert_position_report(config[CONF_INVERT_POSITION_REPORT])) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) paren = await cg.get_variable(config[CONF_TUYA_ID]) cg.add(var.set_tuya_parent(paren)) diff --git a/esphome/components/tuya/cover/tuya_cover.cpp b/esphome/components/tuya/cover/tuya_cover.cpp index fcb961f45e..14bf937cf7 100644 --- a/esphome/components/tuya/cover/tuya_cover.cpp +++ b/esphome/components/tuya/cover/tuya_cover.cpp @@ -51,7 +51,7 @@ void TuyaCover::setup() { return; } auto pos = float(datapoint.value_uint - this->min_value_) / this->value_range_; - this->position = 1.0f - pos; + this->position = this->invert_position_report_ ? pos : 1.0f - pos; this->publish_state(); }); } @@ -62,7 +62,7 @@ void TuyaCover::control(const cover::CoverCall &call) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP); } else { auto pos = this->position; - pos = 1.0f - pos; + pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast(pos * this->value_range_); position_int = position_int + this->min_value_; @@ -78,7 +78,7 @@ void TuyaCover::control(const cover::CoverCall &call) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE); } } else { - pos = 1.0f - pos; + pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast(pos * this->value_range_); position_int = position_int + this->min_value_; @@ -112,6 +112,9 @@ void TuyaCover::dump_config() { ESP_LOGCONFIG(TAG, " Configured as Inverted, but direction_datapoint isn't configured"); } } + if (this->invert_position_report_) { + ESP_LOGCONFIG(TAG, " Position Reporting Inverted"); + } if (this->control_id_.has_value()) { ESP_LOGCONFIG(TAG, " Control has datapoint ID %u", *this->control_id_); } diff --git a/esphome/components/tuya/cover/tuya_cover.h b/esphome/components/tuya/cover/tuya_cover.h index 87c72b0e66..bb5a00bc59 100644 --- a/esphome/components/tuya/cover/tuya_cover.h +++ b/esphome/components/tuya/cover/tuya_cover.h @@ -25,6 +25,7 @@ class TuyaCover : public cover::Cover, public Component { void set_min_value(uint32_t min_value) { min_value_ = min_value; } void set_max_value(uint32_t max_value) { max_value_ = max_value; } void set_invert_position(bool invert_position) { invert_position_ = invert_position; } + void set_invert_position_report(bool invert_position_report) { invert_position_report_ = invert_position_report; } void set_restore_mode(TuyaCoverRestoreMode restore_mode) { restore_mode_ = restore_mode; } protected: @@ -42,6 +43,7 @@ class TuyaCover : public cover::Cover, public Component { uint32_t max_value_; uint32_t value_range_; bool invert_position_; + bool invert_position_report_; }; } // namespace tuya From cc217d8a83a049d259b163fd01e38141373b3e9d Mon Sep 17 00:00:00 2001 From: zry98 Date: Wed, 5 Jun 2024 10:11:19 +0200 Subject: [PATCH 18/30] [Tuya Climate] Support both datapoint and pins for active state (#6789) --- esphome/components/tuya/climate/__init__.py | 15 ++-- .../components/tuya/climate/tuya_climate.cpp | 76 +++++++++++-------- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index 56eb377ed7..363e7c764b 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -189,8 +189,6 @@ CONFIG_SCHEMA = cv.All( cv.has_at_least_one_key(CONF_TARGET_TEMPERATURE_DATAPOINT, CONF_SWITCH_DATAPOINT), validate_temperature_multipliers, validate_cooling_values, - cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_HEATING_STATE_PIN), - cv.has_at_most_one_key(CONF_ACTIVE_STATE, CONF_COOLING_STATE_PIN), ) @@ -207,6 +205,12 @@ async def to_code(config): if switch_datapoint := config.get(CONF_SWITCH_DATAPOINT): cg.add(var.set_switch_id(switch_datapoint)) + if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): + heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) + cg.add(var.set_heating_state_pin(heating_state_pin)) + if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): + cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) + cg.add(var.set_cooling_state_pin(cooling_state_pin)) if active_state_config := config.get(CONF_ACTIVE_STATE): cg.add(var.set_active_state_id(active_state_config.get(CONF_DATAPOINT))) if (heating_value := active_state_config.get(CONF_HEATING_VALUE)) is not None: @@ -217,13 +221,6 @@ async def to_code(config): cg.add(var.set_active_state_drying_value(drying_value)) if (fanonly_value := active_state_config.get(CONF_FANONLY_VALUE)) is not None: cg.add(var.set_active_state_fanonly_value(fanonly_value)) - else: - if heating_state_pin_config := config.get(CONF_HEATING_STATE_PIN): - heating_state_pin = await cg.gpio_pin_expression(heating_state_pin_config) - cg.add(var.set_heating_state_pin(heating_state_pin)) - if cooling_state_pin_config := config.get(CONF_COOLING_STATE_PIN): - cooling_state_pin = await cg.gpio_pin_expression(cooling_state_pin_config) - cg.add(var.set_cooling_state_pin(cooling_state_pin)) if target_temperature_datapoint := config.get(CONF_TARGET_TEMPERATURE_DATAPOINT): cg.add(var.set_target_temperature_id(target_temperature_datapoint)) diff --git a/esphome/components/tuya/climate/tuya_climate.cpp b/esphome/components/tuya/climate/tuya_climate.cpp index 274e19a69e..7827a4e3ab 100644 --- a/esphome/components/tuya/climate/tuya_climate.cpp +++ b/esphome/components/tuya/climate/tuya_climate.cpp @@ -24,6 +24,14 @@ void TuyaClimate::setup() { this->publish_state(); }); } + if (this->heating_state_pin_ != nullptr) { + this->heating_state_pin_->setup(); + this->heating_state_ = this->heating_state_pin_->digital_read(); + } + if (this->cooling_state_pin_ != nullptr) { + this->cooling_state_pin_->setup(); + this->cooling_state_ = this->cooling_state_pin_->digital_read(); + } if (this->active_state_id_.has_value()) { this->parent_->register_listener(*this->active_state_id_, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported active state is: %u", datapoint.value_enum); @@ -31,15 +39,6 @@ void TuyaClimate::setup() { this->compute_state_(); this->publish_state(); }); - } else { - if (this->heating_state_pin_ != nullptr) { - this->heating_state_pin_->setup(); - this->heating_state_ = this->heating_state_pin_->digital_read(); - } - if (this->cooling_state_pin_ != nullptr) { - this->cooling_state_pin_->setup(); - this->cooling_state_ = this->cooling_state_pin_->digital_read(); - } } if (this->target_temperature_id_.has_value()) { this->parent_->register_listener(*this->target_temperature_id_, [this](const TuyaDatapoint &datapoint) { @@ -113,9 +112,6 @@ void TuyaClimate::setup() { } void TuyaClimate::loop() { - if (this->active_state_id_.has_value()) - return; - bool state_changed = false; if (this->heating_state_pin_ != nullptr) { bool heating_state = this->heating_state_pin_->digital_read(); @@ -147,14 +143,18 @@ void TuyaClimate::control(const climate::ClimateCall &call) { this->parent_->set_boolean_datapoint_value(*this->switch_id_, switch_state); const climate::ClimateMode new_mode = *call.get_mode(); - if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_); - } else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_); - } else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_); - } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) { - this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_); + if (this->active_state_id_.has_value()) { + if (new_mode == climate::CLIMATE_MODE_HEAT && this->supports_heat_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_heating_value_); + } else if (new_mode == climate::CLIMATE_MODE_COOL && this->supports_cool_) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_cooling_value_); + } else if (new_mode == climate::CLIMATE_MODE_DRY && this->active_state_drying_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_drying_value_); + } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY && this->active_state_fanonly_value_.has_value()) { + this->parent_->set_enum_datapoint_value(*this->active_state_id_, *this->active_state_fanonly_value_); + } + } else { + ESP_LOGW(TAG, "Active state (mode) datapoint not configured"); } } @@ -422,7 +422,32 @@ void TuyaClimate::compute_state_() { } climate::ClimateAction target_action = climate::CLIMATE_ACTION_IDLE; - if (this->active_state_id_.has_value()) { + if (this->heating_state_pin_ != nullptr || this->cooling_state_pin_ != nullptr) { + // Use state from input pins + if (this->heating_state_) { + target_action = climate::CLIMATE_ACTION_HEATING; + this->mode = climate::CLIMATE_MODE_HEAT; + } else if (this->cooling_state_) { + target_action = climate::CLIMATE_ACTION_COOLING; + this->mode = climate::CLIMATE_MODE_COOL; + } + if (this->active_state_id_.has_value()) { + // Both are available, use MCU datapoint as mode + if (this->supports_heat_ && this->active_state_heating_value_.has_value() && + this->active_state_ == this->active_state_heating_value_) { + this->mode = climate::CLIMATE_MODE_HEAT; + } else if (this->supports_cool_ && this->active_state_cooling_value_.has_value() && + this->active_state_ == this->active_state_cooling_value_) { + this->mode = climate::CLIMATE_MODE_COOL; + } else if (this->active_state_drying_value_.has_value() && + this->active_state_ == this->active_state_drying_value_) { + this->mode = climate::CLIMATE_MODE_DRY; + } else if (this->active_state_fanonly_value_.has_value() && + this->active_state_ == this->active_state_fanonly_value_) { + this->mode = climate::CLIMATE_MODE_FAN_ONLY; + } + } + } else if (this->active_state_id_.has_value()) { // Use state from MCU datapoint if (this->supports_heat_ && this->active_state_heating_value_.has_value() && this->active_state_ == this->active_state_heating_value_) { @@ -441,15 +466,6 @@ void TuyaClimate::compute_state_() { target_action = climate::CLIMATE_ACTION_FAN; this->mode = climate::CLIMATE_MODE_FAN_ONLY; } - } else if (this->heating_state_pin_ != nullptr || this->cooling_state_pin_ != nullptr) { - // Use state from input pins - if (this->heating_state_) { - target_action = climate::CLIMATE_ACTION_HEATING; - this->mode = climate::CLIMATE_MODE_HEAT; - } else if (this->cooling_state_) { - target_action = climate::CLIMATE_ACTION_COOLING; - this->mode = climate::CLIMATE_MODE_COOL; - } } else { // Fallback to active state calc based on temp and hysteresis const float temp_diff = this->target_temperature - this->current_temperature; From 7143e9cd9e2073351cfd239e242e2132a36eec0b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 6 Jun 2024 05:27:06 +1000 Subject: [PATCH 19/30] [config] Allow file: scheme for git external components (#6844) --- esphome/config_validation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 5fc72921e1..7259e3c062 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1949,13 +1949,13 @@ def url(value): except ValueError as e: raise Invalid("Not a valid URL") from e - if not parsed.scheme or not parsed.netloc: - raise Invalid("Expected a URL scheme and host") - return parsed.geturl() + if parsed.scheme and parsed.netloc or parsed.scheme == "file": + return parsed.geturl() + raise Invalid("Expected a file scheme or a URL scheme with host") def git_ref(value): - if re.match(r"[a-zA-Z0-9\-_.\./]+", value) is None: + if re.match(r"[a-zA-Z0-9_./-]+", value) is None: raise Invalid("Not a valid git ref") return value From 8ef4aaa70eac95656f2742b7e57d1010cfb235b5 Mon Sep 17 00:00:00 2001 From: Olivier ARCHER Date: Thu, 6 Jun 2024 04:35:28 +0200 Subject: [PATCH 20/30] [ota] http_request update platform (#5586) Co-authored-by: Keith Burzinski Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> --- CODEOWNERS | 1 + .../components/http_request/ota/__init__.py | 189 +++++++++++ .../components/http_request/ota/automation.h | 42 +++ .../http_request/ota/ota_http_request.cpp | 293 ++++++++++++++++++ .../http_request/ota/ota_http_request.h | 72 +++++ .../ota/ota_http_request_arduino.cpp | 134 ++++++++ .../ota/ota_http_request_arduino.h | 42 +++ .../http_request/ota/ota_http_request_idf.cpp | 86 +++++ .../http_request/ota/ota_http_request_idf.h | 24 ++ .../components/http_request/ota/watchdog.cpp | 71 +++++ .../components/http_request/ota/watchdog.h | 27 ++ esphome/core/defines.h | 1 + .../{common.yaml => common_http_request.yaml} | 4 - tests/components/http_request/common_ota.yaml | 36 +++ .../http_request/test-nossl.esp8266.yaml | 38 +++ .../http_request/test.esp32-c3-idf.yaml | 4 + .../http_request/test.esp32-c3.yaml | 7 +- .../http_request/test.esp32-idf.yaml | 4 + tests/components/http_request/test.esp32.yaml | 7 +- .../components/http_request/test.esp8266.yaml | 7 +- .../components/http_request/test.rp2040.yaml | 4 + 21 files changed, 1083 insertions(+), 10 deletions(-) create mode 100644 esphome/components/http_request/ota/__init__.py create mode 100644 esphome/components/http_request/ota/automation.h create mode 100644 esphome/components/http_request/ota/ota_http_request.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request.h create mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.h create mode 100644 esphome/components/http_request/ota/ota_http_request_idf.cpp create mode 100644 esphome/components/http_request/ota/ota_http_request_idf.h create mode 100644 esphome/components/http_request/ota/watchdog.cpp create mode 100644 esphome/components/http_request/ota/watchdog.h rename tests/components/http_request/{common.yaml => common_http_request.yaml} (95%) create mode 100644 tests/components/http_request/common_ota.yaml create mode 100644 tests/components/http_request/test-nossl.esp8266.yaml create mode 100644 tests/components/http_request/test.esp32-c3-idf.yaml create mode 100644 tests/components/http_request/test.esp32-idf.yaml create mode 100644 tests/components/http_request/test.rp2040.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 82f61c3b80..90574ca9ba 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -171,6 +171,7 @@ esphome/components/host/* @clydebarrow @esphome/core esphome/components/host/time/* @clydebarrow esphome/components/hrxl_maxsonar_wr/* @netmikey esphome/components/hte501/* @Stock-M +esphome/components/http_request/ota/* @oarcher esphome/components/htu31d/* @betterengineering esphome/components/hydreon_rgxx/* @functionpointer esphome/components/hyt271/* @Philippe12 diff --git a/esphome/components/http_request/ota/__init__.py b/esphome/components/http_request/ota/__init__.py new file mode 100644 index 0000000000..6a56fac83a --- /dev/null +++ b/esphome/components/http_request/ota/__init__.py @@ -0,0 +1,189 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome import automation +from esphome.const import ( + CONF_ESP8266_DISABLE_SSL_SUPPORT, + CONF_ID, + CONF_PASSWORD, + CONF_TIMEOUT, + CONF_URL, + CONF_USERNAME, +) +from esphome.components import esp32 +from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent +from esphome.core import CORE, coroutine_with_priority +from .. import http_request_ns + +CODEOWNERS = ["@oarcher"] + +AUTO_LOAD = ["md5"] +DEPENDENCIES = ["network"] + +CONF_MD5 = "md5" +CONF_MD5_URL = "md5_url" +CONF_VERIFY_SSL = "verify_ssl" +CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" + +OtaHttpRequestComponent = http_request_ns.class_( + "OtaHttpRequestComponent", OTAComponent +) +OtaHttpRequestComponentArduino = http_request_ns.class_( + "OtaHttpRequestComponentArduino", OtaHttpRequestComponent +) +OtaHttpRequestComponentIDF = http_request_ns.class_( + "OtaHttpRequestComponentIDF", OtaHttpRequestComponent +) +OtaHttpRequestComponentFlashAction = http_request_ns.class_( + "OtaHttpRequestComponentFlashAction", automation.Action +) + + +def validate_ssl_verification(config): + error_message = "" + + if CORE.is_esp32: + if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: + error_message = "ESPHome supports certificate verification only via ESP-IDF" + + if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: + error_message = "ESPHome does not support certificate verification in Arduino" + + if ( + CORE.is_esp8266 + and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] + and config[CONF_VERIFY_SSL] + ): + error_message = "ESPHome does not support certificate verification in Arduino" + + if len(error_message) > 0: + raise cv.Invalid( + f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." + ) + + return config + + +def _declare_request_class(value): + if CORE.using_esp_idf: + return cv.declare_id(OtaHttpRequestComponentIDF)(value) + + if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: + return cv.declare_id(OtaHttpRequestComponentArduino)(value) + return NotImplementedError + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): _declare_request_class, + cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( + cv.only_on_esp8266, cv.boolean + ), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional( + CONF_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( + cv.Any(cv.only_on_esp32, cv.only_on_rp2040), + cv.positive_not_null_time_period, + cv.positive_time_period_milliseconds, + ), + } + ) + .extend(BASE_OTA_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), + cv.require_framework_version( + esp8266_arduino=cv.Version(2, 5, 1), + esp32_arduino=cv.Version(0, 0, 0), + esp_idf=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), + ), + validate_ssl_verification, +) + + +@coroutine_with_priority(52.0) +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await ota_to_code(var, config) + + cg.add(var.set_timeout(config[CONF_TIMEOUT])) + + if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): + cg.add_define( + "USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT", + timeout_ms, + ) + + if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: + cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") + + if CORE.is_esp32: + if CORE.using_esp_idf: + esp32.add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", + config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_INSECURE", + not config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", + not config.get(CONF_VERIFY_SSL), + ) + else: + cg.add_library("WiFiClientSecure", None) + cg.add_library("HTTPClient", None) + if CORE.is_esp8266: + cg.add_library("ESP8266HTTPClient", None) + if CORE.is_rp2040 and CORE.using_arduino: + cg.add_library("HTTPClient", None) + + await cg.register_component(var, config) + + +OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.use_id(OtaHttpRequestComponent), + cv.Optional(CONF_MD5_URL): cv.templatable(cv.url), + cv.Optional(CONF_MD5): cv.templatable(cv.string), + cv.Optional(CONF_PASSWORD): cv.templatable(cv.string), + cv.Optional(CONF_USERNAME): cv.templatable(cv.string), + cv.Required(CONF_URL): cv.templatable(cv.url), + } + ), + cv.has_exactly_one_key(CONF_MD5, CONF_MD5_URL), +) + + +@automation.register_action( + "ota_http_request.flash", + OtaHttpRequestComponentFlashAction, + OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA, +) +async def ota_http_request_action_to_code(config, action_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, paren) + + if md5_url := config.get(CONF_MD5_URL): + template_ = await cg.templatable(md5_url, args, cg.std_string) + cg.add(var.set_md5_url(template_)) + + if md5_str := config.get(CONF_MD5): + template_ = await cg.templatable(md5_str, args, cg.std_string) + cg.add(var.set_md5(template_)) + + if password_str := config.get(CONF_PASSWORD): + template_ = await cg.templatable(password_str, args, cg.std_string) + cg.add(var.set_password(template_)) + + if username_str := config.get(CONF_USERNAME): + template_ = await cg.templatable(username_str, args, cg.std_string) + cg.add(var.set_username(template_)) + + template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) + cg.add(var.set_url(template_)) + + return var diff --git a/esphome/components/http_request/ota/automation.h b/esphome/components/http_request/ota/automation.h new file mode 100644 index 0000000000..d4c21f1c72 --- /dev/null +++ b/esphome/components/http_request/ota/automation.h @@ -0,0 +1,42 @@ +#pragma once +#include "ota_http_request.h" + +#include "esphome/core/automation.h" + +namespace esphome { +namespace http_request { + +template class OtaHttpRequestComponentFlashAction : public Action { + public: + OtaHttpRequestComponentFlashAction(OtaHttpRequestComponent *parent) : parent_(parent) {} + TEMPLATABLE_VALUE(std::string, md5_url) + TEMPLATABLE_VALUE(std::string, md5) + TEMPLATABLE_VALUE(std::string, password) + TEMPLATABLE_VALUE(std::string, url) + TEMPLATABLE_VALUE(std::string, username) + + void play(Ts... x) override { + if (this->md5_url_.has_value()) { + this->parent_->set_md5_url(this->md5_url_.value(x...)); + } + if (this->md5_.has_value()) { + this->parent_->set_md5(this->md5_.value(x...)); + } + if (this->password_.has_value()) { + this->parent_->set_password(this->password_.value(x...)); + } + if (this->username_.has_value()) { + this->parent_->set_username(this->username_.value(x...)); + } + this->parent_->set_url(this->url_.value(x...)); + + this->parent_->flash(); + // Normally never reached due to reboot + } + + protected: + OtaHttpRequestComponent *parent_; +}; + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp new file mode 100644 index 0000000000..cf0816c858 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -0,0 +1,293 @@ +#include "ota_http_request.h" +#include "watchdog.h" + +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#include "esphome/components/md5/md5.h" +#include "esphome/components/ota/ota_backend_arduino_esp32.h" +#include "esphome/components/ota/ota_backend_arduino_esp8266.h" +#include "esphome/components/ota/ota_backend_arduino_rp2040.h" +#include "esphome/components/ota/ota_backend_esp_idf.h" +#include "esphome/components/ota/ota_backend.h" + +namespace esphome { +namespace http_request { + +void OtaHttpRequestComponent::setup() { +#ifdef USE_OTA_STATE_CALLBACK + ota::register_ota_platform(this); +#endif +} + +void OtaHttpRequestComponent::dump_config() { + ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request:"); + ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: No"); +#else + ESP_LOGCONFIG(TAG, " ESP8266 SSL support: Yes"); +#endif +#endif +#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + ESP_LOGCONFIG(TAG, " TLS server verification: Yes"); +#else + ESP_LOGCONFIG(TAG, " TLS server verification: No"); +#endif +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT / 1000); +#endif +}; + +void OtaHttpRequestComponent::set_md5_url(const std::string &url) { + if (!this->validate_url_(url)) { + this->md5_url_.clear(); // URL was not valid; prevent flashing until it is + return; + } + this->md5_url_ = url; + this->md5_expected_.clear(); // to be retrieved later +} + +void OtaHttpRequestComponent::set_url(const std::string &url) { + if (!this->validate_url_(url)) { + this->url_.clear(); // URL was not valid; prevent flashing until it is + return; + } + this->url_ = url; +} + +bool OtaHttpRequestComponent::check_status() { + // status can be -1, or HTTP status code + if (this->status_ < 100) { + ESP_LOGE(TAG, "HTTP server did not respond (error %d)", this->status_); + return false; + } + if (this->status_ >= 310) { + ESP_LOGE(TAG, "HTTP error %d", this->status_); + return false; + } + ESP_LOGV(TAG, "HTTP status %d", this->status_); + return true; +} + +void OtaHttpRequestComponent::flash() { + if (this->url_.empty()) { + ESP_LOGE(TAG, "URL not set; cannot start update"); + return; + } + + ESP_LOGI(TAG, "Starting update..."); +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0); +#endif + + auto ota_status = this->do_ota_(); + + switch (ota_status) { + case ota::OTA_RESPONSE_OK: +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_COMPLETED, 100.0f, ota_status); +#endif + delay(10); + App.safe_reboot(); + break; + + default: +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_ERROR, 0.0f, ota_status); +#endif + this->md5_computed_.clear(); // will be reset at next attempt + this->md5_expected_.clear(); // will be reset at next attempt + break; + } +} + +void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend) { + if (this->update_started_) { + ESP_LOGV(TAG, "Aborting OTA backend"); + backend->abort(); + } + ESP_LOGV(TAG, "Aborting HTTP connection"); + this->http_end(); +}; + +uint8_t OtaHttpRequestComponent::do_ota_() { + uint8_t buf[this->http_recv_buffer_ + 1]; + uint32_t last_progress = 0; + uint32_t update_start_time = millis(); + md5::MD5Digest md5_receive; + std::unique_ptr md5_receive_str(new char[33]); + + if (this->md5_expected_.empty() && !this->http_get_md5_()) { + return OTA_MD5_INVALID; + } + + ESP_LOGD(TAG, "MD5 expected: %s", this->md5_expected_.c_str()); + + auto url_with_auth = this->get_url_with_auth_(this->url_); + if (url_with_auth.empty()) { + return OTA_BAD_URL; + } + ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); + ESP_LOGI(TAG, "Connecting to: %s", this->url_.c_str()); + this->http_init(url_with_auth); + if (!this->check_status()) { + this->http_end(); + return OTA_CONNECTION_ERROR; + } + + // we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it + md5_receive.init(); + ESP_LOGV(TAG, "MD5Digest initialized"); + + ESP_LOGV(TAG, "OTA backend begin"); + auto backend = ota::make_ota_backend(); + auto error_code = backend->begin(this->body_length_); + if (error_code != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "backend->begin error: %d", error_code); + this->cleanup_(std::move(backend)); + return error_code; + } + + this->bytes_read_ = 0; + while (this->bytes_read_ < this->body_length_) { + // read a maximum of chunk_size bytes into buf. (real read size returned) + int bufsize = this->http_read(buf, this->http_recv_buffer_); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", this->bytes_read_, this->body_length_, bufsize); + + // feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + + if (bufsize < 0) { + ESP_LOGE(TAG, "Stream closed"); + this->cleanup_(std::move(backend)); + return OTA_CONNECTION_ERROR; + } else if (bufsize > 0 && bufsize <= this->http_recv_buffer_) { + // add read bytes to MD5 + md5_receive.add(buf, bufsize); + + // write bytes to OTA backend + this->update_started_ = true; + error_code = backend->write(buf, bufsize); + if (error_code != ota::OTA_RESPONSE_OK) { + // error code explanation available at + // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h + ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, + this->bytes_read_ - bufsize, this->body_length_); + this->cleanup_(std::move(backend)); + return error_code; + } + } + + uint32_t now = millis(); + if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { + last_progress = now; + float percentage = this->bytes_read_ * 100.0f / this->body_length_; + ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); +#ifdef USE_OTA_STATE_CALLBACK + this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); +#endif + } + } // while + + ESP_LOGI(TAG, "Done in %.0f seconds", float(millis() - update_start_time) / 1000); + + // verify MD5 is as expected and act accordingly + md5_receive.calculate(); + md5_receive.get_hex(md5_receive_str.get()); + this->md5_computed_ = md5_receive_str.get(); + if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { + ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); + this->cleanup_(std::move(backend)); + return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; + } else { + backend->set_update_md5(md5_receive_str.get()); + } + + this->http_end(); + + // feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + delay(100); // NOLINT + + error_code = backend->end(); + if (error_code != ota::OTA_RESPONSE_OK) { + ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); + this->cleanup_(std::move(backend)); + return error_code; + } + + ESP_LOGI(TAG, "Update complete"); + return ota::OTA_RESPONSE_OK; +} + +std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { + if (this->username_.empty() || this->password_.empty()) { + return url; + } + + auto start_char = url.find("://"); + if ((start_char == std::string::npos) || (start_char < 4)) { + ESP_LOGE(TAG, "Incorrect URL prefix"); + return {}; + } + + ESP_LOGD(TAG, "Using basic HTTP authentication"); + + start_char += 3; // skip '://' characters + auto url_with_auth = + url.substr(0, start_char) + this->username_ + ":" + this->password_ + "@" + url.substr(start_char); + return url_with_auth; +} + +bool OtaHttpRequestComponent::http_get_md5_() { + if (this->md5_url_.empty()) { + return false; + } + + auto url_with_auth = this->get_url_with_auth_(this->md5_url_); + if (url_with_auth.empty()) { + return false; + } + + ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); + ESP_LOGI(TAG, "Connecting to: %s", this->md5_url_.c_str()); + this->http_init(url_with_auth); + if (!this->check_status()) { + this->http_end(); + return false; + } + int length = this->body_length_; + if (length < 0) { + this->http_end(); + return false; + } + if (length < MD5_SIZE) { + ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, + this->body_length_); + this->http_end(); + return false; + } + + this->bytes_read_ = 0; + this->md5_expected_.resize(MD5_SIZE); + auto read_len = this->http_read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); + this->http_end(); + + return read_len == MD5_SIZE; +} + +bool OtaHttpRequestComponent::validate_url_(const std::string &url) { + if ((url.length() < 8) || (url.find("http") != 0) || (url.find("://") == std::string::npos)) { + ESP_LOGE(TAG, "URL is invalid and/or must be prefixed with 'http://' or 'https://'"); + return false; + } + return true; +} + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h new file mode 100644 index 0000000000..9fbdf2ec25 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -0,0 +1,72 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/components/ota/ota_backend.h" + +#include +#include +#include + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.ota"; +static const uint8_t MD5_SIZE = 32; + +enum OtaHttpRequestError : uint8_t { + OTA_MD5_INVALID = 0x10, + OTA_BAD_URL = 0x11, + OTA_CONNECTION_ERROR = 0x12, +}; + +class OtaHttpRequestComponent : public ota::OTAComponent { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + + void set_md5_url(const std::string &md5_url); + void set_md5(const std::string &md5) { this->md5_expected_ = md5; } + void set_password(const std::string &password) { this->password_ = password; } + void set_timeout(const uint64_t timeout) { this->timeout_ = timeout; } + void set_url(const std::string &url); + void set_username(const std::string &username) { this->username_ = username; } + + std::string md5_computed() { return this->md5_computed_; } + std::string md5_expected() { return this->md5_expected_; } + + bool check_status(); + + void flash(); + + virtual void http_init(const std::string &url){}; + virtual int http_read(uint8_t *buf, size_t len) { return 0; }; + virtual void http_end(){}; + + protected: + void cleanup_(std::unique_ptr backend); + uint8_t do_ota_(); + std::string get_url_with_auth_(const std::string &url); + bool http_get_md5_(); + bool secure_() { return this->url_.find("https:") != std::string::npos; }; + bool validate_url_(const std::string &url); + + std::string md5_computed_{}; + std::string md5_expected_{}; + std::string md5_url_{}; + std::string password_{}; + std::string username_{}; + std::string url_{}; + size_t body_length_ = 0; + size_t bytes_read_ = 0; + int status_ = -1; + uint64_t timeout_ = 0; + bool update_started_ = false; + const uint16_t http_recv_buffer_ = 256; // the firmware GET chunk size + const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS + // overhead) and must be a power of two from 512 to 4096 +}; + +} // namespace http_request +} // namespace esphome diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.cpp b/esphome/components/http_request/ota/ota_http_request_arduino.cpp new file mode 100644 index 0000000000..d1dc638d5e --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_arduino.cpp @@ -0,0 +1,134 @@ +#include "ota_http_request.h" +#include "watchdog.h" + +#ifdef USE_ARDUINO +#include "ota_http_request_arduino.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" +#include "esphome/components/network/util.h" +#include "esphome/components/md5/md5.h" + +namespace esphome { +namespace http_request { + +struct Header { + const char *name; + const char *value; +}; + +void OtaHttpRequestComponentArduino::http_init(const std::string &url) { + const char *header_keys[] = {"Content-Length", "Content-Type"}; + const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); + watchdog::WatchdogManager wdts; + +#ifdef USE_ESP8266 + if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { + ESP_LOGE(TAG, "Unable to set client"); + return; + } +#endif // USE_ESP8266 + +#ifdef USE_RP2040 + this->client_.setInsecure(); +#endif + + App.feed_wdt(); + +#if defined(USE_ESP32) || defined(USE_RP2040) + this->status_ = this->client_.begin(url.c_str()); +#endif +#ifdef USE_ESP8266 + this->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + this->status_ = this->client_.begin(*this->stream_ptr_, url.c_str()); +#endif + + if (!this->status_) { + this->client_.end(); + return; + } + + this->client_.setReuse(true); + + // returned needed headers must be collected before the requests + this->client_.collectHeaders(header_keys, header_count); + + // HTTP GET + this->status_ = this->client_.GET(); + + this->body_length_ = (size_t) this->client_.getSize(); + +#if defined(USE_ESP32) || defined(USE_RP2040) + if (this->stream_ptr_ == nullptr) { + this->set_stream_ptr_(); + } +#endif +} + +int OtaHttpRequestComponentArduino::http_read(uint8_t *buf, const size_t max_len) { +#ifdef USE_ESP8266 +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if (!this->secure_()) { + ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " + "in your YAML, or use HTTPS"); + } +#endif // USE_ARDUINO_VERSION_CODE +#endif // USE_ESP8266 + + watchdog::WatchdogManager wdts; + + // Since arduino8266 >= 3.1 using this->stream_ptr_ is broken (https://github.com/esp8266/Arduino/issues/9035) + WiFiClient *stream_ptr = this->client_.getStreamPtr(); + if (stream_ptr == nullptr) { + ESP_LOGE(TAG, "Stream pointer vanished!"); + return -1; + } + + int available_data = stream_ptr->available(); + int bufsize = std::min((int) max_len, available_data); + if (bufsize > 0) { + stream_ptr->readBytes(buf, bufsize); + this->bytes_read_ += bufsize; + buf[bufsize] = '\0'; // not fed to ota + } + + return bufsize; +} + +void OtaHttpRequestComponentArduino::http_end() { + watchdog::WatchdogManager wdts; + this->client_.end(); +} + +int OtaHttpRequestComponentArduino::set_stream_ptr_() { +#ifdef USE_ESP8266 +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (this->secure_()) { + ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + this->stream_ptr_ = std::make_unique(); + WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); + secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); + secure_client->setInsecure(); + } else { + this->stream_ptr_ = std::make_unique(); + } +#else + ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); + if (this->secure_()) { + ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); + return -1; + } + this->stream_ptr_ = std::make_unique(); +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS +#endif // USE_ESP8266 + +#if defined(USE_ESP32) || defined(USE_RP2040) + this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); +#endif + return 0; +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.h b/esphome/components/http_request/ota/ota_http_request_arduino.h new file mode 100644 index 0000000000..02bc046520 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_arduino.h @@ -0,0 +1,42 @@ +#pragma once + +#include "ota_http_request.h" + +#ifdef USE_ARDUINO +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" + +#include +#include +#include + +#if defined(USE_ESP32) || defined(USE_RP2040) +#include +#endif +#ifdef USE_ESP8266 +#include +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS +#include +#endif +#endif + +namespace esphome { +namespace http_request { + +class OtaHttpRequestComponentArduino : public OtaHttpRequestComponent { + public: + void http_init(const std::string &url) override; + int http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + int set_stream_ptr_(); + HTTPClient client_{}; + std::unique_ptr stream_ptr_; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_idf.cpp b/esphome/components/http_request/ota/ota_http_request_idf.cpp new file mode 100644 index 0000000000..9fa565d9bb --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_idf.cpp @@ -0,0 +1,86 @@ +#include "ota_http_request_idf.h" +#include "watchdog.h" + +#ifdef USE_ESP_IDF +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#include "esphome/components/md5/md5.h" +#include "esphome/components/network/util.h" + +#include "esp_event.h" +#include "esp_http_client.h" +#include "esp_idf_version.h" +#include "esp_log.h" +#include "esp_netif.h" +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "esp_tls.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs_flash.h" + +#include +#include +#include +#include +#include +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +namespace esphome { +namespace http_request { + +void OtaHttpRequestComponentIDF::http_init(const std::string &url) { + App.feed_wdt(); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + esp_http_client_config_t config = {nullptr}; + config.url = url.c_str(); + config.method = HTTP_METHOD_GET; + config.timeout_ms = (int) this->timeout_; + config.buffer_size = this->max_http_recv_buffer_; + config.auth_type = HTTP_AUTH_TYPE_BASIC; + config.max_authorization_retries = -1; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + if (this->secure_()) { + config.crt_bundle_attach = esp_crt_bundle_attach; + } +#endif +#pragma GCC diagnostic pop + + watchdog::WatchdogManager wdts; + this->client_ = esp_http_client_init(&config); + if ((this->status_ = esp_http_client_open(this->client_, 0)) == ESP_OK) { + this->body_length_ = esp_http_client_fetch_headers(this->client_); + this->status_ = esp_http_client_get_status_code(this->client_); + } +} + +int OtaHttpRequestComponentIDF::http_read(uint8_t *buf, const size_t max_len) { + watchdog::WatchdogManager wdts; + int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); + + App.feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + if (read_len > 0) { + this->bytes_read_ += bufsize; + buf[bufsize] = '\0'; // not fed to ota + } + + return read_len; +} + +void OtaHttpRequestComponentIDF::http_end() { + watchdog::WatchdogManager wdts; + + esp_http_client_close(this->client_); + esp_http_client_cleanup(this->client_); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/ota_http_request_idf.h b/esphome/components/http_request/ota/ota_http_request_idf.h new file mode 100644 index 0000000000..9783b2a3e1 --- /dev/null +++ b/esphome/components/http_request/ota/ota_http_request_idf.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ota_http_request.h" + +#ifdef USE_ESP_IDF +#include "esp_http_client.h" + +namespace esphome { +namespace http_request { + +class OtaHttpRequestComponentIDF : public OtaHttpRequestComponent { + public: + void http_init(const std::string &url) override; + int http_read(uint8_t *buf, size_t len) override; + void http_end() override; + + protected: + esp_http_client_handle_t client_{}; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/watchdog.cpp b/esphome/components/http_request/ota/watchdog.cpp new file mode 100644 index 0000000000..663c9afaac --- /dev/null +++ b/esphome/components/http_request/ota/watchdog.cpp @@ -0,0 +1,71 @@ +#include "watchdog.h" + +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + +#include "esphome/core/application.h" +#include "esphome/core/log.h" + +#include +#include +#ifdef USE_ESP32 +#include "esp_idf_version.h" +#include "esp_task_wdt.h" +#endif +#ifdef USE_RP2040 +#include "hardware/watchdog.h" +#include "pico/stdlib.h" +#endif + +namespace esphome { +namespace http_request { +namespace watchdog { + +static const char *const TAG = "watchdog.http_request.ota"; + +WatchdogManager::WatchdogManager() { + this->saved_timeout_ms_ = this->get_timeout_(); + this->set_timeout_(USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT); +} + +WatchdogManager::~WatchdogManager() { this->set_timeout_(this->saved_timeout_ms_); } + +void WatchdogManager::set_timeout_(uint32_t timeout_ms) { + ESP_LOGV(TAG, "Adjusting WDT to %" PRIu32 "ms", timeout_ms); +#ifdef USE_ESP32 +#if ESP_IDF_VERSION_MAJOR >= 5 + esp_task_wdt_config_t wdt_config = { + .timeout_ms = timeout_ms, + .idle_core_mask = 0x03, + .trigger_panic = true, + }; + esp_task_wdt_reconfigure(&wdt_config); +#else + esp_task_wdt_init(timeout_ms, true); +#endif // ESP_IDF_VERSION_MAJOR +#endif // USE_ESP32 + +#ifdef USE_RP2040 + watchdog_enable(timeout_ms, true); +#endif +} + +uint32_t WatchdogManager::get_timeout_() { + uint32_t timeout_ms = 0; + +#ifdef USE_ESP32 + timeout_ms = (uint32_t) CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000; +#endif // USE_ESP32 + +#ifdef USE_RP2040 + timeout_ms = watchdog_get_count() / 1000; +#endif + + ESP_LOGVV(TAG, "get_timeout: %" PRIu32 "ms", timeout_ms); + + return timeout_ms; +} + +} // namespace watchdog +} // namespace http_request +} // namespace esphome +#endif diff --git a/esphome/components/http_request/ota/watchdog.h b/esphome/components/http_request/ota/watchdog.h new file mode 100644 index 0000000000..0a09dcd6fa --- /dev/null +++ b/esphome/components/http_request/ota/watchdog.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/core/defines.h" + +#include + +namespace esphome { +namespace http_request { +namespace watchdog { + +class WatchdogManager { +#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT + public: + WatchdogManager(); + ~WatchdogManager(); + + private: + uint32_t get_timeout_(); + void set_timeout_(uint32_t timeout_ms); + + uint32_t saved_timeout_ms_{0}; +#endif +}; + +} // namespace watchdog +} // namespace http_request +} // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c2ad0f641c..76b6af6592 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -33,6 +33,7 @@ #define USE_GRAPH #define USE_GRAPHICAL_DISPLAY_MENU #define USE_HOMEASSISTANT_TIME +#define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT #define USE_JSON #define USE_LIGHT #define USE_LOCK diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common_http_request.yaml similarity index 95% rename from tests/components/http_request/common.yaml rename to tests/components/http_request/common_http_request.yaml index 848fe3f509..b00768c736 100644 --- a/tests/components/http_request/common.yaml +++ b/tests/components/http_request/common_http_request.yaml @@ -28,10 +28,6 @@ esphome: body: "Some data" verify_ssl: false -wifi: - ssid: MySSID - password: password1 - http_request: useragent: esphome/tagreader timeout: 10s diff --git a/tests/components/http_request/common_ota.yaml b/tests/components/http_request/common_ota.yaml new file mode 100644 index 0000000000..10e7d54c3f --- /dev/null +++ b/tests/components/http_request/common_ota.yaml @@ -0,0 +1,36 @@ +wifi: + ssid: MySSID + password: password1 + +ota: + - platform: http_request + verify_ssl: ${verify_ssl} + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota_http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test-nossl.esp8266.yaml b/tests/components/http_request/test-nossl.esp8266.yaml new file mode 100644 index 0000000000..65116d5550 --- /dev/null +++ b/tests/components/http_request/test-nossl.esp8266.yaml @@ -0,0 +1,38 @@ +<<: !include common_http_request.yaml + +wifi: + ssid: MySSID + password: password1 + +ota: + - platform: http_request + esp8266_disable_ssl_support: true + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota_http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test.esp32-c3-idf.yaml b/tests/components/http_request/test.esp32-c3-idf.yaml new file mode 100644 index 0000000000..da629e83a9 --- /dev/null +++ b/tests/components/http_request/test.esp32-c3-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "true" + +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp32-c3.yaml +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32-idf.yaml b/tests/components/http_request/test.esp32-idf.yaml new file mode 100644 index 0000000000..da629e83a9 --- /dev/null +++ b/tests/components/http_request/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "true" + +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp32.yaml +++ b/tests/components/http_request/test.esp32.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml index 25cb37a0b4..1f597bb500 100644 --- a/tests/components/http_request/test.esp8266.yaml +++ b/tests/components/http_request/test.esp8266.yaml @@ -1,2 +1,5 @@ -packages: - common: !include common.yaml +substitutions: + verify_ssl: "false" + +<<: !include common_http_request.yaml +<<: !include common_ota.yaml diff --git a/tests/components/http_request/test.rp2040.yaml b/tests/components/http_request/test.rp2040.yaml new file mode 100644 index 0000000000..077e4d82da --- /dev/null +++ b/tests/components/http_request/test.rp2040.yaml @@ -0,0 +1,4 @@ +substitutions: + verify_ssl: "false" + +<<: !include common_ota.yaml From ccab57fc583189976248b7574eb4ca448860b16a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:30:49 +1200 Subject: [PATCH 21/30] [logger] Fix defines for development (#6870) * [logger] Fix defines for development * Set debugging flags for rp2040 --- esphome/components/logger/__init__.py | 27 ++++++++++++++++++++------- esphome/core/defines.h | 9 +++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index c05f3d54aa..99aa39c4ba 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -112,11 +112,18 @@ HARDWARE_UART_TO_UART_SELECTION = { } HARDWARE_UART_TO_SERIAL = { - UART0: cg.global_ns.Serial, - UART0_SWAP: cg.global_ns.Serial, - UART1: cg.global_ns.Serial1, - UART2: cg.global_ns.Serial2, - DEFAULT: cg.global_ns.Serial, + PLATFORM_ESP8266: { + UART0: cg.global_ns.Serial, + UART0_SWAP: cg.global_ns.Serial, + UART1: cg.global_ns.Serial1, + UART2: cg.global_ns.Serial2, + DEFAULT: cg.global_ns.Serial, + }, + PLATFORM_RP2040: { + UART0: cg.global_ns.Serial1, + UART1: cg.global_ns.Serial2, + USB_CDC: cg.global_ns.Serial, + }, } is_log_level = cv.one_of(*LOG_LEVELS, upper=True) @@ -244,8 +251,14 @@ async def to_code(config): is_at_least_very_verbose = this_severity >= very_verbose_severity has_serial_logging = baud_rate != 0 - if CORE.is_esp8266 and has_serial_logging and is_at_least_verbose: - debug_serial_port = HARDWARE_UART_TO_SERIAL[config.get(CONF_HARDWARE_UART)] + if ( + (CORE.is_esp8266 or CORE.is_rp2040) + and has_serial_logging + and is_at_least_verbose + ): + debug_serial_port = HARDWARE_UART_TO_SERIAL[CORE.target_platform][ + config.get(CONF_HARDWARE_UART) + ] cg.add_build_flag(f"-DDEBUG_ESP_PORT={debug_serial_port}") cg.add_build_flag("-DLWIP_DEBUG") DEBUG_COMPONENTS = { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 76b6af6592..affcd78089 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -101,6 +101,14 @@ #ifdef USE_ESP_IDF #define USE_ESP_IDF_VERSION_CODE VERSION_CODE(4, 4, 2) #endif + +#if defined(USE_ESP32_VARIANT_ESP32S2) +#define USE_LOGGER_USB_CDC +#elif defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \ + defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2) +#define USE_LOGGER_USB_CDC +#define USE_LOGGER_USB_SERIAL_JTAG +#endif #endif // ESP8266-specific feature flags @@ -123,6 +131,7 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) +#define USE_LOGGER_USB_CDC #define USE_SOCKET_IMPL_LWIP_TCP #define USE_SPI #endif From 276eea2b69f71a91dd87c672ad8c72d8883592a3 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 7 Jun 2024 12:36:07 -0700 Subject: [PATCH 22/30] [docker] Avoid unsafe git error when container user and file config volume permissions don't match (#6873) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f6234235f7..36be700f55 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -101,7 +101,7 @@ RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "a && /platformio_install_deps.py /platformio.ini --libraries # Avoid unsafe git error when container user and file config volume permissions don't match -RUN git config --system --add safe.directory '/config/*' +RUN git config --system --add safe.directory '*' # ======================= docker-type image ======================= From 861a23d039cdc3900087958fb0586bffd790fd7c Mon Sep 17 00:00:00 2001 From: RFDarter Date: Fri, 7 Jun 2024 21:37:05 +0200 Subject: [PATCH 23/30] [datetime] Add logs on DateCall perform (#6868) --- esphome/components/datetime/date_entity.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index 19399c1e59..b5bcef43af 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -80,6 +80,17 @@ void DateCall::validate_() { void DateCall::perform() { this->validate_(); + ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + + if (this->year_.has_value()) { + ESP_LOGD(TAG, " Year: %d", *this->year_); + } + if (this->month_.has_value()) { + ESP_LOGD(TAG, " Month: %d", *this->month_); + } + if (this->day_.has_value()) { + ESP_LOGD(TAG, " Day: %d", *this->day_); + } this->parent_->control(*this); } From 8718e15a6a6dc56323e8e1ce1163da8b6eec9e9f Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Fri, 7 Jun 2024 21:43:22 +0200 Subject: [PATCH 24/30] fix: arduino media player sets wrong state for announcements (#6849) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 11 ++++++++--- .../i2s_audio/media_player/i2s_audio_media_player.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index 1890e27bdf..ef494fac2e 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp @@ -27,6 +27,11 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->start(); } } + + if (this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { + this->is_announcement_ = true; + } + if (call.get_volume().has_value()) { this->volume = call.get_volume().value(); this->set_volume_(volume); @@ -171,9 +176,8 @@ void I2SAudioMediaPlayer::start_() { if (this->current_url_.has_value()) { this->audio_->connecttohost(this->current_url_.value().c_str()); this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; - if (this->is_announcement_.has_value()) { - this->state = this->is_announcement_.value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING - : media_player::MEDIA_PLAYER_STATE_PLAYING; + if (this->is_announcement_) { + this->state = media_player::MEDIA_PLAYER_STATE_ANNOUNCING; } this->publish_state(); } @@ -202,6 +206,7 @@ void I2SAudioMediaPlayer::stop_() { this->high_freq_.stop(); this->state = media_player::MEDIA_PLAYER_STATE_IDLE; this->publish_state(); + this->is_announcement_ = false; } media_player::MediaPlayerTraits I2SAudioMediaPlayer::get_traits() { diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h index d7d9b1f74a..5afe778122 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h @@ -78,7 +78,7 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer, HighFrequencyLoopRequester high_freq_; optional current_url_{}; - optional is_announcement_{}; + bool is_announcement_{false}; }; } // namespace i2s_audio From d77ea461571e338ee1344f56e225fd4de26d66c7 Mon Sep 17 00:00:00 2001 From: RFDarter Date: Fri, 7 Jun 2024 22:29:10 +0200 Subject: [PATCH 25/30] [datetime] datetime-datetime strptime support value string without seconds (#6867) --- esphome/core/time.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index add671701f..f7aa4fdddb 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -84,6 +84,16 @@ bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { esp_time.hour = hour; esp_time.minute = minute; esp_time.second = second; + } else if (sscanf(time_to_parse.c_str(), "%04hu-%02hhu-%02hhu %02hhu:%02hhu %n", &year, &month, &day, // NOLINT + &hour, // NOLINT + &minute, &num) == 5 && // NOLINT + num == time_to_parse.size()) { + esp_time.year = year; + esp_time.month = month; + esp_time.day_of_month = day; + esp_time.hour = hour; + esp_time.minute = minute; + esp_time.second = 0; } else if (sscanf(time_to_parse.c_str(), "%02hhu:%02hhu:%02hhu %n", &hour, &minute, &second, &num) == 3 && // NOLINT num == time_to_parse.size()) { esp_time.hour = hour; From 38b7bed2faa522e7e065d8362d6ea0bcaf1c64d5 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sat, 8 Jun 2024 21:55:57 +1200 Subject: [PATCH 26/30] Update webserver local assets to 20240608-093147 (#6874) --- .../components/web_server/server_index_v2.h | 1231 +++++++++-------- .../components/web_server/server_index_v3.h | 721 +++++----- 2 files changed, 977 insertions(+), 975 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 31c2d1fd85..7417f37015 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -11,623 +11,624 @@ namespace web_server { const uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0x7d, 0xd9, 0x92, 0xdb, 0x46, 0xb6, 0xe0, 0xf3, - 0xdc, 0xaf, 0x40, 0xc1, 0xd5, 0x25, 0x64, 0x33, 0x89, 0x22, 0x59, 0xda, 0x0c, 0x56, 0x92, 0x5d, 0x2a, 0xc9, 0x2d, - 0xbb, 0xb5, 0xd8, 0x2a, 0xc9, 0x6e, 0x9b, 0x66, 0x57, 0xa1, 0x88, 0x24, 0x99, 0x16, 0x88, 0xa4, 0x13, 0xc9, 0x5a, + 0xdc, 0xaf, 0x40, 0xa5, 0xab, 0x4b, 0xc8, 0x66, 0x12, 0x45, 0xb2, 0xb4, 0x19, 0xac, 0x24, 0xbb, 0x54, 0x92, 0x5b, + 0x76, 0x6b, 0xb1, 0x55, 0x92, 0xdd, 0x36, 0xcd, 0xae, 0x42, 0x11, 0x49, 0x32, 0x2d, 0x10, 0x49, 0x03, 0xc9, 0x5a, 0x4c, 0xe2, 0xc6, 0x7c, 0xc0, 0x44, 0x4c, 0xc4, 0x3c, 0xcd, 0xcb, 0xc4, 0xdc, 0x87, 0xf9, 0x88, 0x79, 0xbe, 0x9f, 0x72, 0x7f, 0x60, 0xe6, 0x13, 0x26, 0x4e, 0x2e, 0x40, 0x82, 0x4b, 0xa9, 0xbc, 0xdc, 0x1b, 0x13, 0x0a, 0x49, 0x44, - 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0x09, 0x1f, 0xc9, 0xdb, 0x39, 0xf5, 0xa6, 0x72, 0x96, 0xf6, - 0x8e, 0xcd, 0xbf, 0x34, 0x4e, 0x7a, 0xc7, 0x29, 0xcb, 0x3e, 0x7a, 0x82, 0xa6, 0x84, 0x8d, 0x78, 0xe6, 0x4d, 0x05, - 0x1d, 0x93, 0x24, 0x96, 0x71, 0xc4, 0x66, 0xf1, 0x84, 0x7a, 0x87, 0xbd, 0xe3, 0x19, 0x95, 0xb1, 0x37, 0x9a, 0xc6, - 0x22, 0xa7, 0x92, 0x7c, 0x78, 0xff, 0x45, 0xf3, 0x69, 0xef, 0x38, 0x1f, 0x09, 0x36, 0x97, 0x1e, 0x0c, 0x49, 0x66, - 0x3c, 0x59, 0xa4, 0xb4, 0x77, 0x78, 0x78, 0x7d, 0x7d, 0x1d, 0xfe, 0x94, 0xff, 0xd3, 0x88, 0x67, 0xb9, 0xf4, 0x5e, - 0x91, 0x6b, 0x96, 0x25, 0xfc, 0x1a, 0x53, 0x49, 0x5e, 0x85, 0x67, 0xd3, 0x38, 0xe1, 0xd7, 0xef, 0x38, 0x97, 0x07, - 0x07, 0x81, 0x7e, 0xbc, 0x3d, 0x3d, 0x3b, 0x23, 0x84, 0x5c, 0x71, 0x96, 0x78, 0xad, 0xd5, 0xaa, 0x2a, 0x0c, 0xb3, - 0x58, 0xb2, 0x2b, 0xaa, 0xbb, 0xa0, 0x83, 0x03, 0x3f, 0x4e, 0xf8, 0x5c, 0xd2, 0xe4, 0x4c, 0xde, 0xa6, 0xf4, 0x6c, - 0x4a, 0xa9, 0xcc, 0x7d, 0x96, 0x79, 0xcf, 0xf9, 0x68, 0x31, 0xa3, 0x99, 0x0c, 0xe7, 0x82, 0x4b, 0x0e, 0x90, 0x1c, - 0x1c, 0xf8, 0x82, 0xce, 0xd3, 0x78, 0x44, 0xa1, 0xfe, 0xf4, 0xec, 0xac, 0xea, 0x51, 0x35, 0xc2, 0x4c, 0x92, 0xb3, - 0xdb, 0xd9, 0x25, 0x4f, 0x03, 0x84, 0x53, 0x49, 0x32, 0x7a, 0xed, 0x7d, 0x47, 0xe3, 0x8f, 0xaf, 0xe3, 0x79, 0x77, - 0x94, 0xc6, 0x79, 0xee, 0x5d, 0xca, 0xa5, 0x5a, 0x82, 0x58, 0x8c, 0x24, 0x17, 0x81, 0xc4, 0x14, 0x33, 0xb4, 0x64, - 0xe3, 0x40, 0x4e, 0x59, 0x1e, 0x9e, 0xef, 0x8f, 0xf2, 0xfc, 0x1d, 0xcd, 0x17, 0xa9, 0xdc, 0x27, 0x7b, 0x2d, 0xcc, - 0xf6, 0x08, 0x61, 0x12, 0xc9, 0xa9, 0xe0, 0xd7, 0xde, 0x0b, 0x21, 0xb8, 0x08, 0xfc, 0xd3, 0xb3, 0x33, 0xdd, 0xc2, - 0x63, 0xb9, 0x97, 0x71, 0xe9, 0x95, 0xe3, 0xc5, 0x97, 0x29, 0x0d, 0xbd, 0x0f, 0x39, 0xf5, 0x2e, 0x16, 0x59, 0x1e, - 0x8f, 0xe9, 0xe9, 0xd9, 0xd9, 0x85, 0xc7, 0x85, 0x77, 0x31, 0xca, 0xf3, 0x0b, 0x8f, 0x65, 0xb9, 0xa4, 0x71, 0x12, - 0xfa, 0xa8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x7a, 0x23, 0x89, 0xc4, 0xea, 0x51, 0x12, 0x5a, 0x4c, 0xa8, 0xf4, - 0xf2, 0x72, 0x5d, 0x01, 0x5a, 0xa6, 0x54, 0x7a, 0x92, 0xa8, 0x7a, 0xde, 0xd5, 0xb8, 0xa7, 0xfa, 0x51, 0x76, 0xd9, - 0x38, 0xa0, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0x46, 0x7a, 0x69, 0x1e, 0x23, 0x74, 0xcf, 0x96, 0x1d, 0x1c, 0xd0, 0x30, - 0xa5, 0xd9, 0x44, 0x4e, 0x09, 0x21, 0xed, 0x2e, 0x3b, 0x38, 0x08, 0x24, 0x49, 0x65, 0x38, 0xa1, 0x32, 0xa0, 0x08, - 0xe1, 0xaa, 0xf7, 0xc1, 0x41, 0xa0, 0x91, 0xc0, 0x89, 0x46, 0x5c, 0x0d, 0xc7, 0x28, 0x34, 0xd8, 0x3f, 0xbb, 0xcd, - 0x46, 0x81, 0x0b, 0x3f, 0xc2, 0xec, 0xe0, 0x20, 0x95, 0x61, 0x0e, 0x23, 0x62, 0x89, 0x50, 0x21, 0xa8, 0x5c, 0x88, - 0xcc, 0x93, 0x85, 0xe4, 0x67, 0x52, 0xb0, 0x6c, 0x12, 0xa0, 0xa5, 0x2d, 0x73, 0x3a, 0x16, 0x85, 0x06, 0xf7, 0x6b, - 0x49, 0x04, 0xe9, 0xc1, 0x8c, 0x97, 0x32, 0x80, 0x5d, 0xe4, 0x63, 0x4f, 0x10, 0xe2, 0xe7, 0xaa, 0xaf, 0xdf, 0x17, - 0x91, 0x68, 0xf8, 0x3e, 0xd6, 0x50, 0x62, 0x26, 0x11, 0xfe, 0x48, 0x02, 0x81, 0xc3, 0x30, 0x94, 0x88, 0xf4, 0x96, - 0x16, 0x2b, 0xc2, 0x59, 0x67, 0x5f, 0x0c, 0x5a, 0xc3, 0x48, 0x86, 0x82, 0x26, 0x8b, 0x11, 0x0d, 0x02, 0x86, 0x73, - 0x9c, 0x21, 0xd2, 0x63, 0x8d, 0x80, 0x93, 0x1e, 0x6c, 0x37, 0xaf, 0xef, 0x35, 0x21, 0x7b, 0x2d, 0x64, 0x60, 0xe4, - 0x16, 0x40, 0xc0, 0xb0, 0x81, 0x87, 0x13, 0xe2, 0x67, 0x8b, 0xd9, 0x25, 0x15, 0x7e, 0xd9, 0xac, 0x5b, 0x23, 0x8b, - 0x45, 0x4e, 0xbd, 0x51, 0x9e, 0x7b, 0xe3, 0x45, 0x36, 0x92, 0x8c, 0x67, 0x9e, 0xdf, 0xe0, 0x0d, 0x5f, 0x93, 0x43, - 0x49, 0x0d, 0x3e, 0x2a, 0x50, 0x90, 0xa3, 0x86, 0x18, 0x64, 0x8d, 0xf6, 0x10, 0x03, 0x94, 0xa8, 0x6b, 0xc6, 0x33, - 0x08, 0xa0, 0x58, 0xc0, 0x1a, 0x0b, 0xfc, 0x41, 0xc2, 0x2a, 0xd5, 0x12, 0xa9, 0xec, 0x8b, 0x70, 0xf3, 0xa0, 0x10, - 0x19, 0xce, 0xe2, 0x79, 0x40, 0x49, 0x8f, 0x2a, 0xe2, 0x8a, 0xb3, 0x11, 0xc0, 0x5a, 0xdb, 0xb7, 0x3e, 0x8d, 0x68, - 0x58, 0x91, 0x14, 0x8a, 0x64, 0x38, 0xe6, 0xe2, 0x45, 0x3c, 0x9a, 0x42, 0xbf, 0x92, 0x60, 0x12, 0x7b, 0xde, 0x46, - 0x82, 0xc6, 0x92, 0xbe, 0x48, 0x29, 0x3c, 0x05, 0xbe, 0xea, 0xe9, 0x23, 0x9c, 0x93, 0x57, 0x61, 0xca, 0xe4, 0x1b, - 0x9e, 0x8d, 0x68, 0x37, 0x77, 0xa8, 0x8b, 0xc1, 0xbe, 0x9f, 0x48, 0x29, 0xd8, 0xe5, 0x42, 0xd2, 0xc0, 0xcf, 0xa0, - 0x85, 0x8f, 0x73, 0x84, 0x59, 0x28, 0xe9, 0x8d, 0x3c, 0xe5, 0x99, 0xa4, 0x99, 0x24, 0xd4, 0x22, 0x15, 0x8b, 0x30, - 0x9e, 0xcf, 0x69, 0x96, 0x9c, 0x4e, 0x59, 0x9a, 0x04, 0x0c, 0x15, 0xa8, 0xc0, 0xb1, 0x24, 0xb0, 0x46, 0xd2, 0x13, - 0x11, 0xfc, 0xb3, 0x7b, 0x35, 0x81, 0x24, 0x3d, 0x75, 0x28, 0x28, 0xf1, 0xfd, 0xee, 0x98, 0x8b, 0xc0, 0xac, 0xc0, - 0xe3, 0x63, 0x4f, 0xc2, 0x1c, 0xef, 0x16, 0x29, 0xcd, 0x11, 0x6d, 0x10, 0x56, 0x6e, 0xa3, 0x41, 0xf0, 0xd7, 0x40, - 0xf1, 0x05, 0x0a, 0x04, 0x8a, 0x44, 0xf7, 0x2a, 0x16, 0xde, 0x17, 0xe6, 0x44, 0xfd, 0x64, 0xb9, 0xd9, 0x54, 0x92, - 0x9f, 0x42, 0x29, 0x16, 0xb9, 0xa4, 0xc9, 0xfb, 0xdb, 0x39, 0xcd, 0xf1, 0x4b, 0x49, 0xa6, 0xb2, 0x3f, 0x95, 0x21, - 0x9d, 0xcd, 0xe5, 0xed, 0x99, 0x62, 0x8c, 0x91, 0xef, 0xe3, 0x11, 0xb4, 0x14, 0x34, 0x1e, 0x01, 0x33, 0x33, 0xd8, - 0xfa, 0x9a, 0xa7, 0xb7, 0x63, 0x96, 0xa6, 0x67, 0x8b, 0xf9, 0x9c, 0x0b, 0x89, 0xff, 0x4a, 0x96, 0x92, 0x57, 0xa8, - 0x81, 0xbd, 0x5c, 0xe6, 0xd7, 0x4c, 0x8e, 0xa6, 0x81, 0x44, 0xcb, 0x51, 0x9c, 0x53, 0xef, 0x19, 0xe7, 0x29, 0x8d, - 0xb3, 0x48, 0x10, 0xd1, 0x7f, 0x29, 0xa3, 0x6c, 0x91, 0xa6, 0xdd, 0x4b, 0x41, 0xe3, 0x8f, 0x5d, 0x55, 0xfd, 0xf6, - 0xf2, 0x27, 0x3a, 0x92, 0x91, 0xfa, 0x7d, 0x22, 0x44, 0x7c, 0x0b, 0x0d, 0x09, 0x81, 0x66, 0x7d, 0x11, 0x7d, 0x75, - 0xf6, 0xf6, 0x4d, 0xa8, 0x0f, 0x09, 0x1b, 0xdf, 0x06, 0xa2, 0x3c, 0x78, 0xa2, 0xc0, 0x63, 0xc1, 0x67, 0x6b, 0x53, - 0x6b, 0xac, 0x89, 0xee, 0x0e, 0x10, 0x28, 0x11, 0x7b, 0x7a, 0x68, 0x17, 0x82, 0x37, 0x8a, 0xe6, 0xa1, 0x92, 0x98, - 0x79, 0xe1, 0x9f, 0x48, 0x17, 0x07, 0x02, 0xdd, 0x0d, 0xad, 0x14, 0xb7, 0x4b, 0x4a, 0x14, 0x9c, 0x73, 0x90, 0x30, - 0x00, 0xe3, 0x28, 0x96, 0xa3, 0xe9, 0x92, 0xaa, 0xc1, 0x0a, 0x0b, 0x31, 0x2d, 0x0a, 0x7c, 0x5d, 0xd2, 0xbb, 0xdc, - 0x23, 0x44, 0x28, 0x46, 0x45, 0xe4, 0x6a, 0x25, 0x08, 0x11, 0x08, 0x7f, 0x47, 0x96, 0xb1, 0x5d, 0x4f, 0xb4, 0xd7, - 0xc2, 0x70, 0x2e, 0x23, 0xcd, 0x5d, 0xf0, 0x88, 0x67, 0x57, 0x54, 0x48, 0x2a, 0xa2, 0xbf, 0x62, 0x41, 0xc7, 0x29, - 0x40, 0xb1, 0xd7, 0xc6, 0xd3, 0x38, 0x3f, 0x9d, 0xc6, 0xd9, 0x84, 0x26, 0xd1, 0xb5, 0x2c, 0xf0, 0xdf, 0x89, 0x3f, - 0x66, 0x59, 0x9c, 0xb2, 0x5f, 0x68, 0xe2, 0x1b, 0x69, 0x70, 0xe2, 0xd1, 0x1b, 0x49, 0xb3, 0x24, 0xf7, 0x5e, 0xbe, - 0x7f, 0xfd, 0xca, 0xec, 0x63, 0x4d, 0x40, 0xa0, 0x65, 0xbe, 0x98, 0x53, 0x11, 0x20, 0x6c, 0x04, 0xc4, 0x0b, 0xa6, - 0x98, 0xe3, 0xeb, 0x78, 0xae, 0x4b, 0x58, 0xfe, 0x61, 0x9e, 0xc4, 0x92, 0x7e, 0x4d, 0xb3, 0x84, 0x65, 0x13, 0xb2, - 0xd7, 0xd6, 0xe5, 0xd3, 0xd8, 0x54, 0x24, 0x65, 0xd1, 0xf9, 0xfe, 0x8b, 0x54, 0xad, 0xbb, 0x7c, 0x5c, 0x04, 0xa8, - 0xc8, 0x65, 0x2c, 0xd9, 0xc8, 0x8b, 0x93, 0xe4, 0xcb, 0x8c, 0x49, 0xa6, 0x00, 0x14, 0xb0, 0x3d, 0x40, 0xa2, 0x54, - 0x8b, 0x0a, 0x0b, 0x78, 0x80, 0x70, 0x10, 0x18, 0x01, 0x30, 0x45, 0x66, 0xbf, 0x0e, 0x0e, 0x2a, 0x76, 0xdf, 0xa7, - 0x91, 0xae, 0x24, 0x83, 0x21, 0x0a, 0xe7, 0x8b, 0x1c, 0x36, 0xda, 0x4e, 0x01, 0xd2, 0x85, 0x5f, 0xe6, 0x54, 0x5c, - 0xd1, 0xa4, 0x24, 0x8e, 0x3c, 0x40, 0xcb, 0xb5, 0x39, 0xcc, 0xb1, 0x90, 0x64, 0x30, 0xec, 0xba, 0x7c, 0x9b, 0x1a, - 0x3a, 0x17, 0x7c, 0x4e, 0x85, 0x64, 0x34, 0x2f, 0x59, 0x49, 0x00, 0x52, 0xb4, 0x64, 0x27, 0x39, 0xb1, 0xeb, 0x9b, - 0x07, 0x0c, 0x53, 0x54, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0xc7, 0x0c, 0x61, 0xa9, 0x21, 0xcd, - 0x11, 0x2a, 0x10, 0x96, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xc9, 0x77, 0x4a, 0x54, 0x03, 0x43, - 0x8b, 0x25, 0x3d, 0x38, 0x08, 0x68, 0x58, 0x12, 0x05, 0xd9, 0x6b, 0x9b, 0x3d, 0x72, 0x90, 0xb5, 0x03, 0x6c, 0x98, - 0x58, 0x62, 0x8a, 0xf0, 0x1e, 0x0d, 0x33, 0x7e, 0x32, 0x1a, 0xd1, 0x3c, 0xe7, 0xe2, 0xe0, 0x60, 0x4f, 0xb5, 0x2f, - 0xb5, 0x09, 0xd8, 0xc3, 0xb7, 0xd7, 0x59, 0x05, 0x01, 0xaa, 0x24, 0xac, 0x91, 0x0b, 0x12, 0xe4, 0x94, 0x52, 0x38, - 0xfc, 0xbe, 0x55, 0x3c, 0x22, 0xff, 0xfc, 0xdc, 0x6f, 0x48, 0x6c, 0xd0, 0x30, 0xa1, 0x76, 0xea, 0xdb, 0xe7, 0x54, - 0xab, 0x56, 0x4a, 0xf1, 0xd8, 0xc0, 0x8c, 0x3e, 0x3f, 0x61, 0x42, 0xc7, 0x2c, 0x73, 0x96, 0x5d, 0x03, 0x09, 0x4b, - 0x9c, 0xa3, 0xc2, 0xd9, 0xd0, 0xad, 0x43, 0x2b, 0x9d, 0x46, 0xef, 0xdc, 0x72, 0xa2, 0xf4, 0x08, 0x67, 0x1b, 0x07, - 0x74, 0x58, 0x60, 0x85, 0x7a, 0xbb, 0x9a, 0x4c, 0x01, 0x3a, 0x90, 0xc3, 0xae, 0xa9, 0x27, 0xb9, 0xc6, 0x9c, 0xa0, - 0x3f, 0x2f, 0x68, 0x2e, 0x35, 0x1d, 0x07, 0x12, 0x67, 0x98, 0xa1, 0x02, 0x8e, 0xdb, 0x98, 0x4d, 0x16, 0x02, 0xd4, - 0x1d, 0x38, 0x8a, 0x34, 0x5b, 0xcc, 0xa8, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, 0xc4, 0x1c, 0x68, 0xfa, 0x6e, - 0x72, 0x02, 0x58, 0x25, 0x5a, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, 0x6b, 0x7b, 0xf2, 0x77, 0x64, - 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xd9, 0x6b, 0x95, 0x14, 0x6c, 0x70, 0xaa, 0x81, 0xd1, 0x28, 0x7c, - 0xab, 0x07, 0x42, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x9c, 0x6e, 0xd0, 0xe9, 0x94, 0x0c, 0x40, 0xcf, 0x08, 0xa7, 0xc3, - 0x5d, 0xc4, 0x64, 0xb9, 0x41, 0x20, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, 0x6b, 0x8b, 0xf0, 0xe7, 0x65, - 0x17, 0xbf, 0xa4, 0x31, 0x73, 0xcc, 0xab, 0x2a, 0xcc, 0x14, 0x30, 0xd5, 0x92, 0x9c, 0x21, 0xde, 0xc4, 0x33, 0x9a, - 0x07, 0x14, 0xe1, 0x5d, 0x0d, 0x34, 0x71, 0x42, 0x93, 0xa1, 0x23, 0x36, 0x73, 0x10, 0x9b, 0x0c, 0x69, 0xad, 0xac, - 0x7e, 0xdc, 0x72, 0x4c, 0x07, 0xf9, 0xb0, 0x52, 0xe6, 0x9c, 0xc5, 0x2b, 0x79, 0x6c, 0xa8, 0xdb, 0xe2, 0x4f, 0x97, - 0x69, 0xa4, 0x29, 0xa5, 0x21, 0x47, 0x78, 0xaf, 0xb5, 0xbe, 0x8f, 0xb6, 0x55, 0xb5, 0xc6, 0xc1, 0x10, 0xf6, 0x41, - 0x89, 0x8b, 0x90, 0xe5, 0xea, 0xff, 0xda, 0x39, 0x03, 0xb4, 0x9d, 0x01, 0x59, 0x84, 0xe3, 0x34, 0x96, 0x41, 0xfb, - 0xb0, 0x05, 0x9a, 0xe8, 0x15, 0x05, 0x69, 0x82, 0xd0, 0xe6, 0x52, 0x68, 0xb8, 0xc8, 0xf2, 0x29, 0x1b, 0xcb, 0x20, - 0x96, 0x8a, 0xa1, 0xd0, 0x34, 0xa7, 0x9e, 0xac, 0xe9, 0xc3, 0x8a, 0xd9, 0xc4, 0x40, 0x6a, 0xa5, 0xf2, 0x45, 0x2d, - 0xa4, 0x8a, 0x69, 0x01, 0x6f, 0xa8, 0x74, 0xe9, 0x8a, 0xc7, 0xd8, 0xd6, 0x0c, 0xf4, 0xc5, 0x76, 0x5f, 0x8f, 0x18, - 0x19, 0x56, 0xc0, 0x1c, 0x95, 0x95, 0x45, 0x2e, 0x7f, 0x30, 0x85, 0x32, 0x94, 0xfc, 0x15, 0xbf, 0xa6, 0xe2, 0x34, - 0x06, 0xe0, 0x23, 0xdd, 0xbd, 0xd0, 0x62, 0x40, 0x71, 0x7b, 0xd9, 0xb5, 0xf4, 0x72, 0xae, 0x16, 0xfe, 0xb5, 0xe0, - 0x33, 0x96, 0x53, 0xd0, 0xd4, 0x34, 0xfe, 0x33, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, 0xa1, 0x25, 0x7d, 0x9d, 0xbc, - 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x70, 0x60, 0xec, 0x09, 0x47, 0xca, 0x85, - 0x53, 0x64, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x52, 0x7d, 0x6c, 0x50, 0x11, 0x27, 0x09, 0x68, - 0x75, 0x82, 0xa7, 0xa9, 0x23, 0xa8, 0x30, 0xeb, 0x96, 0xa2, 0xe9, 0x7c, 0xff, 0xc5, 0xd9, 0x5d, 0xd2, 0x09, 0xea, - 0x5d, 0x01, 0x65, 0x01, 0xcd, 0x12, 0x2a, 0xc0, 0x8c, 0x74, 0x76, 0xcb, 0xc8, 0xd8, 0x53, 0x9e, 0x65, 0x74, 0x24, - 0x69, 0x02, 0x56, 0x0a, 0x23, 0x32, 0x9c, 0xf2, 0x5c, 0x96, 0x85, 0x15, 0xf4, 0xcc, 0x81, 0x9e, 0x85, 0xa3, 0x38, - 0x4d, 0x03, 0x6d, 0x91, 0xcc, 0xf8, 0x15, 0xdd, 0x02, 0x75, 0xb7, 0x06, 0x72, 0x39, 0x0c, 0x75, 0x86, 0xa1, 0x61, - 0x3e, 0x4f, 0xd9, 0x88, 0x96, 0x82, 0xeb, 0x2c, 0x64, 0x59, 0x42, 0x6f, 0x80, 0x8f, 0xa0, 0x5e, 0xaf, 0xd7, 0xc2, - 0x6d, 0x54, 0x68, 0x84, 0x2f, 0x37, 0x10, 0x7b, 0x87, 0xc8, 0x04, 0x22, 0x23, 0xbd, 0xe5, 0x36, 0x7e, 0x40, 0x91, - 0x23, 0x27, 0x99, 0xb5, 0xac, 0x34, 0x6f, 0x46, 0x38, 0xa1, 0x29, 0x95, 0xd4, 0xf2, 0x72, 0xd0, 0x9f, 0xf5, 0xd1, - 0x7d, 0x57, 0xe2, 0xaf, 0x24, 0x27, 0x7b, 0xca, 0xec, 0x9e, 0xe7, 0xa5, 0xa5, 0x5e, 0x6d, 0x4f, 0x85, 0xed, 0xbe, - 0xd4, 0xdb, 0x13, 0x4b, 0x19, 0x8f, 0xa6, 0xda, 0x44, 0x0f, 0x36, 0x96, 0x54, 0x8d, 0x61, 0xf8, 0x7a, 0x79, 0x88, - 0x3e, 0x58, 0x30, 0xb7, 0xa1, 0xe0, 0xcc, 0x30, 0x05, 0x0a, 0x56, 0x9f, 0xde, 0xb6, 0xd3, 0x38, 0x4d, 0x2f, 0xe3, - 0xd1, 0xc7, 0x3a, 0xf5, 0x57, 0x64, 0x40, 0xd6, 0xb9, 0xb1, 0x53, 0xe5, 0xb0, 0x2c, 0x77, 0xdd, 0x96, 0x4b, 0xd7, - 0x0e, 0x4a, 0xb0, 0xd7, 0xaa, 0xc8, 0xbe, 0xbe, 0xd1, 0x3b, 0xa9, 0x5d, 0x41, 0xc4, 0xcc, 0xca, 0x02, 0xe0, 0x02, - 0x9f, 0xa4, 0x38, 0xcb, 0x0f, 0x0c, 0xdd, 0x81, 0xad, 0x51, 0xac, 0x01, 0x22, 0xd1, 0xb2, 0x48, 0x58, 0xbe, 0x1b, - 0x03, 0x7f, 0x08, 0x94, 0xcf, 0x9d, 0x19, 0xee, 0x0b, 0x68, 0xc9, 0xe3, 0x8c, 0xca, 0x5c, 0x42, 0x66, 0xb4, 0x09, - 0xcb, 0x68, 0xfe, 0x06, 0x9a, 0x8b, 0xa2, 0xf7, 0xb7, 0xba, 0x0a, 0x74, 0x32, 0x80, 0x22, 0xef, 0xba, 0xca, 0x44, - 0x8d, 0x02, 0x0c, 0x4f, 0x65, 0x4a, 0xe4, 0x66, 0x35, 0xe3, 0xd1, 0xa8, 0xeb, 0xda, 0xfe, 0x36, 0x2c, 0x97, 0x93, - 0x20, 0x08, 0x72, 0xb0, 0xdf, 0xac, 0x5e, 0x5f, 0x2d, 0x22, 0xdf, 0x58, 0x44, 0x1e, 0x3a, 0x46, 0x16, 0xaa, 0x68, - 0xd9, 0xe9, 0x1e, 0xfd, 0x15, 0xb9, 0x8d, 0x40, 0x59, 0x0d, 0x81, 0x3f, 0xa3, 0x92, 0xdd, 0xa6, 0x44, 0x62, 0x6e, - 0x0c, 0x1c, 0x43, 0x69, 0xc0, 0x30, 0xaa, 0x2e, 0x19, 0xd2, 0x47, 0xa3, 0x66, 0xec, 0x66, 0x98, 0xa3, 0x35, 0xcd, - 0xbe, 0x28, 0x0c, 0x8e, 0x28, 0x32, 0x7b, 0x53, 0x53, 0x89, 0x1d, 0xac, 0xe0, 0x8c, 0x18, 0x35, 0x58, 0x6b, 0x3d, - 0xeb, 0xb8, 0x29, 0xc7, 0x85, 0x83, 0x5a, 0xa1, 0xa6, 0xa6, 0x4f, 0x5a, 0xc5, 0x2a, 0x43, 0x78, 0x6a, 0x35, 0x52, - 0x5e, 0xad, 0x9b, 0x10, 0xdf, 0x7a, 0x23, 0xfc, 0xfe, 0xb2, 0x66, 0x12, 0x46, 0x4e, 0xb3, 0x22, 0x02, 0x96, 0xca, - 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0xce, 0x5d, 0x84, 0x3b, 0x98, 0xcd, 0x34, 0xe7, 0xca, 0x86, - 0x64, 0x5a, 0xef, 0x1b, 0x50, 0xcc, 0xf5, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, 0x24, 0x08, 0x06, 0x6c, 0x0e, - 0xca, 0x9d, 0x2b, 0x1f, 0x02, 0x80, 0x9d, 0xad, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, 0x44, 0x61, 0x65, 0x14, 0xae, - 0x56, 0xd7, 0x12, 0x05, 0x46, 0xf3, 0xc5, 0x14, 0xf5, 0x2d, 0xc7, 0x3d, 0x79, 0x05, 0xad, 0x94, 0x22, 0x5a, 0x95, - 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, 0x54, 0xa1, 0x11, 0xd3, 0xd5, - 0x92, 0x4f, 0xcd, 0xd0, 0x0c, 0x21, 0x14, 0xe5, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, 0x1e, 0x1c, 0xe4, 0xce, 0x40, - 0xe7, 0x25, 0x9b, 0xf8, 0x29, 0x00, 0x91, 0x9c, 0xdf, 0x66, 0x4a, 0x77, 0xf9, 0xc9, 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, - 0xd5, 0x05, 0x6b, 0x3c, 0xbe, 0x8e, 0x99, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0x1e, 0x50, 0xb4, 0x34, 0xaa, 0x46, 0x28, - 0x28, 0x28, 0x8f, 0xc0, 0x13, 0xac, 0x0a, 0xad, 0xe9, 0x7e, 0x34, 0xa5, 0xe0, 0x08, 0xb6, 0x5a, 0x44, 0x69, 0x17, - 0xee, 0x19, 0x29, 0x62, 0x06, 0xde, 0x0e, 0x7b, 0xb1, 0xde, 0xbd, 0x66, 0x07, 0xcc, 0xa9, 0x18, 0x73, 0x31, 0xb3, - 0x75, 0xc5, 0xda, 0xb3, 0xe1, 0x8c, 0x6c, 0x1c, 0x6c, 0x1d, 0xdb, 0xa8, 0xff, 0xdd, 0x35, 0xa3, 0xbb, 0x32, 0xd7, - 0x6b, 0xa2, 0xb4, 0x94, 0xbe, 0xda, 0x1f, 0x68, 0x29, 0x33, 0x77, 0xcd, 0x7b, 0xe3, 0x4c, 0xed, 0x6a, 0x87, 0xc9, - 0x5e, 0xbb, 0x5b, 0xda, 0x7c, 0x96, 0x1a, 0xba, 0xda, 0xb1, 0x61, 0x44, 0x2a, 0x5f, 0xa4, 0x89, 0x01, 0x96, 0x21, - 0x4c, 0x0d, 0x1d, 0x5d, 0xb3, 0x34, 0xad, 0x4a, 0x7f, 0x0d, 0x5f, 0xcf, 0x0d, 0x5f, 0xcf, 0x2c, 0x5f, 0x07, 0x4e, - 0x01, 0x7c, 0x5d, 0x0f, 0x57, 0x75, 0xcf, 0x36, 0x4e, 0x67, 0xa6, 0x39, 0x7a, 0xae, 0xec, 0x68, 0x98, 0x6f, 0x61, - 0x21, 0x40, 0xa5, 0xe6, 0xf5, 0x31, 0x30, 0x4e, 0x18, 0x30, 0x00, 0xb5, 0x0b, 0x93, 0xba, 0x2e, 0x8a, 0x8f, 0x01, - 0xc2, 0x79, 0x41, 0x4b, 0xca, 0x3e, 0x79, 0x01, 0x4e, 0x3a, 0x67, 0x39, 0x20, 0xc4, 0x54, 0xf1, 0xaf, 0x52, 0xa2, - 0xec, 0xea, 0x98, 0x59, 0x5d, 0x6e, 0x57, 0x07, 0x9c, 0xbe, 0x5a, 0x5d, 0x72, 0x37, 0xaf, 0x57, 0xcb, 0x63, 0xe5, - 0xf2, 0xaa, 0xfd, 0x5e, 0xad, 0x82, 0xb5, 0x12, 0xf0, 0xdf, 0x1b, 0x13, 0x45, 0x94, 0xa3, 0x03, 0x0f, 0x70, 0x31, - 0x03, 0x05, 0x85, 0x5e, 0x74, 0x29, 0xe2, 0x5e, 0x7d, 0xca, 0xc1, 0xa3, 0xdc, 0xf4, 0xba, 0xff, 0x29, 0x9f, 0xcd, - 0x41, 0x1b, 0x5b, 0x23, 0xe9, 0x09, 0x35, 0x13, 0x56, 0xf5, 0xc5, 0x96, 0xb2, 0x5a, 0x1f, 0x75, 0x1e, 0x6b, 0xd4, - 0x54, 0xda, 0xcb, 0x7b, 0xad, 0x62, 0x51, 0x16, 0x95, 0x8c, 0x63, 0x9b, 0x53, 0xe5, 0x74, 0xdd, 0x25, 0x63, 0x2b, - 0xde, 0x06, 0x4c, 0xf3, 0x61, 0x06, 0xbc, 0xce, 0x61, 0x3f, 0x96, 0xdc, 0xdd, 0xfd, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, - 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0x44, 0x1b, 0xd9, 0xf8, 0x64, 0xb7, 0x35, 0x5c, 0xd5, 0x19, 0x63, 0x71, 0x30, 0xc4, - 0x27, 0x9b, 0xaa, 0x23, 0x59, 0xce, 0x78, 0x42, 0x23, 0x9f, 0xcf, 0x69, 0xe6, 0x17, 0xe0, 0x55, 0x35, 0x7b, 0x3f, - 0x92, 0xc1, 0xf2, 0x5d, 0xdd, 0xbd, 0x1a, 0x9d, 0x14, 0xe0, 0xfd, 0xfa, 0x62, 0xd3, 0xf1, 0xfa, 0x2d, 0x15, 0xb9, - 0x52, 0x44, 0x4b, 0x9d, 0xf6, 0x8b, 0x4a, 0x2c, 0x7d, 0x11, 0xed, 0x6c, 0x5f, 0x99, 0x20, 0x7e, 0x3b, 0x7c, 0x1c, - 0x1e, 0xf9, 0x48, 0xb9, 0x85, 0xbf, 0x32, 0x07, 0xfe, 0xb9, 0x75, 0x0b, 0xbf, 0x20, 0xcf, 0xeb, 0x5e, 0xe1, 0x44, - 0x92, 0x17, 0xfd, 0x17, 0xd6, 0x62, 0xe6, 0x29, 0x1b, 0xdd, 0x06, 0x7e, 0xca, 0x64, 0x13, 0x42, 0x6f, 0x3e, 0x5e, - 0xea, 0x0a, 0x70, 0x29, 0x2a, 0x77, 0x76, 0x61, 0x6d, 0x3d, 0x2c, 0x25, 0xf1, 0xf7, 0x53, 0x26, 0xf7, 0x7d, 0x3c, - 0x23, 0x17, 0xf0, 0x63, 0x7f, 0x19, 0xbc, 0x8e, 0xe5, 0x34, 0x14, 0x71, 0x96, 0xf0, 0x59, 0x80, 0x1a, 0xbe, 0x8f, - 0xc2, 0x5c, 0xd9, 0x1b, 0x9f, 0xa3, 0x62, 0xff, 0x02, 0xdf, 0x48, 0xe2, 0xf7, 0xfd, 0xc6, 0x0c, 0xbf, 0x91, 0xe4, - 0xe2, 0x78, 0x7f, 0x79, 0x23, 0x8b, 0xde, 0x05, 0xbe, 0x29, 0x3d, 0xf6, 0xf8, 0x6b, 0x12, 0x20, 0xd2, 0xbb, 0x31, - 0xd0, 0x9c, 0xf2, 0x99, 0xf6, 0xdc, 0xfb, 0x08, 0x7f, 0x80, 0xb8, 0x8a, 0xa8, 0xb8, 0x8d, 0x09, 0xad, 0xec, 0x11, - 0x9f, 0x2b, 0x17, 0x81, 0x7f, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x3e, 0x91, 0xa4, 0x66, 0x90, 0xe3, 0xf7, 0x2a, - 0x42, 0x73, 0x22, 0x03, 0x81, 0xec, 0x30, 0x81, 0xf5, 0x43, 0x9b, 0xa3, 0x29, 0x06, 0xda, 0xc3, 0x10, 0x32, 0x49, - 0x45, 0x2c, 0xb9, 0x18, 0x22, 0x57, 0xfd, 0xc0, 0x7f, 0x23, 0x17, 0x03, 0xef, 0x3f, 0xfd, 0xd3, 0x8f, 0xe3, 0x1f, - 0xc5, 0xf0, 0x02, 0xbf, 0x25, 0x87, 0xc7, 0x41, 0x3f, 0x0a, 0xf6, 0x9a, 0xcd, 0xd5, 0x8f, 0x87, 0x83, 0x7f, 0xc4, - 0xcd, 0x5f, 0x4e, 0x9a, 0x3f, 0x0c, 0xd1, 0x2a, 0xf8, 0xf1, 0xb0, 0x3f, 0x30, 0x4f, 0x83, 0x7f, 0xf4, 0x7e, 0xcc, - 0x87, 0x7f, 0xd6, 0x85, 0xfb, 0x08, 0x1d, 0x4e, 0xf0, 0x42, 0x92, 0xc3, 0x66, 0xb3, 0x77, 0x38, 0xc1, 0x73, 0x49, - 0x0e, 0xe1, 0xff, 0x4b, 0xf2, 0x8e, 0x4e, 0x5e, 0xdc, 0xcc, 0x83, 0x8b, 0xde, 0x6a, 0x7f, 0xf9, 0xb7, 0x02, 0x46, - 0x1d, 0xfc, 0xe3, 0xc7, 0x1f, 0x73, 0xff, 0x41, 0x8f, 0x1c, 0x0e, 0x1b, 0x28, 0x80, 0xd2, 0x3f, 0x13, 0xf5, 0x6f, - 0xd0, 0x8f, 0x06, 0xff, 0x30, 0x50, 0xf8, 0x0f, 0x7e, 0xbc, 0x38, 0xee, 0x91, 0xe1, 0x2a, 0xf0, 0x57, 0x0f, 0xd0, - 0x0a, 0xa1, 0xd5, 0x3e, 0xba, 0xc0, 0xfe, 0xc4, 0x47, 0x78, 0x22, 0xc9, 0xe1, 0x83, 0xc3, 0x09, 0xbe, 0x92, 0xe4, - 0xd0, 0x3f, 0x9c, 0xe0, 0x17, 0x92, 0x1c, 0xfe, 0x23, 0xe8, 0x47, 0xda, 0xc3, 0xb6, 0x52, 0xee, 0x8d, 0x15, 0x04, - 0x37, 0x62, 0x41, 0xe3, 0x95, 0x64, 0x32, 0xa5, 0x68, 0xff, 0x90, 0xe1, 0x33, 0x85, 0xa6, 0x40, 0x82, 0x13, 0x06, - 0x6c, 0xbb, 0x60, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x09, 0xac, 0xfd, 0x00, 0x79, 0x24, 0xf1, 0x55, 0x9c, - 0x2e, 0x68, 0x1e, 0xd1, 0x02, 0xe1, 0x11, 0x39, 0x93, 0x41, 0x1b, 0xe1, 0x77, 0x12, 0x7e, 0x74, 0x10, 0x3e, 0x33, - 0x01, 0x4c, 0x38, 0xc8, 0x9a, 0xa8, 0x32, 0xae, 0x35, 0x16, 0x1f, 0xe1, 0xf9, 0x96, 0x4a, 0x39, 0x05, 0xef, 0x02, - 0xc2, 0xe3, 0x5a, 0xb8, 0x13, 0x5f, 0x13, 0x4b, 0x12, 0xef, 0x05, 0xa5, 0xdf, 0xc5, 0xe9, 0x47, 0x2a, 0x82, 0x1b, - 0xdc, 0xee, 0x7c, 0x8e, 0x95, 0x0b, 0x7a, 0xaf, 0x8d, 0xba, 0x65, 0xac, 0xea, 0x54, 0xea, 0x18, 0x01, 0x08, 0xd9, - 0xba, 0x2f, 0x06, 0x76, 0x7c, 0x4f, 0x6c, 0x38, 0xac, 0x44, 0x7c, 0xed, 0xa3, 0x7a, 0x5c, 0x94, 0x65, 0x57, 0x71, - 0xca, 0x12, 0x4f, 0xd2, 0xd9, 0x3c, 0x8d, 0x25, 0xf5, 0xcc, 0x7a, 0xbd, 0x18, 0x06, 0xf2, 0x4b, 0x95, 0x21, 0x71, - 0x0c, 0xce, 0xc4, 0x06, 0x9c, 0xe0, 0xac, 0x04, 0x10, 0x9d, 0x32, 0x6a, 0xc7, 0xeb, 0x2a, 0xf8, 0xb5, 0x1e, 0xdf, - 0x6b, 0xb6, 0xc1, 0x11, 0x36, 0x54, 0xe2, 0x39, 0xc7, 0x19, 0x01, 0x21, 0xda, 0xe9, 0xfb, 0xc7, 0xf9, 0xd5, 0xa4, - 0xe7, 0x43, 0x6c, 0x86, 0x93, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xa4, 0xd5, 0x9d, 0x1e, 0xd3, 0xee, 0xb4, 0xd1, - 0xb0, 0x3a, 0x74, 0x4a, 0xc4, 0x60, 0xaa, 0xbb, 0xc7, 0x38, 0xc1, 0x0b, 0xd2, 0x6c, 0xe3, 0x09, 0x69, 0xa9, 0x2e, - 0xdd, 0xc9, 0x71, 0x6a, 0xa6, 0x39, 0x38, 0x08, 0x78, 0x98, 0xc6, 0xb9, 0xfc, 0x12, 0x8c, 0x7d, 0x32, 0xc1, 0x09, - 0xe1, 0x21, 0xbd, 0xa1, 0xa3, 0x20, 0x45, 0x38, 0x31, 0x9c, 0x06, 0x75, 0xd1, 0x84, 0x38, 0xcd, 0xc0, 0x88, 0x20, - 0x6f, 0xfb, 0xc9, 0xa0, 0x3d, 0x24, 0x84, 0xf8, 0x7b, 0xcd, 0xa6, 0xdf, 0xe7, 0x64, 0x21, 0x23, 0x28, 0x71, 0x54, - 0x65, 0x32, 0x87, 0xa2, 0x8e, 0x53, 0x14, 0xbc, 0x90, 0xa1, 0xa4, 0xb9, 0x0c, 0xa0, 0x18, 0xcc, 0xff, 0xdc, 0x12, - 0xb6, 0x7f, 0x7c, 0xe8, 0x37, 0xa0, 0x54, 0x11, 0x27, 0xc2, 0x9c, 0x5c, 0xa2, 0x28, 0x19, 0x1c, 0x0d, 0x5d, 0xfe, - 0xaf, 0x0a, 0x61, 0xf2, 0xcb, 0x7e, 0x32, 0x68, 0xa9, 0xc9, 0x7b, 0x7e, 0x3f, 0xe0, 0x24, 0xd7, 0x0a, 0x5a, 0x3f, - 0x8f, 0xde, 0xaa, 0xa5, 0xa2, 0xc8, 0x00, 0x67, 0xe6, 0x5d, 0x90, 0x66, 0x27, 0x0a, 0x16, 0xee, 0x22, 0x9a, 0x30, - 0x99, 0xc1, 0x02, 0x8e, 0x09, 0xb4, 0xc7, 0x9c, 0xc0, 0x8c, 0x55, 0xb7, 0xcb, 0xc8, 0x3c, 0x3f, 0xf0, 0x1f, 0xf4, - 0xaf, 0x64, 0x34, 0x91, 0x7a, 0xfa, 0x2b, 0xb9, 0x5a, 0xc1, 0xff, 0x13, 0xd9, 0xe7, 0xe4, 0x52, 0x15, 0x2d, 0x4c, - 0xd1, 0x1c, 0x8a, 0xde, 0x46, 0x00, 0x2a, 0xce, 0x4b, 0x25, 0x4b, 0xef, 0xc9, 0x15, 0x51, 0xb0, 0x1f, 0x1c, 0x88, - 0xc1, 0xb4, 0xd1, 0x1e, 0x82, 0x7f, 0x5f, 0xc8, 0xfc, 0x3b, 0x26, 0xa7, 0x81, 0x7f, 0xd8, 0xf3, 0x51, 0xdf, 0xf7, - 0x60, 0x6b, 0xbb, 0x59, 0x83, 0x68, 0x0c, 0xa7, 0x8d, 0x37, 0x32, 0x5a, 0xf4, 0x48, 0xab, 0x1f, 0x30, 0xe3, 0xcf, - 0x43, 0x38, 0x35, 0x8c, 0xb3, 0x85, 0x17, 0xa8, 0x21, 0x65, 0xc3, 0x3e, 0x2f, 0x50, 0x63, 0xd6, 0xb8, 0x42, 0x51, - 0xda, 0x98, 0x35, 0x82, 0x05, 0x21, 0xa4, 0xd9, 0x29, 0xbb, 0x59, 0xe9, 0x37, 0x45, 0xd1, 0x95, 0x75, 0x76, 0x0e, - 0xd4, 0x71, 0xc8, 0x1a, 0x81, 0x18, 0xd0, 0xe1, 0x6a, 0xe5, 0x1f, 0xf7, 0x7b, 0x3e, 0x6a, 0x04, 0x96, 0xd0, 0x0e, - 0x2d, 0xa5, 0x21, 0x84, 0xd9, 0xb0, 0x30, 0xa1, 0xa4, 0x97, 0xb5, 0xb0, 0xd1, 0xb2, 0x3a, 0xec, 0x0e, 0x0f, 0xa0, - 0x45, 0x69, 0xc7, 0x68, 0x7d, 0x75, 0x0e, 0xcb, 0xb4, 0xc4, 0x9c, 0x91, 0x16, 0xe6, 0xc4, 0xfa, 0xae, 0xa7, 0x44, - 0x56, 0x04, 0x9f, 0x92, 0xaa, 0x39, 0x1e, 0xc4, 0x38, 0x19, 0x92, 0xd7, 0xda, 0x1e, 0xe9, 0x5a, 0xbf, 0x38, 0x4d, - 0xc9, 0xcb, 0xb5, 0xe8, 0x6d, 0x0c, 0xb1, 0x95, 0xeb, 0x70, 0xb4, 0x10, 0x82, 0x66, 0xf2, 0x0d, 0x4f, 0x8c, 0x9a, - 0x46, 0x53, 0xb0, 0x94, 0x20, 0x2c, 0x8b, 0x41, 0x47, 0xeb, 0xd8, 0x93, 0xb1, 0xd8, 0xa8, 0x9e, 0x90, 0x85, 0x56, - 0x9f, 0x54, 0xb0, 0xb6, 0x3b, 0x31, 0x76, 0x71, 0x80, 0xf0, 0xc2, 0x44, 0x71, 0x83, 0x30, 0x0c, 0x27, 0xe1, 0x08, - 0xaa, 0x61, 0x82, 0x1c, 0x15, 0xea, 0x1c, 0x05, 0x39, 0xb9, 0x0e, 0x33, 0x7a, 0xa3, 0x66, 0x0d, 0x50, 0x25, 0x99, - 0xed, 0xf1, 0x3a, 0x9e, 0x76, 0x15, 0xbb, 0xc9, 0xc3, 0x8c, 0x27, 0x14, 0xd0, 0x03, 0x71, 0x7b, 0x53, 0x34, 0x8d, - 0x73, 0x37, 0x3e, 0x55, 0xc1, 0x37, 0x70, 0x9d, 0xd7, 0x13, 0xf0, 0xf8, 0x2a, 0x5d, 0xab, 0x6c, 0xac, 0xdd, 0xe0, - 0x08, 0xb1, 0x71, 0x30, 0x09, 0x21, 0xae, 0xa7, 0x48, 0x48, 0x82, 0x29, 0x37, 0x71, 0x89, 0x6a, 0x56, 0x8e, 0x79, - 0x45, 0x92, 0x01, 0x6f, 0x34, 0x94, 0x17, 0x7a, 0xa1, 0x49, 0x62, 0x82, 0xf0, 0x55, 0x79, 0xb6, 0x6c, 0xbb, 0xb7, - 0x92, 0xd4, 0xa7, 0x0a, 0xae, 0xea, 0xee, 0xdc, 0x86, 0x94, 0x48, 0x79, 0x0a, 0x65, 0x30, 0x43, 0xf8, 0x19, 0x39, - 0x0c, 0x06, 0x61, 0xff, 0x2f, 0x43, 0xd4, 0x0f, 0xc2, 0x3f, 0xa3, 0x43, 0xcd, 0x39, 0xae, 0x50, 0x37, 0xd5, 0x73, - 0x2c, 0x55, 0xfc, 0xb2, 0x8d, 0x95, 0x27, 0x31, 0xca, 0x70, 0x16, 0xcf, 0x68, 0xf4, 0x0c, 0x0e, 0xb9, 0x25, 0x9c, - 0xb7, 0x12, 0x03, 0x25, 0x45, 0xcf, 0x0c, 0x2f, 0x09, 0xfd, 0xfe, 0x2b, 0x59, 0x3e, 0xf5, 0xfd, 0xfe, 0xf3, 0xea, - 0xe9, 0x2f, 0x7e, 0xff, 0x17, 0x19, 0xfd, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, 0x42, 0x6f, 0x8d, - 0x83, 0xbb, 0x05, 0xda, 0x74, 0x74, 0x4c, 0x50, 0xc1, 0xc6, 0x25, 0x33, 0xca, 0x43, 0x19, 0x4f, 0x00, 0xa9, 0xce, - 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0x42, 0xcb, 0x5a, 0x5b, - 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0x22, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, 0x68, 0xa0, 0xdc, - 0x92, 0xd6, 0x62, 0x70, 0x35, 0xc4, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x5c, 0x5b, 0x5e, 0xc7, 0x2c, 0xaf, 0xd1, - 0xc8, 0x0a, 0xd4, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x48, 0x95, 0x40, 0x32, - 0x14, 0x21, 0xe4, 0x46, 0xa2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, 0x4a, 0x04, 0x80, - 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x78, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, 0x9e, 0x54, 0x63, - 0xe1, 0x45, 0x83, 0xcc, 0x4a, 0x2c, 0x15, 0x59, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, 0x02, 0x10, 0x37, - 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x85, 0x2c, 0xcb, 0xa8, 0x00, 0x29, 0x4a, 0x24, 0x66, 0x45, 0x51, - 0x49, 0x76, 0x10, 0xa3, 0x98, 0x12, 0x01, 0x9c, 0x47, 0xd9, 0x5d, 0x38, 0xc3, 0x1c, 0x4f, 0x15, 0xdf, 0x20, 0x84, - 0x9c, 0xd9, 0x74, 0x16, 0xa9, 0x78, 0x50, 0x4a, 0x98, 0x23, 0x93, 0x72, 0x42, 0xc3, 0xf3, 0xfd, 0x53, 0x7e, 0xa7, - 0x4d, 0x36, 0x60, 0xc3, 0x48, 0x35, 0x4b, 0x0d, 0xe7, 0x8a, 0xc9, 0x87, 0x40, 0xa2, 0x32, 0x3a, 0x12, 0x2a, 0x06, - 0xf8, 0x9c, 0x09, 0xaa, 0x74, 0xf0, 0x7d, 0x6b, 0xf7, 0xa5, 0x75, 0x05, 0x32, 0x75, 0xbd, 0x37, 0x80, 0xc8, 0x18, - 0x9c, 0x3b, 0x19, 0xd9, 0x68, 0x76, 0xbe, 0x7f, 0xf2, 0x76, 0x9b, 0x0d, 0xbc, 0x5a, 0x19, 0xeb, 0x57, 0xe9, 0x36, - 0x38, 0xae, 0x20, 0x4d, 0xcd, 0x8f, 0x28, 0x48, 0x95, 0x8a, 0x14, 0x07, 0x02, 0xa8, 0xe8, 0x7c, 0xff, 0xe4, 0x7d, - 0x20, 0x94, 0x6f, 0x09, 0x61, 0x77, 0xd9, 0x01, 0x27, 0xc1, 0x94, 0x50, 0xa4, 0xd7, 0x5e, 0xb2, 0x2e, 0xee, 0x08, - 0xf0, 0x68, 0xaa, 0x2a, 0xc1, 0x82, 0x18, 0xb0, 0x21, 0x49, 0x0d, 0x06, 0x48, 0x8a, 0x70, 0x5a, 0xb3, 0xcb, 0x08, - 0x6c, 0x80, 0x9a, 0xeb, 0x0c, 0x76, 0x22, 0xd4, 0xaa, 0x1f, 0xc2, 0xa9, 0x9a, 0x55, 0x16, 0x5a, 0x78, 0x3c, 0xdb, - 0xc8, 0x4a, 0xab, 0xcc, 0xd1, 0x6f, 0xc1, 0x76, 0xb2, 0x0f, 0x6f, 0x88, 0xb5, 0x24, 0x4c, 0xc1, 0x73, 0x9b, 0x3e, - 0x76, 0xbe, 0x7f, 0xf2, 0xda, 0x64, 0x90, 0xcd, 0x63, 0xcb, 0xef, 0x37, 0x4c, 0xcc, 0x93, 0xd7, 0x61, 0x55, 0xab, - 0x1a, 0x9f, 0xef, 0x9f, 0x7c, 0xd8, 0xd6, 0x0c, 0xca, 0x8b, 0x45, 0x65, 0xe3, 0x2b, 0xf8, 0x96, 0x34, 0x8d, 0x96, - 0x46, 0x38, 0x44, 0xac, 0xc0, 0x4a, 0x20, 0x45, 0x79, 0x51, 0xba, 0x46, 0x9e, 0xe3, 0x8c, 0xa8, 0x30, 0x50, 0x7d, - 0xd7, 0x8c, 0x9a, 0xc7, 0x78, 0x76, 0x36, 0xe2, 0x73, 0xba, 0x23, 0x36, 0x74, 0x83, 0x42, 0x36, 0x83, 0xd4, 0x19, - 0x05, 0x3a, 0xc3, 0x7b, 0x2d, 0xd4, 0xad, 0x8b, 0xaf, 0x4c, 0x11, 0x29, 0xaf, 0xc9, 0x16, 0x3c, 0x25, 0x2d, 0x9c, - 0x92, 0x16, 0x8e, 0x49, 0x3e, 0x68, 0x69, 0x01, 0xd1, 0x8d, 0xcb, 0x71, 0xb5, 0x98, 0x81, 0xac, 0x30, 0x73, 0x5a, - 0xb5, 0x00, 0x4e, 0xba, 0xb1, 0xf2, 0x3d, 0x2a, 0x99, 0x9e, 0x28, 0xb2, 0x78, 0x1f, 0x70, 0xcc, 0xd5, 0xc0, 0x67, - 0xec, 0x32, 0x85, 0xc4, 0x12, 0x58, 0x15, 0x96, 0x28, 0x2a, 0x9b, 0xb6, 0x4d, 0xd3, 0x38, 0x54, 0xfb, 0xc4, 0x71, - 0x1c, 0x02, 0xe7, 0xc6, 0xb1, 0xc9, 0xc3, 0xc9, 0x37, 0xbb, 0x3c, 0x3e, 0x38, 0x08, 0x74, 0xa7, 0x2f, 0x65, 0xc0, - 0x6d, 0x7d, 0x15, 0xb9, 0xfb, 0x56, 0xf3, 0x8a, 0x04, 0x29, 0xf8, 0x1b, 0x8d, 0x74, 0x58, 0x40, 0x18, 0x3a, 0x88, - 0xeb, 0x18, 0xb4, 0xc0, 0x2b, 0x5d, 0xaf, 0xbe, 0xfc, 0x46, 0xa3, 0x8c, 0xd2, 0xd6, 0xb1, 0x75, 0x83, 0xb3, 0xe2, - 0x2a, 0x28, 0x53, 0x7f, 0x5a, 0x1b, 0xf9, 0x52, 0x16, 0x04, 0xc4, 0x5c, 0x9a, 0x65, 0x76, 0x31, 0xce, 0x91, 0x60, - 0xd0, 0xee, 0x4b, 0x93, 0xb5, 0x80, 0x55, 0x76, 0x95, 0x69, 0x64, 0xd9, 0x59, 0x07, 0x45, 0xb6, 0x11, 0x44, 0xa5, - 0xa0, 0x51, 0xa3, 0x30, 0xe4, 0xfd, 0x7e, 0x33, 0xe7, 0x12, 0xe7, 0xc8, 0x38, 0xb9, 0x14, 0x14, 0x0a, 0x59, 0x9d, - 0x12, 0x29, 0x2f, 0xc9, 0x7c, 0x37, 0xc9, 0x9f, 0x38, 0x24, 0xff, 0x8c, 0x50, 0x87, 0xfc, 0xb5, 0x8b, 0x23, 0xe4, - 0xc6, 0xb9, 0x90, 0xdb, 0xaa, 0xd3, 0x39, 0x01, 0x27, 0x5a, 0x1d, 0xa3, 0xb5, 0xb0, 0xe2, 0x0e, 0x86, 0xe2, 0x9e, - 0x10, 0xe5, 0x86, 0xc4, 0x36, 0x06, 0x1c, 0x54, 0x41, 0x35, 0x98, 0x7a, 0x9b, 0x4f, 0xcf, 0xe5, 0x80, 0x27, 0x1f, - 0xee, 0x8e, 0x87, 0x9e, 0xce, 0x37, 0x4f, 0xae, 0x93, 0xfb, 0x09, 0xab, 0x76, 0x0e, 0x6e, 0x3d, 0x13, 0x14, 0xe6, - 0x2f, 0xe3, 0xd8, 0x75, 0xe6, 0xb3, 0x76, 0x08, 0xad, 0xfc, 0x03, 0x68, 0xdb, 0x6d, 0xd5, 0x82, 0x3a, 0xc3, 0x02, - 0x3f, 0xd2, 0x19, 0xa8, 0xb1, 0xd8, 0xc1, 0x3e, 0x4e, 0x54, 0x03, 0x9a, 0x25, 0xdb, 0xab, 0x9f, 0x15, 0x86, 0x4c, - 0x34, 0x68, 0x68, 0x09, 0xfc, 0x4f, 0x93, 0x3c, 0xd0, 0x8d, 0x92, 0x0b, 0x80, 0xa0, 0xb9, 0xc2, 0x53, 0x85, 0x30, - 0xdf, 0xaf, 0xbc, 0xef, 0x2f, 0xf7, 0x08, 0x99, 0x57, 0xde, 0xc7, 0x77, 0x55, 0xea, 0x15, 0x90, 0x05, 0x8a, 0xc0, - 0x7c, 0x2c, 0x0b, 0x74, 0xf8, 0xf2, 0xcc, 0x36, 0x57, 0x26, 0x64, 0x58, 0x69, 0xdc, 0x4e, 0x68, 0x53, 0xb9, 0xe5, - 0x74, 0xbd, 0x45, 0xc3, 0x5a, 0xed, 0x3e, 0xd4, 0xbe, 0x97, 0x0a, 0x46, 0x78, 0x7e, 0xaf, 0x5a, 0xdb, 0x71, 0x8b, - 0x8f, 0xeb, 0xf9, 0x2b, 0x6b, 0x9b, 0x12, 0xb2, 0x2c, 0xa7, 0x42, 0x3e, 0xa3, 0x63, 0x2e, 0x20, 0x66, 0x51, 0xe2, - 0x04, 0x15, 0xfb, 0x8e, 0xdf, 0x4e, 0xad, 0xcf, 0x09, 0x14, 0xac, 0x2d, 0x50, 0xfd, 0xfa, 0xa8, 0x82, 0xd6, 0xe7, - 0xeb, 0xbd, 0xe6, 0x07, 0x07, 0x1f, 0x2a, 0x34, 0x19, 0x28, 0x15, 0x14, 0x0e, 0xd3, 0xd2, 0x2a, 0x8d, 0x89, 0xe4, - 0xee, 0x07, 0xa5, 0x13, 0xc0, 0x32, 0x0c, 0x97, 0xf7, 0xbc, 0x24, 0xb2, 0x98, 0xac, 0xb3, 0x78, 0xe3, 0x9c, 0x60, - 0xae, 0xe1, 0x02, 0x1c, 0x1e, 0x4c, 0x6d, 0xed, 0x2d, 0xca, 0xab, 0x64, 0xd8, 0x12, 0x86, 0x53, 0x40, 0x56, 0xa0, - 0xcc, 0x10, 0x87, 0x02, 0xb7, 0x9a, 0x25, 0xa7, 0xa0, 0x57, 0x4e, 0x71, 0x1e, 0x4e, 0x21, 0xfd, 0xb5, 0x76, 0x64, - 0x11, 0xc2, 0x3a, 0x31, 0xc7, 0x49, 0x25, 0x38, 0x79, 0xb9, 0xcd, 0xa5, 0x6c, 0x89, 0x9a, 0x2a, 0xa9, 0xa3, 0x5a, - 0xa0, 0xb2, 0x43, 0x78, 0x15, 0x30, 0xa3, 0xb8, 0xd9, 0xb8, 0x19, 0x30, 0xe0, 0x67, 0x32, 0xd0, 0xc1, 0x28, 0x90, - 0x19, 0x3c, 0x5c, 0x04, 0xb5, 0xa9, 0xbb, 0x5c, 0x75, 0xc3, 0x06, 0x71, 0x53, 0x17, 0x4d, 0x5c, 0xc5, 0xf5, 0x4e, - 0x2b, 0x5e, 0x3a, 0xd6, 0x19, 0xd4, 0xd2, 0x72, 0xc1, 0x2a, 0x91, 0xc4, 0x59, 0xfe, 0x58, 0x27, 0x45, 0x97, 0x8d, - 0x30, 0x55, 0x60, 0xbc, 0x54, 0x7b, 0x40, 0x0b, 0xa0, 0xaf, 0xe5, 0x89, 0x74, 0x76, 0xd4, 0x3a, 0xb1, 0xd5, 0x9c, - 0x8e, 0xd4, 0x7f, 0x07, 0xa9, 0x2e, 0xeb, 0x67, 0xfe, 0xa5, 0x92, 0x85, 0x0c, 0xe7, 0x35, 0xc6, 0x9e, 0x29, 0xc6, - 0x8e, 0x40, 0x4f, 0xb3, 0x89, 0xdf, 0x7d, 0x93, 0xf1, 0xc2, 0x8c, 0x94, 0x33, 0x24, 0xf6, 0x75, 0x19, 0x2d, 0x77, - 0x7e, 0xaf, 0xed, 0x46, 0xc4, 0x08, 0x64, 0x01, 0x61, 0xc3, 0xd9, 0x33, 0x84, 0xf3, 0x46, 0xa3, 0x9b, 0x1f, 0xd3, - 0xca, 0x49, 0x52, 0xc1, 0xc8, 0x20, 0xa0, 0x0b, 0x04, 0x5f, 0x93, 0xa1, 0x10, 0xf2, 0xb7, 0x99, 0xd9, 0x39, 0xf8, - 0xda, 0x4f, 0xde, 0x05, 0x2e, 0x57, 0x73, 0xdb, 0x96, 0x41, 0x53, 0x58, 0x4f, 0x50, 0x05, 0x5c, 0xbe, 0xbe, 0x3b, - 0xc1, 0x03, 0xe0, 0xde, 0x6b, 0x63, 0x48, 0x45, 0x43, 0x5d, 0xa9, 0x59, 0x42, 0x79, 0xfa, 0xba, 0xa8, 0xca, 0x4a, - 0x74, 0x27, 0xeb, 0xca, 0xca, 0x98, 0x95, 0x24, 0x2f, 0x8a, 0x9c, 0x56, 0xe1, 0xfd, 0xb5, 0xf4, 0x4b, 0x25, 0x5c, - 0x36, 0xbd, 0xed, 0xa7, 0x73, 0x22, 0xb1, 0x43, 0xa8, 0x5f, 0xef, 0x8a, 0x7d, 0x54, 0x60, 0xc2, 0xb9, 0x36, 0x42, - 0xf1, 0xe7, 0x6d, 0x42, 0x11, 0x67, 0xe6, 0xc8, 0x2b, 0x81, 0xd8, 0xbe, 0x87, 0x40, 0x34, 0x6e, 0x76, 0x2b, 0x13, - 0x41, 0x1d, 0xa9, 0xc9, 0xc4, 0xfa, 0x96, 0x92, 0x0c, 0x33, 0xb3, 0x1b, 0xbd, 0xce, 0x6a, 0xc5, 0x06, 0x2d, 0x70, - 0x23, 0xf9, 0x3e, 0xfc, 0x6c, 0xeb, 0x9f, 0x0e, 0x27, 0xd6, 0x6e, 0xe0, 0x80, 0x95, 0x26, 0x0b, 0x0a, 0x21, 0xc1, - 0x39, 0x50, 0x49, 0x59, 0x8a, 0xa6, 0x0d, 0x05, 0x19, 0x02, 0x27, 0xac, 0x0c, 0x33, 0x01, 0xc4, 0x4a, 0x56, 0x18, - 0x03, 0x32, 0xd8, 0x9a, 0xfb, 0x67, 0xcd, 0xcb, 0x4f, 0x6b, 0xa2, 0x35, 0xb9, 0xa2, 0xd5, 0x87, 0x5a, 0xbe, 0x81, - 0x81, 0xc0, 0xe8, 0x87, 0x7b, 0xca, 0x04, 0xad, 0x44, 0x39, 0x72, 0xe5, 0x10, 0x6e, 0x81, 0x13, 0x6d, 0xef, 0x83, - 0x8e, 0xf0, 0x6e, 0x91, 0x26, 0x98, 0x3b, 0x74, 0xfd, 0x92, 0xc8, 0x1a, 0x2b, 0x99, 0x12, 0x63, 0x29, 0xe1, 0x58, - 0x91, 0xa9, 0x24, 0xd9, 0xa0, 0x35, 0x04, 0x05, 0xb4, 0x9b, 0x1e, 0x67, 0x95, 0x09, 0x9c, 0x36, 0x1a, 0x28, 0xb6, - 0xb3, 0x4e, 0x07, 0xac, 0x91, 0x0e, 0x31, 0xc5, 0xa9, 0x36, 0x4c, 0xce, 0x0e, 0x0e, 0x82, 0xb8, 0x9a, 0x77, 0x90, - 0x0e, 0x11, 0xe6, 0xab, 0x55, 0xa0, 0xc0, 0x8a, 0xd1, 0x6a, 0x15, 0xbb, 0x60, 0xa9, 0x6a, 0xe8, 0x36, 0xef, 0x4b, - 0x32, 0x57, 0x02, 0x70, 0x0e, 0x10, 0x36, 0x48, 0x10, 0x1b, 0xf7, 0x5e, 0x0c, 0xee, 0xa8, 0x46, 0x36, 0x48, 0x1b, - 0xed, 0xa1, 0xc3, 0xb8, 0x06, 0xe9, 0x90, 0xc4, 0x05, 0x3f, 0x38, 0xd8, 0xcb, 0x8d, 0x88, 0xfc, 0x09, 0x44, 0xd9, - 0x4f, 0x4a, 0xb2, 0xe8, 0x01, 0xdd, 0xdd, 0x58, 0x77, 0x06, 0x94, 0x14, 0x65, 0xb6, 0xd5, 0xb6, 0xab, 0x65, 0x41, - 0x94, 0x8d, 0xb0, 0x09, 0x06, 0xf7, 0xc1, 0xb2, 0x2f, 0xc9, 0xfc, 0x95, 0x2c, 0x73, 0xac, 0x7f, 0xde, 0x9a, 0x59, - 0x1d, 0x86, 0x61, 0x2c, 0x26, 0x2a, 0x96, 0x61, 0xc3, 0xb0, 0x8a, 0xf8, 0x8f, 0x0c, 0x98, 0xce, 0xc4, 0x83, 0x72, - 0xae, 0x21, 0xd1, 0xe0, 0x5b, 0xd5, 0xc6, 0xde, 0x25, 0xf9, 0x69, 0xab, 0x97, 0x41, 0x43, 0xf2, 0xfc, 0xb7, 0x42, - 0xf2, 0xd0, 0x40, 0xa2, 0xc9, 0x63, 0x0d, 0x67, 0x3b, 0x70, 0xf1, 0x93, 0x5c, 0xc3, 0xd9, 0x6e, 0xdc, 0x5a, 0x4c, - 0xfd, 0xb2, 0x0b, 0x3e, 0x87, 0x37, 0x68, 0x40, 0xab, 0x02, 0x07, 0xca, 0x47, 0xeb, 0xba, 0x97, 0x66, 0xa5, 0x20, - 0x4c, 0x25, 0x09, 0x58, 0xfd, 0x00, 0x54, 0xda, 0xa8, 0x63, 0xf8, 0xb2, 0x68, 0x8e, 0x1c, 0x97, 0x40, 0x3d, 0x75, - 0x05, 0xc8, 0xc9, 0x78, 0xdb, 0xe7, 0x07, 0x07, 0x60, 0x1b, 0x80, 0x12, 0x17, 0x8e, 0xe2, 0xb9, 0x5c, 0x08, 0x50, - 0xa5, 0x72, 0xfb, 0x1b, 0x8a, 0xe1, 0x16, 0x88, 0x2a, 0x83, 0x1f, 0x50, 0x30, 0x8f, 0xf3, 0x9c, 0x5d, 0xe9, 0x32, - 0xf3, 0x1b, 0x73, 0x62, 0x49, 0x39, 0xd7, 0x3a, 0x61, 0x86, 0xba, 0x99, 0xa1, 0xd3, 0x3a, 0xda, 0x5e, 0x5c, 0xd1, - 0x4c, 0xbe, 0x62, 0xb9, 0xa4, 0x19, 0x2c, 0xbf, 0xa2, 0x38, 0x58, 0x51, 0x8e, 0xe0, 0xc0, 0xd6, 0x7a, 0xc5, 0x49, - 0x72, 0x67, 0x17, 0x59, 0xd7, 0x81, 0xa6, 0x71, 0x96, 0xa4, 0x7a, 0x12, 0x37, 0x9f, 0xd1, 0xe6, 0x70, 0x96, 0x2d, - 0xdd, 0x7c, 0x9a, 0x4a, 0xd9, 0x50, 0xdc, 0x3d, 0x60, 0xc4, 0x4a, 0x02, 0x2b, 0x3d, 0xef, 0xd4, 0x5a, 0x20, 0xe2, - 0xbd, 0x63, 0x13, 0xdc, 0x95, 0x60, 0xe9, 0x70, 0xd4, 0xb0, 0x0e, 0xa7, 0xa5, 0x9b, 0x2f, 0xb7, 0x5e, 0x69, 0xdb, - 0x26, 0x1c, 0x14, 0x9d, 0x3c, 0xde, 0x6d, 0x59, 0xbd, 0xb6, 0x92, 0xc3, 0x4a, 0x0b, 0x76, 0x5f, 0xc6, 0x8c, 0x96, - 0x96, 0xbc, 0x90, 0x3d, 0x8a, 0xfb, 0x92, 0x3c, 0x87, 0x3b, 0x43, 0x2f, 0xe5, 0x2c, 0x5d, 0xbb, 0x1a, 0xd3, 0xdd, - 0x2f, 0xb5, 0xff, 0x7d, 0x19, 0xbc, 0xc4, 0xef, 0x21, 0xb0, 0xfb, 0x55, 0xd5, 0x7c, 0x33, 0xa0, 0xfb, 0x55, 0x85, - 0xa0, 0xaf, 0xa2, 0x8d, 0x76, 0x4e, 0x20, 0xb7, 0x13, 0x3e, 0x0d, 0x5b, 0xbe, 0xd5, 0x96, 0x7e, 0xd6, 0x61, 0x24, - 0x9d, 0x69, 0xa9, 0xce, 0x03, 0xae, 0xf2, 0xd4, 0x20, 0x5f, 0xae, 0x6e, 0x21, 0x51, 0x93, 0x61, 0xa8, 0x75, 0xf8, - 0x5d, 0xdb, 0x63, 0x64, 0x4c, 0xa6, 0xed, 0x8c, 0xaf, 0x63, 0x21, 0xf7, 0xe1, 0x94, 0xf1, 0x8d, 0x7b, 0x78, 0x53, - 0x02, 0x1e, 0xb4, 0xfb, 0x4d, 0xe1, 0x18, 0xdb, 0xb9, 0xbe, 0x07, 0xe4, 0x8e, 0x4f, 0xb8, 0xd5, 0xdd, 0xea, 0x56, - 0xc6, 0xd7, 0x60, 0xff, 0x23, 0x3c, 0xb5, 0x97, 0xe3, 0xa8, 0xe1, 0xc0, 0x34, 0x5a, 0x16, 0xa5, 0x53, 0x80, 0x6b, - 0xe5, 0x4d, 0x20, 0xcc, 0x0b, 0x15, 0xe0, 0xfe, 0x01, 0x7f, 0x63, 0x58, 0xe2, 0xb8, 0xe4, 0x38, 0x27, 0xf7, 0xe5, - 0x88, 0x1a, 0xfc, 0x32, 0x7e, 0x0f, 0x74, 0xac, 0x28, 0xb4, 0xb0, 0x54, 0xf4, 0x9c, 0x9b, 0x85, 0xec, 0x4c, 0x4b, - 0xc5, 0xb4, 0x4c, 0xa9, 0x51, 0xd3, 0x6c, 0xc9, 0xe3, 0xb4, 0x56, 0xb6, 0x2c, 0x4f, 0x55, 0x6d, 0x5e, 0xb4, 0x03, - 0x8b, 0x55, 0x68, 0x71, 0xb5, 0x0a, 0xea, 0xa8, 0x26, 0xcc, 0x89, 0x64, 0x20, 0xcc, 0x9c, 0x8c, 0x8a, 0x9a, 0x66, - 0xad, 0xfb, 0x04, 0x68, 0x3d, 0xa1, 0xc8, 0xea, 0xe6, 0x35, 0x38, 0x5c, 0x17, 0x82, 0xee, 0xee, 0xfa, 0x14, 0xb0, - 0x5e, 0x5d, 0x39, 0x91, 0x83, 0xa1, 0x9f, 0xcb, 0x54, 0xd9, 0x2a, 0xa7, 0x75, 0x0b, 0x7e, 0xd1, 0x1d, 0xc9, 0xb2, - 0x06, 0x75, 0x9b, 0xf5, 0x4e, 0xb2, 0xd1, 0x73, 0xbe, 0x2b, 0xd9, 0xa8, 0xa6, 0xed, 0xee, 0xb5, 0xd0, 0xdd, 0x69, - 0xa9, 0x7a, 0xae, 0xed, 0x4d, 0x7e, 0xc3, 0x74, 0x6d, 0xa0, 0x4d, 0x8d, 0x66, 0xcb, 0x55, 0xce, 0x8a, 0x62, 0x5c, - 0x5e, 0x26, 0x50, 0xb9, 0x3b, 0x63, 0x4d, 0xff, 0xc6, 0x6a, 0x54, 0xd7, 0x71, 0x83, 0x1f, 0xc8, 0x24, 0xe5, 0x97, - 0x71, 0xfa, 0x1e, 0xe6, 0xab, 0x2a, 0x5f, 0xde, 0x26, 0x22, 0x96, 0xd4, 0x70, 0x97, 0x0a, 0x86, 0x1f, 0x1c, 0x18, - 0x7e, 0xd0, 0x7c, 0xba, 0xea, 0x8f, 0x97, 0xaf, 0xca, 0x01, 0xa2, 0x71, 0x61, 0x59, 0xc6, 0xb9, 0xdc, 0x3e, 0xc7, - 0x3a, 0x0b, 0x3b, 0x2f, 0x59, 0xd8, 0xb9, 0x0c, 0xd6, 0x87, 0x0a, 0x82, 0x6f, 0xb6, 0x8f, 0xb2, 0xc9, 0xd9, 0xbe, - 0xa9, 0x0e, 0xfe, 0x37, 0xd1, 0x9d, 0x7d, 0x1c, 0x2e, 0x77, 0x14, 0x1e, 0xa9, 0x74, 0x15, 0x0d, 0xf2, 0x3b, 0x48, - 0x3b, 0x90, 0xa4, 0xe7, 0xdc, 0x39, 0xa8, 0xe4, 0x94, 0x4d, 0x04, 0x0a, 0x46, 0x8b, 0x5c, 0xf2, 0x99, 0x19, 0x33, - 0x37, 0xd7, 0x8c, 0x54, 0x25, 0xb8, 0xa2, 0x55, 0xb4, 0x3d, 0xaa, 0x5f, 0xe4, 0x5a, 0x7e, 0x64, 0x59, 0x12, 0xe5, - 0xd8, 0x48, 0x91, 0x3c, 0xca, 0x0a, 0x62, 0x93, 0x8d, 0x37, 0xeb, 0xf0, 0x98, 0x65, 0x2c, 0x9f, 0x52, 0x11, 0x70, - 0xb4, 0xdc, 0x35, 0x19, 0x87, 0x80, 0x8c, 0x9e, 0x0c, 0x7f, 0x5b, 0x5d, 0xf8, 0x0b, 0x61, 0x34, 0xf0, 0x03, 0xcd, - 0xa8, 0x9c, 0xf2, 0x04, 0x12, 0x53, 0xc2, 0xa4, 0xbc, 0xd1, 0x74, 0x70, 0xb0, 0x17, 0xf8, 0xca, 0x2d, 0x01, 0x57, - 0xbf, 0xdd, 0x1a, 0xd4, 0x5f, 0xc2, 0xf5, 0x9c, 0x6a, 0x6a, 0x8a, 0x96, 0x74, 0xfd, 0x26, 0x8b, 0x0c, 0x3f, 0xd2, - 0x5b, 0x2c, 0x50, 0x51, 0x44, 0x1a, 0x6a, 0x7f, 0xcc, 0x68, 0x9a, 0xf8, 0xf8, 0x23, 0xbd, 0x8d, 0xca, 0xdb, 0xe2, - 0xea, 0x72, 0xb3, 0xda, 0x40, 0x9f, 0x5f, 0x67, 0x3e, 0xae, 0x26, 0x89, 0x96, 0x05, 0xe6, 0x82, 0x4d, 0x80, 0x38, - 0xff, 0x46, 0x6f, 0x23, 0x3d, 0x1e, 0x73, 0x2e, 0xeb, 0xa1, 0xa5, 0x45, 0x7d, 0xe8, 0x14, 0xbb, 0xdb, 0x60, 0x0c, - 0x8a, 0x81, 0xea, 0x3b, 0x24, 0xb5, 0x76, 0x95, 0x79, 0x88, 0x50, 0x71, 0xdf, 0xa5, 0xe0, 0x2f, 0x5c, 0xd1, 0x26, - 0x6b, 0xa9, 0xaf, 0x6b, 0x9d, 0x28, 0x74, 0xa8, 0x72, 0x3d, 0xce, 0x03, 0x61, 0x4f, 0x9d, 0xb9, 0x83, 0xe0, 0x38, - 0xc2, 0xbe, 0x90, 0x66, 0xd0, 0xe8, 0x5b, 0x9d, 0x12, 0x52, 0x45, 0x92, 0x5e, 0x57, 0xfd, 0xbc, 0xf3, 0x00, 0xf0, - 0x0e, 0x29, 0x2d, 0xb1, 0xba, 0x8e, 0x59, 0xd8, 0x74, 0xd1, 0xef, 0x24, 0x09, 0x96, 0x76, 0x09, 0x91, 0x70, 0xb1, - 0x28, 0x0b, 0xa0, 0x42, 0x43, 0x5f, 0x3a, 0x03, 0x90, 0x8d, 0x03, 0xb6, 0x21, 0x35, 0x33, 0x25, 0x35, 0x43, 0x07, - 0xe3, 0x3b, 0xa4, 0x24, 0x55, 0xc8, 0x50, 0x4a, 0xa4, 0x12, 0x7a, 0x66, 0x73, 0x0d, 0x09, 0xb9, 0x1b, 0x5a, 0x5e, - 0x9f, 0xd3, 0x7b, 0x9e, 0xd5, 0xc0, 0x0a, 0xd4, 0x38, 0xa8, 0x88, 0x60, 0x49, 0x54, 0x37, 0x28, 0xac, 0x3b, 0x47, - 0xd8, 0xfc, 0xd6, 0x80, 0x87, 0x76, 0x59, 0xc4, 0xa2, 0x24, 0x98, 0xa2, 0xa5, 0x08, 0xa6, 0x38, 0x83, 0x7c, 0x44, - 0x5e, 0x94, 0xf0, 0x53, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, 0x21, 0x47, 0x13, 0x0b, - 0xcb, 0x53, 0x44, 0xa0, 0xee, 0xda, 0x39, 0xdb, 0xf6, 0x95, 0x49, 0xd1, 0x31, 0x80, 0x7d, 0x27, 0x83, 0xa5, 0xb3, - 0x0a, 0xf7, 0x2e, 0xb7, 0xb9, 0xf2, 0x67, 0x82, 0x7d, 0x55, 0x12, 0x69, 0x90, 0x93, 0x35, 0x89, 0x73, 0x77, 0xae, - 0xe5, 0xcf, 0x0b, 0x2a, 0x6e, 0xcf, 0x28, 0xe4, 0x3a, 0x73, 0xb8, 0xeb, 0x5b, 0x6d, 0x43, 0x95, 0xa7, 0xde, 0xcf, - 0x94, 0xb2, 0x52, 0xd4, 0x2f, 0x01, 0xae, 0x5f, 0x11, 0x2c, 0x54, 0xb4, 0xd1, 0x71, 0xc4, 0xe8, 0xd3, 0x42, 0x77, - 0x5e, 0x9e, 0xa4, 0x5d, 0x06, 0xfe, 0xb5, 0x0a, 0xd3, 0x26, 0x58, 0x80, 0xb9, 0x7b, 0x21, 0x75, 0x90, 0x0f, 0xd7, - 0xbd, 0x32, 0x50, 0x04, 0xe1, 0xbb, 0x6c, 0xf7, 0x52, 0xb7, 0x65, 0xcd, 0xee, 0x5e, 0x6a, 0x2d, 0xe8, 0xa7, 0x52, - 0x7e, 0xb0, 0x99, 0xa7, 0xbc, 0xbc, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0xf7, 0xdd, 0x20, 0xf8, 0xde, 0x24, 0x0d, - 0x86, 0x10, 0x8b, 0x3d, 0x4b, 0xb9, 0x65, 0xe2, 0xd5, 0xfc, 0xdf, 0x6f, 0xcc, 0xff, 0xbd, 0x73, 0xe5, 0x14, 0x4c, - 0xa3, 0x49, 0x46, 0x13, 0xcb, 0x3a, 0x91, 0x26, 0x40, 0xa5, 0xb7, 0xe5, 0x92, 0x7c, 0xbc, 0x88, 0x40, 0xe3, 0x5a, - 0x8e, 0x79, 0x26, 0x9b, 0xe3, 0x78, 0xc6, 0xd2, 0xdb, 0x68, 0xc1, 0x9a, 0x33, 0x9e, 0xf1, 0x7c, 0x1e, 0x8f, 0x28, - 0xce, 0x6f, 0x73, 0x49, 0x67, 0xcd, 0x05, 0xc3, 0x2f, 0x69, 0x7a, 0x45, 0x25, 0x1b, 0xc5, 0xd8, 0x3f, 0x11, 0x2c, - 0x4e, 0xbd, 0x37, 0xb1, 0x10, 0xfc, 0xda, 0xc7, 0xef, 0xf8, 0x25, 0x97, 0x1c, 0xbf, 0xbd, 0xb9, 0x9d, 0xd0, 0x0c, - 0x7f, 0xb8, 0x5c, 0x64, 0x72, 0x81, 0xf3, 0x38, 0xcb, 0x9b, 0x39, 0x15, 0x6c, 0xdc, 0x1d, 0xf1, 0x94, 0x8b, 0x26, - 0xa4, 0x6c, 0xcf, 0x68, 0x94, 0xb2, 0xc9, 0x54, 0x7a, 0x49, 0x2c, 0x3e, 0x76, 0x9b, 0xcd, 0xb9, 0x60, 0xb3, 0x58, - 0xdc, 0x36, 0x55, 0x8b, 0xe8, 0xb3, 0xd6, 0x51, 0xfc, 0xf9, 0xf8, 0x61, 0x57, 0x8a, 0x38, 0xcb, 0x19, 0x6c, 0x53, - 0x14, 0xa7, 0xa9, 0x77, 0xf4, 0xa8, 0x35, 0xcb, 0xf7, 0x74, 0x20, 0x2f, 0xce, 0x64, 0x71, 0x81, 0x3f, 0x02, 0xdc, - 0xe1, 0xa5, 0xcc, 0xf0, 0xe5, 0x42, 0x4a, 0x9e, 0x2d, 0x47, 0x0b, 0x91, 0x73, 0x11, 0xcd, 0x39, 0xcb, 0x24, 0x15, - 0xdd, 0x4b, 0x2e, 0x12, 0x2a, 0x9a, 0x22, 0x4e, 0xd8, 0x22, 0x8f, 0x1e, 0xce, 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x04, - 0x5f, 0x64, 0x89, 0x99, 0x8b, 0x65, 0x53, 0x2a, 0x98, 0x74, 0x2b, 0xd4, 0x2b, 0x4c, 0xa2, 0x94, 0x65, 0x34, 0x16, - 0xcd, 0x09, 0x74, 0x06, 0xb3, 0xa8, 0x95, 0xd0, 0x09, 0x16, 0x93, 0xcb, 0x38, 0x68, 0x77, 0x9e, 0x60, 0xfb, 0x37, - 0x7c, 0x84, 0xbc, 0xd6, 0xf6, 0xe2, 0x76, 0xab, 0xf5, 0x27, 0xd4, 0x5d, 0x9b, 0x45, 0x01, 0x14, 0xb5, 0xe7, 0x37, - 0x5e, 0xce, 0x21, 0xa7, 0x6d, 0x5b, 0xcf, 0xee, 0x3c, 0x4e, 0x20, 0x21, 0x38, 0xea, 0xcc, 0x6f, 0x0a, 0x58, 0x5d, - 0xa4, 0x93, 0x4c, 0xcd, 0x22, 0xcd, 0xd3, 0xf2, 0xb7, 0x42, 0xfc, 0x74, 0x3b, 0xc4, 0x1d, 0x0b, 0x71, 0x85, 0xf5, - 0x66, 0xb2, 0x10, 0x2a, 0xb6, 0x1a, 0xb5, 0x73, 0x0d, 0xc8, 0x94, 0x5f, 0x51, 0x61, 0xe1, 0x50, 0x0f, 0xbf, 0x19, - 0x8c, 0xce, 0x76, 0x30, 0x9e, 0x7e, 0x0a, 0x0c, 0x91, 0x25, 0xcb, 0xfa, 0xbe, 0xb6, 0x05, 0x9d, 0x75, 0xa7, 0x14, - 0xe8, 0x29, 0xea, 0xc0, 0xef, 0x6b, 0x96, 0xc8, 0xa9, 0xfe, 0xa9, 0xc8, 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, - 0x73, 0xce, 0x7e, 0xa1, 0x51, 0x3b, 0x84, 0x06, 0xc5, 0x05, 0xfe, 0x5b, 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xf1, 0x0f, - 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x8d, 0x85, 0x95, 0x95, 0x5a, 0xf8, 0x80, 0xdb, 0x4e, 0x9d, 0x27, - 0xc2, 0x7a, 0xe5, 0x2d, 0x4e, 0xd6, 0xff, 0x41, 0xe7, 0x5d, 0x44, 0x10, 0xe9, 0x70, 0x92, 0x0d, 0x79, 0x37, 0xeb, - 0x91, 0x56, 0x37, 0x6b, 0x36, 0x51, 0xc0, 0x89, 0x18, 0x64, 0x26, 0x3d, 0x2f, 0x60, 0x7d, 0xae, 0x8c, 0xed, 0x1c, - 0x45, 0x1c, 0xae, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0xa9, 0xeb, 0x1a, 0x7f, 0x93, 0xa6, 0x01, 0xce, 0x1d, 0x4e, - 0x9e, 0xd9, 0x17, 0xbb, 0x08, 0xcb, 0x2b, 0x52, 0x3e, 0x52, 0x98, 0x0b, 0xe7, 0xb1, 0x9c, 0x82, 0x97, 0xa2, 0x14, - 0x3f, 0x55, 0x12, 0x93, 0x7f, 0xe8, 0xa3, 0xbe, 0x28, 0x33, 0xdc, 0x20, 0x93, 0x4f, 0x14, 0x30, 0xca, 0x37, 0x92, - 0xc0, 0x88, 0xf8, 0x17, 0xa2, 0x6d, 0x3a, 0x6b, 0xd1, 0x8d, 0xef, 0x6b, 0xd1, 0xd1, 0x4c, 0x32, 0x95, 0xbb, 0x6d, - 0x23, 0x0e, 0xd3, 0x38, 0x3f, 0x1f, 0xe9, 0xbb, 0x92, 0x79, 0x75, 0x33, 0x20, 0x56, 0xd0, 0x6b, 0x23, 0x8d, 0x0a, - 0x65, 0x8f, 0x7e, 0x2f, 0x77, 0xda, 0x27, 0xe2, 0x2e, 0xfb, 0xa4, 0x5c, 0x78, 0xce, 0x17, 0x62, 0x04, 0xe1, 0x48, - 0x23, 0xf5, 0x36, 0x1d, 0x37, 0xbe, 0x52, 0x31, 0x7c, 0x2c, 0x9d, 0x4c, 0x50, 0x89, 0x99, 0xfb, 0x52, 0x09, 0xaa, - 0x42, 0x5e, 0xfa, 0xbe, 0x86, 0x11, 0x71, 0x76, 0x49, 0x20, 0xb3, 0x13, 0x95, 0xd4, 0x18, 0x64, 0xa4, 0x97, 0x85, - 0x8b, 0x8c, 0xfd, 0xbc, 0xa0, 0xe7, 0x0c, 0x74, 0x4d, 0x16, 0xb2, 0x44, 0xc5, 0x9a, 0x40, 0xf6, 0x35, 0xdb, 0x10, - 0xbc, 0x60, 0x89, 0xde, 0x98, 0x4c, 0x55, 0x9a, 0xdc, 0x26, 0xbf, 0xe9, 0x83, 0xbf, 0x18, 0xb4, 0x03, 0x86, 0x13, - 0x3e, 0x8b, 0x59, 0x16, 0x29, 0x97, 0x6f, 0x39, 0x58, 0x04, 0xad, 0x31, 0x4b, 0xa2, 0xcc, 0x6c, 0x4f, 0x1b, 0x85, - 0x3f, 0x71, 0x96, 0xa9, 0xae, 0x45, 0x97, 0x2b, 0x84, 0x6a, 0xf4, 0x11, 0x8b, 0xe0, 0x13, 0x2d, 0xd7, 0x38, 0xc2, - 0x6e, 0x75, 0x79, 0xed, 0xbc, 0xb6, 0x03, 0xad, 0xb5, 0x8d, 0xd2, 0x46, 0x00, 0x5f, 0x2f, 0xcd, 0xb9, 0x90, 0x41, - 0x30, 0xc5, 0x29, 0x22, 0xbd, 0xa9, 0x72, 0x76, 0x1d, 0xa7, 0xea, 0xbf, 0x7e, 0xb3, 0x1d, 0xb5, 0x4b, 0xf3, 0xbd, - 0x76, 0x1b, 0x58, 0x27, 0x47, 0x99, 0x1b, 0xa5, 0x6a, 0x19, 0xe5, 0x6f, 0xbd, 0xd4, 0xea, 0xb9, 0x5c, 0x2e, 0x36, - 0xc7, 0x4d, 0x8b, 0xaa, 0xa0, 0x06, 0x84, 0x0a, 0x16, 0xed, 0x98, 0x0a, 0x15, 0xd5, 0xba, 0x4b, 0x55, 0xf2, 0x42, - 0x8b, 0xe8, 0xf3, 0xfd, 0xa5, 0x30, 0x33, 0x16, 0x17, 0xcc, 0x3a, 0x99, 0xea, 0x24, 0x57, 0x18, 0x8c, 0x38, 0x7a, - 0xe8, 0xb6, 0x66, 0x1a, 0x96, 0x5b, 0x22, 0xb6, 0xd2, 0x6d, 0xa8, 0x1f, 0xa9, 0x20, 0x55, 0xb8, 0x6b, 0x63, 0x00, - 0xc8, 0xd5, 0xdb, 0x06, 0x18, 0x98, 0xad, 0xb9, 0xb4, 0x4b, 0x00, 0x6d, 0x6c, 0x4c, 0xe1, 0x22, 0xcd, 0xc5, 0xfe, - 0xf2, 0x1b, 0x59, 0x1c, 0x3a, 0x4d, 0xd5, 0x6f, 0x96, 0xc0, 0xff, 0x20, 0x01, 0x97, 0x5a, 0x29, 0x8d, 0xfc, 0xaf, - 0xdf, 0x9e, 0xbd, 0xf7, 0xf1, 0x25, 0x4f, 0x6e, 0x23, 0x5f, 0x8a, 0x05, 0xf5, 0x0b, 0x14, 0xca, 0x29, 0xcd, 0xca, - 0x97, 0xf1, 0xf0, 0x94, 0x86, 0x29, 0x9f, 0xe8, 0x4b, 0x99, 0xeb, 0x46, 0xf2, 0xe8, 0xe2, 0x58, 0xbd, 0x64, 0xaa, - 0x77, 0x2c, 0xf5, 0xeb, 0xbd, 0xa4, 0x80, 0x9f, 0x3d, 0x08, 0xa1, 0x1c, 0x1f, 0xca, 0xa9, 0x7a, 0x38, 0x83, 0x03, - 0xa3, 0x9e, 0xf6, 0x97, 0x1b, 0xc4, 0xd4, 0x87, 0x21, 0xa6, 0x3d, 0xbd, 0x84, 0x5c, 0xb5, 0xba, 0x88, 0x46, 0x17, - 0x17, 0xc5, 0xf1, 0x21, 0x8c, 0x75, 0x68, 0xc7, 0x05, 0x08, 0x6d, 0xff, 0x92, 0xc0, 0xe0, 0x65, 0x43, 0x82, 0xf4, - 0x60, 0x08, 0x98, 0x37, 0xe9, 0xc1, 0x22, 0x81, 0xc0, 0xa0, 0x77, 0x52, 0x96, 0xa8, 0x13, 0xab, 0x8b, 0x76, 0x41, - 0xa0, 0x1b, 0x56, 0x74, 0xaf, 0xbd, 0xa9, 0xd5, 0xfe, 0x5a, 0x90, 0x12, 0x17, 0xba, 0x0b, 0x04, 0xff, 0x2b, 0xc8, - 0x8e, 0x0f, 0x35, 0x1e, 0x2e, 0xdc, 0x57, 0x9b, 0xe8, 0xd7, 0x0e, 0x94, 0xd8, 0x1a, 0xe4, 0x12, 0x7f, 0x94, 0xf8, - 0xe3, 0x85, 0x6a, 0x6a, 0x85, 0x11, 0x68, 0x49, 0x20, 0xb4, 0x5b, 0x56, 0xeb, 0x18, 0xf1, 0x34, 0x8d, 0xe7, 0x39, - 0x8d, 0xec, 0x0f, 0x23, 0x97, 0x40, 0xbc, 0x6d, 0x2a, 0x02, 0x26, 0xbd, 0xe6, 0x14, 0xd4, 0x85, 0x4d, 0x2d, 0xe5, - 0x2a, 0x16, 0x41, 0xb3, 0x39, 0x6a, 0x5e, 0x4e, 0x50, 0x21, 0xa7, 0x4b, 0x57, 0xaa, 0x3d, 0x6e, 0xb5, 0xba, 0x90, - 0x0b, 0xd9, 0x8c, 0x53, 0x36, 0xc9, 0xa2, 0x94, 0x8e, 0x65, 0x21, 0xe1, 0x96, 0xda, 0xd2, 0xaa, 0x11, 0x61, 0xe7, - 0x91, 0xa0, 0x33, 0x2f, 0x84, 0x7f, 0xef, 0x9e, 0xb8, 0x90, 0x49, 0x94, 0xc9, 0x69, 0x53, 0x65, 0xdd, 0xc2, 0x9d, - 0x01, 0x39, 0xad, 0x3d, 0x2f, 0x9d, 0x89, 0x46, 0x14, 0x54, 0xac, 0x42, 0x0a, 0x4f, 0x4e, 0xb1, 0x14, 0x6e, 0xbb, - 0x0c, 0x2d, 0x37, 0x56, 0xb0, 0x29, 0xe9, 0x8f, 0x50, 0x91, 0x2b, 0xc5, 0x78, 0xb3, 0xb1, 0x55, 0x97, 0xea, 0x4f, - 0x1b, 0xe8, 0x73, 0x14, 0xbb, 0x42, 0x3b, 0x96, 0x97, 0xba, 0xc7, 0x7d, 0x90, 0x59, 0x53, 0x39, 0xb1, 0xdb, 0x03, - 0x15, 0x2c, 0x9b, 0x2f, 0xe4, 0x40, 0x39, 0xb5, 0x05, 0x5c, 0x90, 0x18, 0x62, 0xa7, 0x04, 0x70, 0x30, 0x5c, 0x6a, - 0x60, 0x46, 0x71, 0x3a, 0x0a, 0x00, 0x22, 0xaf, 0xe9, 0x3d, 0x15, 0x74, 0x86, 0xba, 0x33, 0x96, 0x35, 0x75, 0xdd, - 0x23, 0x47, 0x2d, 0x09, 0x9f, 0xc0, 0x53, 0x11, 0xaa, 0xd1, 0xb0, 0xca, 0x5d, 0xdd, 0x82, 0xcb, 0x8b, 0x61, 0x51, - 0x74, 0x85, 0x0c, 0x06, 0xaf, 0x03, 0x34, 0xc4, 0xbf, 0x38, 0x2f, 0x67, 0xf1, 0xed, 0x51, 0xf1, 0x71, 0x07, 0xed, - 0x68, 0xe2, 0x9e, 0x05, 0xd5, 0xec, 0x17, 0x02, 0x0d, 0xdf, 0x05, 0x3e, 0xcd, 0xe7, 0x4d, 0xcd, 0xbb, 0x9a, 0x8a, - 0x64, 0x7d, 0xe8, 0x8a, 0x8c, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, - 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x50, 0x8d, 0x9f, 0x5c, 0x9c, 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, - 0x71, 0x9a, 0xc2, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, 0x90, 0xc3, 0x00, 0x15, 0xe6, 0x9c, 0x3e, 0x53, - 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, 0x32, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, - 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x7c, 0x91, 0x25, 0xbe, 0xf7, 0x97, 0x51, 0xca, 0x46, 0x1f, 0x89, 0xbf, - 0xbf, 0x0c, 0xd0, 0xe6, 0xb5, 0x47, 0xc5, 0x15, 0x2c, 0xc3, 0x46, 0x75, 0x47, 0x7a, 0x16, 0x3a, 0xbc, 0x58, 0xbf, - 0x15, 0xc7, 0xef, 0xed, 0x2f, 0x81, 0xf1, 0xe8, 0x79, 0x7a, 0x17, 0xc5, 0x79, 0xf5, 0xae, 0xab, 0x0a, 0x0a, 0x40, - 0xb3, 0x2e, 0xf7, 0x14, 0x51, 0x11, 0xff, 0x93, 0x94, 0xe6, 0x7b, 0x9a, 0xa9, 0x01, 0x9c, 0xd2, 0xf0, 0x37, 0xdf, - 0xfb, 0x4b, 0x59, 0x46, 0x4b, 0x8f, 0x86, 0x4a, 0xc9, 0x20, 0x3e, 0xcc, 0x05, 0x66, 0x6c, 0x98, 0x50, 0x19, 0xb3, - 0x54, 0x77, 0xe9, 0x5a, 0x03, 0x7c, 0x6d, 0x45, 0xab, 0x55, 0x5e, 0x5f, 0x0b, 0xab, 0x63, 0x50, 0xad, 0xec, 0xf8, - 0xb0, 0x82, 0x5b, 0xad, 0x4c, 0x9d, 0x49, 0x37, 0x34, 0x58, 0xad, 0x50, 0xd7, 0x79, 0x7f, 0x19, 0xa9, 0x6b, 0x43, - 0x00, 0x20, 0x37, 0x00, 0x42, 0xd0, 0x5a, 0x5f, 0x8b, 0x09, 0x52, 0xc2, 0x43, 0x19, 0x8b, 0x09, 0x95, 0x6b, 0x88, - 0x4d, 0x75, 0x8e, 0x6a, 0xd7, 0x06, 0xa8, 0x37, 0xa0, 0x8d, 0xeb, 0xd0, 0x5e, 0x00, 0xd2, 0xfb, 0xfb, 0x4b, 0x56, - 0x90, 0xfd, 0x25, 0xcd, 0x46, 0x3c, 0xa1, 0x1f, 0xde, 0x7d, 0x09, 0x97, 0x1c, 0x79, 0x06, 0x86, 0xc5, 0x14, 0x81, - 0xe0, 0x54, 0x9b, 0xa3, 0x45, 0x08, 0x57, 0x22, 0x44, 0x73, 0x02, 0x4f, 0xcd, 0xa5, 0x40, 0x2c, 0x7c, 0xaf, 0xaf, - 0x21, 0xa7, 0x89, 0x86, 0x99, 0x64, 0xaa, 0x17, 0x2f, 0x8e, 0x0f, 0x75, 0x6b, 0x2d, 0x02, 0x74, 0x23, 0x40, 0x82, - 0x3a, 0xa7, 0x15, 0x0e, 0x20, 0xaf, 0xd9, 0xc5, 0x43, 0xc2, 0xae, 0x4a, 0x62, 0x53, 0x17, 0xa8, 0x7a, 0xc7, 0x69, - 0x7c, 0x49, 0xd3, 0xde, 0xfe, 0x32, 0x5b, 0xad, 0x5a, 0xc5, 0xf1, 0xa1, 0x7e, 0xf4, 0x8e, 0x15, 0xdf, 0xd0, 0x2f, - 0xbc, 0x54, 0x5b, 0x0c, 0xb7, 0x12, 0x21, 0xdb, 0xd3, 0xa6, 0x39, 0x45, 0x66, 0x80, 0xc2, 0xf7, 0x54, 0x82, 0x85, - 0x6a, 0x54, 0x2a, 0x44, 0x85, 0xef, 0xb1, 0x64, 0xb3, 0x2c, 0x97, 0x74, 0x0e, 0xa5, 0xd3, 0xd5, 0xaa, 0x5d, 0xf8, - 0xde, 0x8c, 0x65, 0xf0, 0x94, 0xad, 0x56, 0xea, 0xc2, 0xdf, 0x8c, 0x65, 0x41, 0x0b, 0xc8, 0xd6, 0xf7, 0x66, 0xf1, - 0x8d, 0x5a, 0xb0, 0xad, 0x89, 0x6f, 0x82, 0xb6, 0xa9, 0x0a, 0x4b, 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8e, 0xa6, 0x66, - 0x47, 0x13, 0xbc, 0xd0, 0x57, 0x99, 0x48, 0x90, 0x90, 0x74, 0xfb, 0x8e, 0x26, 0x76, 0x47, 0x17, 0x3b, 0x76, 0x74, - 0x71, 0xc7, 0x8e, 0xc6, 0x66, 0xf7, 0xbc, 0x12, 0x77, 0x7c, 0xb5, 0x6a, 0xb7, 0x2a, 0xec, 0x1d, 0x1f, 0x26, 0xec, - 0x0a, 0x76, 0x03, 0xd4, 0x3c, 0xc9, 0x66, 0x74, 0x3b, 0x51, 0xd6, 0x51, 0x4c, 0x7f, 0x15, 0x26, 0x2b, 0x2c, 0x64, - 0x75, 0x2c, 0xb8, 0x74, 0x5d, 0xc6, 0xdc, 0xfe, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x30, 0x35, 0x78, 0xb8, - 0x28, 0xce, 0x41, 0x24, 0xa8, 0xe5, 0xdc, 0x8b, 0xf4, 0xa0, 0xb5, 0xdf, 0xdb, 0x4d, 0x62, 0x10, 0x0d, 0xbf, 0xe6, - 0x22, 0xf1, 0x23, 0xdd, 0xf4, 0x57, 0x61, 0x66, 0xc6, 0x32, 0x93, 0x5b, 0xb5, 0x93, 0xb4, 0xaa, 0x7a, 0x97, 0xc0, - 0x3a, 0x8f, 0x1e, 0xe9, 0x16, 0xf3, 0x58, 0x4a, 0x2a, 0x32, 0x43, 0xa8, 0xbe, 0xff, 0xff, 0x05, 0xd1, 0x6d, 0x61, - 0x23, 0xb1, 0x65, 0x23, 0x96, 0xde, 0x8c, 0x7e, 0x6e, 0x58, 0xbc, 0x96, 0x46, 0x7b, 0x95, 0xc2, 0x7a, 0x8b, 0x5c, - 0x1b, 0x41, 0x17, 0x81, 0xc9, 0xb2, 0x98, 0xd1, 0xe4, 0x5c, 0xf1, 0xe3, 0xfe, 0xe8, 0xc2, 0xe8, 0xa7, 0x6b, 0xd2, - 0xad, 0xea, 0x80, 0xfd, 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x7d, 0xac, 0x59, 0x3a, 0x1f, 0x8f, 0x7d, 0x54, 0x78, - 0xf7, 0xeb, 0xd6, 0x7e, 0xf8, 0xe3, 0xe2, 0x8b, 0x17, 0xad, 0x2f, 0xca, 0xce, 0x99, 0x8f, 0x8a, 0x0b, 0x13, 0xce, - 0xb7, 0x92, 0xc9, 0x81, 0xd7, 0xae, 0x68, 0x1c, 0x67, 0xbb, 0x97, 0x33, 0x70, 0x97, 0x93, 0xcf, 0x29, 0x4d, 0xb0, - 0xef, 0xf9, 0x78, 0xa3, 0xf4, 0x3c, 0xa5, 0x57, 0xd4, 0xbe, 0x68, 0x70, 0xcb, 0x64, 0x5b, 0x7a, 0x8c, 0xf8, 0x22, - 0x93, 0x26, 0xaf, 0xc1, 0x70, 0x56, 0x67, 0x49, 0x17, 0x6a, 0x0d, 0xae, 0x49, 0x70, 0xab, 0xc5, 0x5a, 0x5d, 0x58, - 0x15, 0x17, 0xd8, 0x77, 0x00, 0xd8, 0x09, 0x59, 0x7f, 0x47, 0x79, 0xd4, 0xc2, 0xad, 0x5d, 0xb0, 0xe1, 0x36, 0x8a, - 0x7c, 0x7f, 0x68, 0xf1, 0xa4, 0x5c, 0x93, 0xb5, 0xf7, 0x43, 0xec, 0xc4, 0xd7, 0x27, 0x31, 0x70, 0x29, 0x60, 0xb0, - 0x8c, 0xe6, 0xf9, 0x4e, 0x04, 0x94, 0x9b, 0x88, 0xfd, 0xaa, 0xb5, 0xbf, 0x63, 0x14, 0xdc, 0xc2, 0x70, 0xc2, 0x14, - 0xc0, 0x65, 0x80, 0xd4, 0xb4, 0xa2, 0xe3, 0x31, 0x1d, 0x95, 0x9e, 0x5d, 0x08, 0x75, 0x8d, 0x59, 0x2a, 0x21, 0xe2, - 0xa3, 0x42, 0x31, 0xfe, 0x1b, 0x9e, 0x51, 0x1f, 0xd9, 0xe4, 0x4d, 0x03, 0xbf, 0x11, 0xf7, 0xdb, 0xe1, 0xd1, 0x23, - 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, 0xab, 0x53, 0x2b, 0xaf, 0x23, 0x92, 0x2b, 0xb7, 0xcd, 0xae, 0x03, 0x74, - 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, 0xdd, 0x2a, 0x7c, 0xec, 0xc3, 0x70, 0xf7, 0x3d, 0x25, 0xaa, 0xd7, 0x11, - 0xf4, 0x5a, 0x64, 0xbf, 0xa6, 0x5f, 0xa7, 0xfd, 0x79, 0xdb, 0xc7, 0xfa, 0xbd, 0x01, 0xa8, 0x28, 0x99, 0xc1, 0x08, - 0x7c, 0x9d, 0xbf, 0x7b, 0x29, 0xf5, 0xc1, 0xef, 0x07, 0xcf, 0xe3, 0x76, 0xcb, 0xc7, 0x7e, 0x2e, 0xf9, 0xfc, 0x57, - 0x2c, 0xe1, 0xc8, 0xc7, 0xfe, 0x28, 0xe5, 0x39, 0x75, 0xd7, 0xa0, 0xb5, 0xd7, 0xdf, 0xbf, 0x08, 0x0d, 0xd1, 0x5c, - 0xd0, 0x3c, 0xf7, 0xdc, 0xf1, 0x0d, 0x29, 0x7d, 0x82, 0x61, 0x6e, 0xa5, 0xb8, 0x9c, 0x4a, 0x85, 0x17, 0x7d, 0xa5, - 0xdf, 0xa5, 0x2a, 0x5d, 0xb6, 0x41, 0x6c, 0x4a, 0x04, 0x94, 0x8c, 0x4d, 0x2b, 0x53, 0x9f, 0x9c, 0x79, 0xcb, 0xd1, - 0xd3, 0x13, 0xeb, 0x10, 0xf0, 0xe6, 0x04, 0xb5, 0x92, 0x19, 0xcb, 0xce, 0xb7, 0x94, 0xc6, 0x37, 0x5b, 0x4a, 0x41, - 0x43, 0x2b, 0xa1, 0x33, 0x6f, 0x9b, 0xf9, 0x34, 0xd6, 0x2b, 0x3d, 0xc7, 0x05, 0x31, 0x51, 0x6e, 0xca, 0x4f, 0x40, - 0xea, 0x6c, 0x83, 0x1a, 0xe1, 0xb7, 0x4f, 0x07, 0x25, 0xbf, 0x6a, 0x3a, 0x7a, 0xf3, 0xe9, 0x3d, 0x77, 0x14, 0x9b, - 0xdf, 0x81, 0x7d, 0x73, 0x73, 0x7c, 0x1d, 0xfd, 0x5b, 0x8a, 0x8d, 0xee, 0x51, 0x6e, 0xc1, 0x28, 0x65, 0xb3, 0x6a, - 0x17, 0x36, 0xc1, 0x54, 0x4a, 0x07, 0xa4, 0x0f, 0xb9, 0x83, 0x68, 0xed, 0xe3, 0x1c, 0x2e, 0x45, 0xc2, 0x9b, 0x27, - 0x16, 0x82, 0x9e, 0xa7, 0xfc, 0x7a, 0xfd, 0x4d, 0x5a, 0xbb, 0x1b, 0x4f, 0xd9, 0x64, 0xea, 0xdc, 0x74, 0xa2, 0xa4, - 0x44, 0xfd, 0x9d, 0x13, 0x14, 0xff, 0xfa, 0x2f, 0x61, 0xf8, 0xaf, 0xff, 0xf2, 0xc9, 0xa6, 0x30, 0x7c, 0x71, 0x81, - 0x65, 0x35, 0xec, 0x6e, 0x02, 0xdf, 0x3e, 0x53, 0x1d, 0xe7, 0xdb, 0xdb, 0x6c, 0x6c, 0x02, 0xd4, 0x6f, 0x6c, 0xc1, - 0x46, 0xa1, 0x3e, 0x00, 0xde, 0x6f, 0x01, 0x0c, 0xd6, 0xf5, 0x49, 0xc8, 0xa0, 0xd1, 0xef, 0x02, 0xed, 0x02, 0x45, - 0xf7, 0xda, 0x91, 0xdf, 0x8e, 0xe1, 0x4f, 0xad, 0xe1, 0x77, 0x82, 0x6f, 0x3c, 0x02, 0xa3, 0x8b, 0x8b, 0x32, 0xa5, - 0xcd, 0xed, 0x0a, 0x57, 0xe6, 0xfb, 0x1b, 0x25, 0x46, 0xf6, 0x47, 0x2d, 0xd4, 0x53, 0x17, 0xf2, 0xc8, 0xe8, 0xe2, - 0x35, 0xbc, 0x27, 0xe7, 0xf8, 0x52, 0x58, 0x97, 0xea, 0x1d, 0xfc, 0x19, 0x86, 0xa8, 0xaf, 0x4a, 0x0d, 0xba, 0xc1, - 0x9c, 0xa1, 0x14, 0x34, 0x7e, 0x00, 0x13, 0x8f, 0x2e, 0x8c, 0x7d, 0x77, 0xaa, 0x1d, 0x1f, 0xd1, 0x3a, 0x69, 0x1b, - 0x87, 0x48, 0x0d, 0xe9, 0xd8, 0x7b, 0xaf, 0xf0, 0xa5, 0x1a, 0xd3, 0xca, 0x9e, 0x56, 0xce, 0x25, 0x50, 0xe5, 0x2f, - 0x0a, 0x15, 0x18, 0xff, 0xeb, 0xae, 0xd8, 0xdd, 0xdf, 0x3f, 0x1d, 0xbb, 0xe3, 0xf7, 0x8a, 0xdd, 0xfd, 0xfd, 0x0f, - 0x8f, 0xdd, 0xfd, 0xd5, 0x8d, 0xdd, 0xc1, 0x26, 0x7e, 0x79, 0xaf, 0xf8, 0x9a, 0x8d, 0x7d, 0xf0, 0xeb, 0x9c, 0xb4, - 0x8d, 0x26, 0x9b, 0xf2, 0x09, 0x04, 0xd7, 0xfe, 0xfd, 0x63, 0x65, 0x29, 0x9f, 0xb8, 0x91, 0x32, 0x78, 0x4f, 0x2a, - 0x84, 0xc6, 0xba, 0x36, 0xa6, 0x65, 0xa2, 0x53, 0xad, 0xf2, 0x0e, 0x48, 0xf3, 0xa1, 0x7d, 0x67, 0x81, 0x1f, 0x95, - 0xef, 0x1d, 0x6a, 0xe1, 0x8e, 0x8d, 0x5f, 0x45, 0x2a, 0xf4, 0x55, 0x76, 0xec, 0x34, 0xec, 0x05, 0x07, 0x77, 0x84, - 0xae, 0x7d, 0xaf, 0x8a, 0xbe, 0xef, 0xbe, 0xf4, 0x7f, 0xbc, 0x69, 0x3f, 0x1b, 0xb4, 0xbb, 0x47, 0xed, 0x99, 0x1f, - 0xf9, 0x20, 0xa5, 0x54, 0x41, 0xab, 0x7b, 0x74, 0x04, 0x05, 0xd7, 0x4e, 0x41, 0x07, 0x0a, 0x98, 0x53, 0xf0, 0x08, - 0x0a, 0x46, 0x4e, 0xc1, 0x63, 0x28, 0x48, 0x9c, 0x82, 0x27, 0x50, 0x70, 0xe5, 0x17, 0x03, 0x56, 0x82, 0xfb, 0x04, - 0x0d, 0xb1, 0x36, 0x1e, 0x6c, 0xd9, 0x13, 0xdc, 0x86, 0xa0, 0x59, 0x3c, 0x51, 0xb9, 0x3e, 0xe0, 0x82, 0x8b, 0x38, - 0xbe, 0x9e, 0xd2, 0x2c, 0x82, 0xb0, 0xe5, 0x73, 0x25, 0x63, 0x42, 0xc9, 0xdf, 0xb3, 0x19, 0xb5, 0x5f, 0xa8, 0xb0, - 0x78, 0xf0, 0x7c, 0x34, 0x68, 0x0d, 0x8b, 0x6e, 0xb9, 0x73, 0x3a, 0xda, 0x66, 0xf2, 0x3e, 0xf4, 0x5e, 0x56, 0x75, - 0x7a, 0xba, 0x66, 0xb9, 0xe7, 0x3b, 0xa2, 0x36, 0x8e, 0x3b, 0x60, 0x9c, 0xf2, 0xeb, 0xe6, 0x8d, 0xdf, 0xdb, 0x1e, - 0xc9, 0x01, 0x88, 0xca, 0x48, 0x8e, 0x5a, 0x53, 0xf9, 0xf4, 0x3e, 0x9e, 0x94, 0xbf, 0x5f, 0xd3, 0x3c, 0x8f, 0x27, - 0xa6, 0xe5, 0xee, 0xc8, 0x8d, 0x02, 0xd1, 0x8d, 0xda, 0x58, 0x20, 0x20, 0xfa, 0x02, 0x9b, 0x05, 0xe6, 0xb4, 0x09, - 0xc6, 0x00, 0x76, 0xea, 0x71, 0x1c, 0x35, 0x7d, 0xbd, 0x48, 0xc6, 0x93, 0xaa, 0xe0, 0x78, 0x2e, 0xa8, 0x2a, 0xd5, - 0x18, 0x2e, 0x8e, 0x0f, 0xa1, 0x40, 0x57, 0xef, 0x88, 0xd7, 0x58, 0xdb, 0x7d, 0x77, 0xd4, 0xc6, 0xb3, 0xf1, 0x1a, - 0x37, 0xc3, 0xa5, 0x4c, 0x6f, 0xd9, 0x8c, 0x12, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, 0x13, 0x83, 0xf8, 0x6c, 0x3c, 0x1e, - 0xdf, 0x19, 0xbf, 0xf9, 0x2c, 0x19, 0xd3, 0x0e, 0x7d, 0xd4, 0x85, 0xec, 0x87, 0xa6, 0xf1, 0xfa, 0xb7, 0x0b, 0x85, - 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0x80, 0x40, 0x4e, 0x97, 0xf7, 0x8f, 0xe5, 0x14, 0x73, 0x41, 0x97, 0xb3, 0x58, 0x4c, - 0x58, 0x16, 0xb5, 0x8a, 0xf0, 0xca, 0x04, 0x3f, 0x3e, 0x7b, 0xfa, 0xf4, 0x69, 0x11, 0x26, 0xf6, 0xa9, 0x95, 0x24, - 0x45, 0x38, 0x5a, 0x96, 0xcb, 0x68, 0xb5, 0xc6, 0xe3, 0x22, 0x64, 0xb6, 0xe0, 0xa8, 0x33, 0x4a, 0x8e, 0x3a, 0x45, - 0x78, 0xed, 0xb4, 0x28, 0x42, 0x6a, 0x9e, 0x04, 0x4d, 0x6a, 0x29, 0x14, 0x4f, 0x5a, 0xad, 0x22, 0xd4, 0x84, 0xb6, - 0x04, 0x8b, 0x48, 0xff, 0x8c, 0xe2, 0x85, 0xe4, 0xc0, 0x92, 0xbb, 0x5c, 0x06, 0x83, 0x73, 0xf3, 0x7a, 0x0a, 0xfd, - 0x29, 0x87, 0x02, 0x0d, 0xf1, 0x97, 0x6e, 0x98, 0x02, 0x88, 0x59, 0x85, 0x27, 0xb8, 0x8d, 0x62, 0xd4, 0xaa, 0x81, - 0xb2, 0x54, 0xf5, 0x97, 0x84, 0x57, 0xd1, 0x0b, 0xe0, 0x3f, 0xd0, 0x52, 0xbf, 0x47, 0x4d, 0xd2, 0x1d, 0x5c, 0x9f, - 0xd2, 0x4f, 0x72, 0xfd, 0xdb, 0xfb, 0x30, 0x7d, 0x4a, 0xff, 0x68, 0xa6, 0x6f, 0x5e, 0x36, 0xaa, 0x99, 0xbe, 0x66, - 0x6b, 0x33, 0x49, 0xfc, 0xd1, 0x94, 0x8e, 0x3e, 0x5e, 0xf2, 0x9b, 0x26, 0x1c, 0x09, 0xe1, 0x2b, 0x7e, 0xba, 0xff, - 0x5b, 0xd3, 0x2d, 0xec, 0x60, 0xce, 0x97, 0x20, 0x94, 0xd8, 0x7c, 0x9b, 0x11, 0xff, 0xad, 0x35, 0xab, 0x74, 0xc9, - 0x78, 0x4c, 0xfc, 0xb7, 0xe3, 0xb1, 0x6f, 0x2f, 0xd9, 0xc5, 0x92, 0xaa, 0x56, 0x6f, 0x6a, 0x25, 0xaa, 0xd5, 0x17, - 0x5f, 0xb8, 0x65, 0x6e, 0x81, 0x09, 0x72, 0xb8, 0x01, 0x0d, 0x53, 0x93, 0xb0, 0x1c, 0x8e, 0x1a, 0x7c, 0xa0, 0xa2, - 0xfe, 0x96, 0x3f, 0x51, 0x7b, 0x21, 0x73, 0x09, 0xf0, 0x96, 0xb7, 0x48, 0xaf, 0xdf, 0x30, 0x9f, 0x50, 0x9b, 0xf0, - 0xf6, 0xec, 0xf6, 0xcb, 0x24, 0x98, 0x49, 0x54, 0xb0, 0xfc, 0x6d, 0xb6, 0x76, 0x7b, 0x44, 0xc3, 0x48, 0x88, 0xbb, - 0xac, 0x42, 0xf2, 0xc9, 0x24, 0x85, 0x4f, 0x84, 0x2c, 0x6b, 0x6f, 0x1e, 0xd5, 0xdd, 0xfb, 0xb5, 0xf5, 0x46, 0x6e, - 0x47, 0xf3, 0x9e, 0x4e, 0xf5, 0xc5, 0x22, 0x9d, 0x75, 0x7c, 0x65, 0x3e, 0x5d, 0xa3, 0x2c, 0xb2, 0xa5, 0xe1, 0xff, - 0x4b, 0x9d, 0xab, 0x2a, 0x21, 0x4f, 0x43, 0x0f, 0x9c, 0x14, 0x85, 0xc9, 0xf2, 0x4f, 0x58, 0x3e, 0x87, 0x37, 0x62, - 0xea, 0x9e, 0xf4, 0x53, 0x2c, 0x3c, 0xbf, 0x76, 0x22, 0x09, 0xb5, 0xed, 0x2a, 0x6c, 0x28, 0x41, 0xfb, 0x6a, 0x67, - 0xb2, 0xf0, 0x8d, 0xcb, 0xd7, 0x22, 0xd1, 0xf7, 0x34, 0x3e, 0x75, 0x8c, 0xc3, 0x59, 0x21, 0xf8, 0x5d, 0xcb, 0x0d, - 0xb1, 0x55, 0xb6, 0xa0, 0x70, 0x23, 0x65, 0xaa, 0x46, 0x63, 0x4b, 0xf9, 0xe5, 0xf3, 0x79, 0x9c, 0x69, 0x36, 0x4a, - 0x7c, 0xcd, 0x0f, 0xf6, 0x97, 0xd5, 0xce, 0x17, 0xbe, 0x05, 0x5b, 0x13, 0x6f, 0xef, 0xf8, 0x10, 0x3a, 0xf4, 0xbc, - 0x1a, 0xe8, 0xd9, 0x86, 0x3b, 0xff, 0x13, 0x81, 0xf5, 0x8b, 0x30, 0xbf, 0xc6, 0x61, 0x7e, 0xed, 0xfd, 0x79, 0xd9, - 0xbc, 0xa6, 0x97, 0x1f, 0x99, 0x6c, 0xca, 0x78, 0xde, 0x04, 0x85, 0x5f, 0xf9, 0xe5, 0x0c, 0x7b, 0x56, 0xe9, 0x61, - 0xfa, 0x8e, 0x7c, 0x77, 0x91, 0x43, 0xfc, 0x5d, 0xa9, 0xad, 0x51, 0xc6, 0x33, 0xda, 0xad, 0xa7, 0x01, 0xba, 0xe1, - 0x5c, 0x8b, 0xad, 0xe1, 0x92, 0x43, 0xbc, 0x5e, 0xde, 0x46, 0x2d, 0xc3, 0xd6, 0x5b, 0x36, 0x56, 0xdb, 0xda, 0xda, - 0x3e, 0x32, 0xc8, 0x6d, 0x28, 0xe9, 0x25, 0x36, 0x63, 0xd6, 0xbb, 0x62, 0xce, 0x9f, 0x4a, 0x8a, 0x03, 0x6f, 0x9e, - 0xfd, 0xeb, 0x64, 0x13, 0xae, 0x17, 0xab, 0xa4, 0xb8, 0xfb, 0x40, 0x16, 0xc5, 0x63, 0x49, 0x05, 0xbe, 0x4f, 0xcb, - 0x4b, 0x75, 0x7f, 0x65, 0x09, 0x62, 0x26, 0x6a, 0x3f, 0x9d, 0xdf, 0xdc, 0x7f, 0xf8, 0xbb, 0x97, 0x5f, 0x18, 0x1c, - 0xd9, 0xf7, 0xb9, 0xf8, 0x7e, 0x17, 0x0e, 0x42, 0x1a, 0xdf, 0x46, 0x2c, 0x53, 0x32, 0xef, 0x12, 0x5c, 0x72, 0xdd, - 0x39, 0x37, 0xd9, 0x9d, 0x82, 0xa6, 0xea, 0xe3, 0x6d, 0x66, 0x2b, 0x8e, 0x1e, 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, - 0xb2, 0x36, 0xff, 0xd0, 0xe4, 0xcc, 0xdd, 0xd9, 0xa0, 0xf5, 0x04, 0xc3, 0x47, 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0x4d, - 0xa1, 0xa1, 0x6a, 0xcd, 0x6f, 0xdc, 0xf4, 0xd4, 0x6a, 0x20, 0x2f, 0x3c, 0xca, 0x3d, 0x1a, 0xe7, 0xb4, 0x0b, 0x6f, - 0xac, 0x66, 0xa3, 0x38, 0x35, 0xc2, 0x7c, 0xc6, 0x92, 0x24, 0xa5, 0x5d, 0x2b, 0xaf, 0xbd, 0xf6, 0x63, 0xc8, 0xee, - 0x74, 0xb7, 0xac, 0xbe, 0x2b, 0x0e, 0xf2, 0x4a, 0x3c, 0xc5, 0x97, 0x39, 0x4f, 0xe1, 0x73, 0x11, 0x5b, 0xd1, 0x69, - 0xd2, 0x1e, 0x5b, 0x15, 0xf2, 0xd4, 0xef, 0xfa, 0x5a, 0x1e, 0xb5, 0xfe, 0xd4, 0x55, 0x1b, 0xde, 0xea, 0x4a, 0x3e, - 0x8f, 0x9a, 0x47, 0xf5, 0x85, 0x40, 0x55, 0xb9, 0x04, 0xbc, 0x65, 0x59, 0x18, 0xa4, 0x95, 0xe6, 0xd3, 0x5e, 0xd8, - 0x36, 0x65, 0x6a, 0x00, 0x78, 0xb5, 0x72, 0x59, 0x54, 0xd4, 0x17, 0xf3, 0xef, 0x73, 0x5a, 0x3e, 0xdf, 0x7e, 0x5a, - 0x3e, 0xb7, 0xa7, 0xe5, 0x6e, 0x8a, 0xfd, 0x6c, 0xdc, 0x86, 0x3f, 0xdd, 0x6a, 0x41, 0x51, 0xcb, 0x3b, 0x9a, 0xdf, - 0x78, 0xa0, 0xa7, 0x35, 0x3b, 0xf3, 0x1b, 0x9d, 0x9c, 0x0b, 0x61, 0x83, 0x16, 0xa4, 0xab, 0xe2, 0x96, 0x07, 0x85, - 0xf0, 0xb7, 0x55, 0xab, 0x6a, 0x3f, 0x84, 0x3a, 0xe8, 0xf5, 0x68, 0xb3, 0xae, 0x73, 0xf7, 0xa1, 0x8d, 0x32, 0x2e, - 0x83, 0xc8, 0x72, 0x63, 0x14, 0xca, 0xf8, 0xf2, 0x92, 0x26, 0xd1, 0x98, 0x8f, 0x16, 0xf9, 0x3f, 0x1b, 0xf8, 0x0d, - 0x12, 0xef, 0x3c, 0xd2, 0x6b, 0xe3, 0xd8, 0xae, 0x3a, 0x55, 0xd8, 0x8e, 0xb0, 0x2c, 0xf7, 0x29, 0xca, 0x47, 0x71, - 0x4a, 0x83, 0x4e, 0xf8, 0x70, 0xcb, 0x21, 0xf8, 0x0f, 0xd9, 0x9b, 0xad, 0x8b, 0xf9, 0xbd, 0xc8, 0xb8, 0x13, 0x09, - 0xbf, 0x0a, 0x07, 0xee, 0x1e, 0xb6, 0x9e, 0x6e, 0x07, 0x77, 0x60, 0x67, 0x1a, 0x5a, 0xa1, 0x60, 0xe4, 0x4e, 0x42, - 0xc7, 0xf1, 0x22, 0x95, 0x77, 0x8f, 0xba, 0x8b, 0x32, 0x36, 0x46, 0xbd, 0x83, 0xa1, 0x57, 0x6d, 0xef, 0xc9, 0xa5, - 0x3f, 0xfb, 0xfc, 0x21, 0xfc, 0xd1, 0x99, 0x46, 0xb7, 0x95, 0xae, 0xae, 0x6d, 0x55, 0xd0, 0xd5, 0xf7, 0x6b, 0xca, - 0xb8, 0x16, 0xe1, 0x4a, 0x1f, 0xbf, 0x6f, 0x6b, 0xd0, 0x2a, 0xef, 0xd5, 0xdc, 0x68, 0x59, 0xbf, 0xaa, 0xf5, 0xaf, - 0x1b, 0xfc, 0x9e, 0x6d, 0x47, 0x5a, 0x73, 0xad, 0xb7, 0x35, 0x5f, 0xaf, 0xdb, 0x68, 0x6c, 0x31, 0xae, 0xda, 0xef, - 0x93, 0xdb, 0xd2, 0x44, 0xd1, 0x81, 0x40, 0xb0, 0x52, 0xf6, 0xb5, 0x95, 0xc2, 0x28, 0x79, 0x00, 0xef, 0x8e, 0xf5, - 0x6e, 0x66, 0x69, 0x96, 0x13, 0x7f, 0x2a, 0xe5, 0x3c, 0xd2, 0x9f, 0x3b, 0xbd, 0x3e, 0x0a, 0xb9, 0x98, 0x1c, 0x76, - 0x5a, 0xad, 0x16, 0xbc, 0xf3, 0xd3, 0xf7, 0xae, 0x18, 0xbd, 0x7e, 0xc6, 0x6f, 0x88, 0xff, 0xc4, 0x7b, 0xea, 0x3d, - 0x39, 0xf2, 0x1e, 0x3d, 0xf6, 0x3d, 0xc5, 0xce, 0x89, 0xff, 0xe4, 0xc8, 0xf7, 0x34, 0x3b, 0x27, 0xfe, 0xa3, 0xc7, - 0x7e, 0xef, 0x78, 0x62, 0x55, 0x32, 0xb8, 0x34, 0xa8, 0xf5, 0x9d, 0x5c, 0x0a, 0xfe, 0x91, 0xd6, 0x0f, 0xae, 0x2e, - 0x33, 0xb9, 0x68, 0x1d, 0xfb, 0x08, 0xa7, 0x77, 0x14, 0xcf, 0x23, 0x45, 0x14, 0x6e, 0x21, 0xb8, 0x65, 0x74, 0xa9, - 0x9a, 0x02, 0xd4, 0xcc, 0x4b, 0xbf, 0x77, 0x0c, 0x79, 0xe3, 0x5e, 0x42, 0xfc, 0xd7, 0x9d, 0x27, 0x5e, 0xfb, 0xf1, - 0x55, 0xf3, 0xe1, 0xa8, 0xd5, 0x6c, 0x7b, 0xed, 0x66, 0x27, 0x7c, 0xe2, 0x75, 0xf4, 0xbf, 0x5e, 0xcb, 0x3b, 0xf2, - 0xda, 0xe1, 0x13, 0xef, 0xc8, 0xeb, 0x84, 0x4f, 0xae, 0x1e, 0xea, 0x7c, 0x82, 0xd8, 0x3f, 0xec, 0x1d, 0xc3, 0xa7, - 0x2b, 0x6f, 0x88, 0xff, 0xb9, 0xaf, 0x3f, 0x10, 0xeb, 0x7f, 0xe6, 0x96, 0xb6, 0x9f, 0x6e, 0x2d, 0xee, 0x3c, 0xd9, - 0x5a, 0x7c, 0xf4, 0x78, 0x6b, 0xf1, 0xc3, 0x47, 0xf5, 0xe2, 0xc3, 0x89, 0xae, 0x2a, 0x4f, 0x39, 0xf1, 0x67, 0xb1, - 0x14, 0xec, 0x26, 0x68, 0x7b, 0x2d, 0xaf, 0xe5, 0x35, 0xe1, 0xbf, 0x27, 0x1d, 0x54, 0xf6, 0xba, 0x84, 0x5e, 0xe5, - 0x2a, 0x9f, 0x3c, 0xf5, 0xda, 0x8f, 0x5f, 0x76, 0x1e, 0x8f, 0xa0, 0x9d, 0x5a, 0x68, 0xdb, 0x6b, 0x5f, 0x1d, 0x3d, - 0x1d, 0xb5, 0x3c, 0xe8, 0xd8, 0x86, 0x3f, 0xd3, 0x47, 0x9d, 0x91, 0x7e, 0x68, 0x41, 0xfd, 0xb7, 0xed, 0x27, 0x79, - 0xab, 0xd9, 0x86, 0x3f, 0xbf, 0x94, 0x1a, 0x31, 0xe8, 0xe3, 0xee, 0xb8, 0x0f, 0x5b, 0xde, 0xd1, 0xd3, 0x69, 0x27, - 0xfc, 0xfc, 0xea, 0x49, 0xf8, 0x74, 0xda, 0x7e, 0xf2, 0xad, 0x7e, 0x4a, 0x9b, 0x9d, 0xf0, 0x73, 0xf8, 0xfb, 0xed, - 0x51, 0x6b, 0xda, 0x6c, 0x87, 0x4f, 0xaf, 0x8e, 0xc2, 0xa3, 0xb4, 0xf9, 0x38, 0x7c, 0x0a, 0x7f, 0xab, 0xe1, 0xa6, - 0x7c, 0x46, 0x7d, 0x0f, 0xf6, 0x7b, 0xcd, 0xdc, 0x72, 0xe7, 0xe8, 0x3c, 0xf4, 0x1e, 0x3d, 0x7c, 0xf9, 0xf4, 0xaa, - 0xf9, 0x70, 0xda, 0xee, 0x5c, 0x35, 0x77, 0xfe, 0xfc, 0x16, 0x10, 0x6f, 0x06, 0x8e, 0x29, 0x5c, 0xe0, 0xb1, 0x88, - 0x53, 0xef, 0x9f, 0x7d, 0x80, 0xf3, 0x5d, 0xe6, 0xb5, 0xf8, 0xb4, 0x79, 0x9d, 0xd1, 0xfb, 0xd8, 0xd7, 0xe2, 0x0f, - 0xb7, 0xaf, 0x73, 0xba, 0xe6, 0x54, 0xbd, 0x95, 0x1b, 0x66, 0xf4, 0xba, 0xed, 0xf5, 0x4e, 0x06, 0x03, 0x06, 0xdf, - 0x39, 0x2a, 0xba, 0xb7, 0xf0, 0x8a, 0x6b, 0xd7, 0xdb, 0xc0, 0xe1, 0x20, 0xdf, 0x4a, 0x7d, 0x92, 0xf9, 0x2e, 0x84, - 0xa4, 0x9f, 0x46, 0xc8, 0xb7, 0xf7, 0xc1, 0x47, 0xfa, 0x87, 0xe3, 0x83, 0xbb, 0xf8, 0xa8, 0xf9, 0x79, 0x95, 0x3d, - 0xab, 0xec, 0xd1, 0x33, 0xf5, 0x1c, 0xc0, 0x1d, 0x8f, 0x86, 0x7f, 0x48, 0xa1, 0x28, 0xf7, 0x75, 0x5c, 0xe1, 0xcd, - 0xaf, 0x71, 0x49, 0xeb, 0x0b, 0x5d, 0xc4, 0x37, 0xc6, 0xff, 0x1c, 0xbe, 0x65, 0x60, 0x1f, 0xae, 0xf4, 0x15, 0x63, - 0xe2, 0x77, 0xc2, 0x56, 0xd8, 0x2a, 0x1d, 0x07, 0x70, 0x89, 0x8f, 0x2c, 0xb9, 0x8c, 0xe1, 0x73, 0x9a, 0x29, 0x9f, - 0xa8, 0x0f, 0x6f, 0xc2, 0xeb, 0xce, 0xd5, 0x27, 0x50, 0xf5, 0x9b, 0xe6, 0x23, 0xdf, 0x37, 0x57, 0xff, 0xe1, 0x92, - 0xd8, 0x37, 0x70, 0x91, 0xce, 0x7a, 0xac, 0x67, 0x60, 0x53, 0xbf, 0xa6, 0x09, 0x8b, 0x03, 0x3f, 0x98, 0x0b, 0x3a, - 0xa6, 0x22, 0x6f, 0xd6, 0x6e, 0x97, 0xa9, 0x8b, 0x65, 0xc8, 0xb7, 0x1f, 0x6e, 0x14, 0xf0, 0xfa, 0x5e, 0x32, 0x30, - 0x5e, 0x2d, 0xdf, 0xa8, 0xf9, 0x7e, 0x81, 0x6d, 0x89, 0x00, 0x8e, 0x5e, 0xa9, 0x06, 0xbe, 0xd6, 0x0d, 0xda, 0x61, - 0xe7, 0x11, 0xd2, 0xbc, 0x04, 0x5e, 0x8b, 0xfa, 0x7d, 0xd0, 0x3c, 0x6a, 0xfd, 0x09, 0x39, 0xdd, 0xca, 0x81, 0x86, - 0xc6, 0xa9, 0x23, 0xaa, 0x0f, 0xde, 0xd6, 0xaf, 0xfe, 0xf9, 0x9a, 0x22, 0x3e, 0xd3, 0x6b, 0x87, 0x17, 0xac, 0x9a, - 0xf8, 0xa1, 0xbe, 0xc0, 0x3e, 0x66, 0x93, 0xc0, 0xfd, 0x9c, 0xa9, 0x7e, 0xed, 0xaa, 0xfa, 0x0a, 0x32, 0x2a, 0xaa, - 0x26, 0x02, 0x2d, 0x95, 0x2f, 0x9e, 0x65, 0x9e, 0x58, 0xad, 0x02, 0x01, 0x8e, 0x58, 0xe2, 0xe0, 0x14, 0x9e, 0x51, - 0x0d, 0xc9, 0x02, 0x97, 0x00, 0x29, 0x04, 0x13, 0xa1, 0xff, 0xaf, 0x8a, 0xed, 0x0f, 0xe3, 0x5e, 0x09, 0xd3, 0x38, - 0x9b, 0x00, 0x15, 0xc6, 0xd9, 0x64, 0xc3, 0x79, 0xa3, 0xc3, 0x09, 0x6b, 0xa5, 0xd5, 0x50, 0x95, 0x93, 0x26, 0x7f, - 0x76, 0xfb, 0xde, 0xbc, 0x9f, 0xc9, 0x07, 0x1f, 0xa8, 0xf2, 0x7d, 0x57, 0xef, 0x92, 0x6d, 0x90, 0x07, 0xfa, 0x03, - 0xe1, 0x2a, 0x21, 0x0d, 0xa4, 0x1f, 0x5c, 0xea, 0xf3, 0x8c, 0xcd, 0x43, 0x7c, 0x2d, 0xfb, 0x12, 0x7a, 0xc5, 0x46, - 0x46, 0x84, 0x61, 0xcf, 0x5c, 0x6c, 0x6e, 0xaa, 0xad, 0x21, 0x6d, 0xac, 0xad, 0xfe, 0x51, 0xac, 0x32, 0x8c, 0x49, - 0xc6, 0xfd, 0xde, 0x83, 0xf2, 0xeb, 0x8c, 0xbb, 0x36, 0x01, 0xbe, 0x5a, 0x3e, 0x10, 0x34, 0xfd, 0x67, 0xf2, 0x00, - 0xbe, 0x5b, 0xfe, 0x60, 0x08, 0x9f, 0xcc, 0x0e, 0x95, 0x28, 0x78, 0x50, 0x7d, 0xbe, 0x1c, 0xf8, 0x60, 0xe3, 0x66, - 0x96, 0xe2, 0xfb, 0x8a, 0x6f, 0x23, 0xaa, 0x3b, 0x8f, 0x2a, 0x51, 0xdd, 0x79, 0xe4, 0x4a, 0xcf, 0xb6, 0xd7, 0xee, - 0x84, 0x8f, 0x1c, 0x01, 0x70, 0xd5, 0x84, 0xff, 0x6b, 0x22, 0xe0, 0x61, 0xf8, 0xa8, 0x94, 0x01, 0xaf, 0xda, 0x9d, - 0xf0, 0x48, 0x8b, 0x9b, 0x4e, 0xf8, 0xe8, 0x07, 0xc5, 0xa0, 0x35, 0x73, 0xae, 0x1f, 0x88, 0x2d, 0xa1, 0x1a, 0x9d, - 0x54, 0xe7, 0xe3, 0xa0, 0xfc, 0x06, 0x9c, 0x39, 0x9f, 0xc6, 0x25, 0xf4, 0x3c, 0x16, 0xf0, 0x21, 0x8e, 0xfa, 0xd9, - 0xad, 0xd5, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x05, 0x9c, 0x70, 0x1f, 0xbb, 0x37, 0x83, 0xe1, 0x5a, 0xad, 0x7a, 0x6d, - 0xb1, 0x7d, 0x7b, 0xdb, 0x6e, 0xd2, 0xd6, 0x0d, 0xed, 0x1b, 0xe2, 0x14, 0xb3, 0x60, 0xea, 0x15, 0xf1, 0x6a, 0x92, - 0x2f, 0x93, 0x62, 0x7d, 0x7e, 0xc8, 0xed, 0x13, 0xdc, 0xb9, 0x1c, 0x4d, 0xab, 0x04, 0xf4, 0x84, 0xc1, 0x75, 0xf6, - 0xa2, 0xb0, 0xa0, 0xd7, 0x9c, 0x81, 0x15, 0x96, 0x14, 0xbf, 0xa0, 0x79, 0xdf, 0x87, 0x22, 0x3f, 0xf2, 0x95, 0x23, - 0xc9, 0x2f, 0x3f, 0x46, 0x52, 0x12, 0x76, 0x55, 0x80, 0xd5, 0x25, 0x12, 0x38, 0xb5, 0x80, 0x1f, 0x1f, 0x1d, 0x1c, - 0xec, 0x3c, 0x2f, 0x4a, 0x1b, 0x83, 0xb5, 0x56, 0x1f, 0x31, 0x70, 0x59, 0x91, 0xef, 0x22, 0xba, 0x1c, 0x57, 0xa1, - 0x10, 0x19, 0x3c, 0x5d, 0xd2, 0x58, 0x86, 0x71, 0xa6, 0x53, 0x14, 0x1c, 0x86, 0x85, 0xdb, 0xf4, 0x08, 0x15, 0x5c, - 0xc6, 0xce, 0x57, 0x4a, 0xcd, 0x39, 0xe7, 0x32, 0xb6, 0x57, 0xfd, 0x32, 0x59, 0xcb, 0x85, 0x9f, 0x76, 0x7a, 0x6f, - 0xdf, 0x9f, 0x78, 0xfa, 0x78, 0x1e, 0x1f, 0x4e, 0x3b, 0xbd, 0x63, 0x65, 0x99, 0xeb, 0x8b, 0x42, 0x44, 0x5f, 0x14, - 0xf2, 0xcc, 0xa5, 0x31, 0x88, 0xd7, 0x14, 0x87, 0x7a, 0xd9, 0xbe, 0x47, 0xb3, 0x91, 0xf6, 0x29, 0xce, 0x16, 0xa9, - 0x64, 0xf0, 0x0a, 0xde, 0x43, 0xe8, 0xda, 0x84, 0x0d, 0x2b, 0x13, 0x4d, 0xad, 0x86, 0x23, 0x33, 0xeb, 0x81, 0x1c, - 0xb3, 0x94, 0xda, 0xd4, 0x52, 0x33, 0x54, 0x99, 0xf9, 0xbc, 0xd9, 0x3a, 0x5f, 0x5c, 0xce, 0x98, 0xf4, 0x6d, 0x7e, - 0xf6, 0x07, 0xd3, 0xe1, 0x58, 0x4d, 0xd5, 0xbb, 0x28, 0x8c, 0x8b, 0xd4, 0x7e, 0x6e, 0x64, 0xed, 0x03, 0xef, 0x7a, - 0xf5, 0x46, 0x42, 0xc0, 0x8d, 0x9f, 0xe9, 0x51, 0xaf, 0x74, 0x4a, 0xba, 0x75, 0xc5, 0xf1, 0xe1, 0xf4, 0xa8, 0x77, - 0x11, 0xcd, 0xcd, 0x78, 0xaf, 0xf8, 0xc6, 0xc7, 0xe2, 0x4b, 0x8e, 0xd9, 0x57, 0xa9, 0xed, 0xfa, 0x0e, 0xa5, 0x01, - 0x78, 0xc4, 0x53, 0xbf, 0x77, 0x6c, 0x94, 0x01, 0x4f, 0x05, 0x5d, 0xfd, 0x47, 0x2d, 0x9b, 0x2d, 0x9f, 0x72, 0xa5, - 0x2d, 0xe9, 0x2e, 0xce, 0x24, 0x35, 0xbf, 0xee, 0xb4, 0xdd, 0x3b, 0x8e, 0x8d, 0x9a, 0x09, 0xcc, 0x23, 0x8f, 0x0e, - 0xa1, 0x33, 0xe8, 0x72, 0x21, 0xe3, 0x87, 0xd7, 0xf4, 0xb2, 0x19, 0xcf, 0x59, 0xe5, 0x44, 0x05, 0xa5, 0xa3, 0x9c, - 0x92, 0x57, 0x33, 0xc1, 0xcf, 0x78, 0x6d, 0x91, 0x8a, 0x85, 0x17, 0xc6, 0x43, 0xab, 0x74, 0x75, 0x1a, 0x4b, 0xdf, - 0xd3, 0x1c, 0xde, 0x7a, 0x72, 0x8d, 0xec, 0x2d, 0xfc, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, 0xb3, 0xc7, 0x87, - 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x30, 0xab, 0xa2, 0x89, 0xf4, 0xa6, 0x39, 0x11, 0x2c, 0x69, - 0x4e, 0xe3, 0x74, 0xec, 0xf7, 0x76, 0x23, 0xc8, 0xbd, 0x59, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, 0xfe, 0xa6, 0xbb, - 0x11, 0x36, 0xc5, 0x5e, 0x9d, 0x56, 0xf7, 0xa6, 0x44, 0x75, 0xa0, 0x6a, 0xb7, 0x25, 0x84, 0xf9, 0x2a, 0x91, 0x61, - 0x6a, 0xa2, 0x76, 0x49, 0xa2, 0xf0, 0xbd, 0x32, 0x1a, 0xf2, 0x7f, 0xff, 0xe7, 0x7f, 0xf9, 0x6f, 0xf6, 0x11, 0x82, - 0x1c, 0xff, 0xf6, 0xdf, 0xff, 0xf3, 0xff, 0xf9, 0xdf, 0xff, 0x15, 0x12, 0xeb, 0x4d, 0x20, 0x44, 0xf1, 0x09, 0xaf, - 0x8a, 0x82, 0x68, 0x86, 0xe1, 0x41, 0x32, 0xda, 0x8c, 0xe5, 0x92, 0x8d, 0xea, 0xd7, 0x26, 0xce, 0xd4, 0x84, 0xea, - 0xb0, 0x19, 0xe8, 0xd4, 0xa1, 0x2d, 0x2a, 0x1a, 0xa9, 0xa1, 0x5c, 0xd1, 0x62, 0x71, 0x7c, 0x08, 0xf8, 0xbe, 0xdf, - 0x4d, 0xb3, 0xb0, 0xdc, 0x8e, 0xa5, 0x75, 0xfd, 0x41, 0x49, 0x51, 0x95, 0x7b, 0xe0, 0x94, 0x5f, 0xc2, 0x63, 0xd4, - 0x71, 0x8a, 0xd5, 0xee, 0xd5, 0xfa, 0x74, 0x7f, 0x5a, 0xe4, 0x92, 0x8d, 0x01, 0xe5, 0xda, 0xc1, 0xa8, 0xe2, 0x9f, - 0x4d, 0x50, 0xff, 0xd2, 0xdb, 0x42, 0x8d, 0xa2, 0x6d, 0xc6, 0x87, 0x4f, 0xff, 0x54, 0xfc, 0x65, 0x06, 0x4a, 0x96, - 0x17, 0xcc, 0xe2, 0x1b, 0x63, 0x49, 0x3e, 0x6e, 0xb5, 0xe6, 0x37, 0x68, 0x59, 0xcd, 0x80, 0x77, 0x4d, 0xa6, 0x9c, - 0x92, 0xee, 0x80, 0x2a, 0x70, 0x5a, 0xfa, 0x3f, 0x5b, 0x1e, 0x38, 0x51, 0xbd, 0x56, 0x51, 0xfc, 0x79, 0xa9, 0x5c, - 0x70, 0xec, 0x17, 0x08, 0x70, 0x1a, 0x6f, 0xe5, 0x25, 0x77, 0x17, 0xb7, 0x74, 0x7a, 0x75, 0x74, 0xaf, 0x69, 0x7b, - 0xf3, 0x02, 0x95, 0x1b, 0xa0, 0x75, 0x43, 0xab, 0x0f, 0x21, 0x58, 0x3a, 0x6d, 0xe3, 0x69, 0x67, 0x59, 0x0e, 0x2f, - 0x25, 0x9f, 0xb9, 0x11, 0x59, 0x1a, 0xd3, 0x11, 0x1d, 0x5b, 0x2f, 0xaf, 0xa9, 0xd7, 0xd1, 0xd6, 0x62, 0x7a, 0xb4, - 0x65, 0x2e, 0x03, 0x92, 0x8a, 0xc4, 0x7a, 0xad, 0xe2, 0x33, 0x38, 0x81, 0xcb, 0x71, 0xca, 0x63, 0x19, 0x29, 0x82, - 0xed, 0xba, 0x71, 0xdd, 0x18, 0xd8, 0x0c, 0x5f, 0x3a, 0xf0, 0x74, 0x75, 0x53, 0xf0, 0xb7, 0xd6, 0xaf, 0xb9, 0x15, - 0xa1, 0xea, 0xee, 0x0e, 0xa5, 0xdd, 0x35, 0xdf, 0x9a, 0x70, 0xe9, 0x9b, 0x9a, 0x9f, 0xc3, 0xc8, 0x98, 0x0e, 0xda, - 0x5e, 0xaf, 0x45, 0xb5, 0xae, 0xfd, 0x4a, 0x06, 0xbe, 0x02, 0xd3, 0x5f, 0x6f, 0xa5, 0x0a, 0xa1, 0xd5, 0x1b, 0xf2, - 0x6d, 0x69, 0x05, 0xc5, 0xf3, 0xb9, 0x6a, 0x88, 0xba, 0xc7, 0x87, 0x5a, 0x79, 0x05, 0xee, 0xa1, 0x72, 0x01, 0x74, - 0xe8, 0xdd, 0x34, 0x32, 0x47, 0x41, 0xff, 0x32, 0x41, 0x79, 0xf8, 0x5c, 0x55, 0xef, 0xff, 0x01, 0xb9, 0x37, 0x65, - 0xfc, 0x3f, 0x86, 0x00, 0x00}; + 0xae, 0x27, 0x4f, 0x9e, 0x3c, 0x7b, 0x02, 0xc7, 0x7b, 0xb1, 0x18, 0xc9, 0xdb, 0x39, 0xf3, 0xa6, 0x72, 0x96, 0xf4, + 0x8e, 0xcd, 0xbf, 0x2c, 0x8a, 0x7b, 0xc7, 0x09, 0x4f, 0x3f, 0x7a, 0x19, 0x4b, 0x28, 0x1f, 0x89, 0xd4, 0x9b, 0x66, + 0x6c, 0x4c, 0xe3, 0x48, 0x46, 0x21, 0x9f, 0x45, 0x13, 0xe6, 0x1d, 0xf6, 0x8e, 0x67, 0x4c, 0x46, 0xde, 0x68, 0x1a, + 0x65, 0x39, 0x93, 0xf4, 0xc3, 0xfb, 0x2f, 0x9a, 0x4f, 0x7b, 0xc7, 0xf9, 0x28, 0xe3, 0x73, 0xe9, 0xc1, 0x90, 0x74, + 0x26, 0xe2, 0x45, 0xc2, 0x7a, 0x87, 0x87, 0xd7, 0xd7, 0xd7, 0xc1, 0x4f, 0xf9, 0x3f, 0x8d, 0x44, 0x9a, 0x4b, 0xef, + 0x15, 0xbd, 0xe6, 0x69, 0x2c, 0xae, 0x09, 0x93, 0xf4, 0x55, 0x70, 0x36, 0x8d, 0x62, 0x71, 0xfd, 0x4e, 0x08, 0x79, + 0x70, 0xe0, 0xeb, 0xc7, 0xdb, 0xd3, 0xb3, 0x33, 0x4a, 0xe9, 0x95, 0xe0, 0xb1, 0xd7, 0x5a, 0xad, 0xaa, 0xc2, 0x20, + 0x8d, 0x24, 0xbf, 0x62, 0xba, 0x0b, 0x3e, 0x38, 0x40, 0x51, 0x2c, 0xe6, 0x92, 0xc5, 0x67, 0xf2, 0x36, 0x61, 0x67, + 0x53, 0xc6, 0x64, 0x8e, 0x78, 0xea, 0x3d, 0x17, 0xa3, 0xc5, 0x8c, 0xa5, 0x32, 0x98, 0x67, 0x42, 0x0a, 0x80, 0xe4, + 0xe0, 0x00, 0x65, 0x6c, 0x9e, 0x44, 0x23, 0x06, 0xf5, 0xa7, 0x67, 0x67, 0x55, 0x8f, 0xaa, 0x11, 0xe1, 0x92, 0x9e, + 0xdd, 0xce, 0x2e, 0x45, 0xe2, 0x63, 0x92, 0x48, 0x9a, 0xb2, 0x6b, 0xef, 0x3b, 0x16, 0x7d, 0x7c, 0x1d, 0xcd, 0xbb, + 0xa3, 0x24, 0xca, 0x73, 0xef, 0x52, 0x2e, 0xd5, 0x12, 0xb2, 0xc5, 0x48, 0x8a, 0xcc, 0x97, 0x84, 0x11, 0x8e, 0x97, + 0x7c, 0xec, 0xcb, 0x29, 0xcf, 0x83, 0xf3, 0xfd, 0x51, 0x9e, 0xbf, 0x63, 0xf9, 0x22, 0x91, 0xfb, 0x74, 0xaf, 0x45, + 0xf8, 0x1e, 0xa5, 0x5c, 0x62, 0x39, 0xcd, 0xc4, 0xb5, 0xf7, 0x22, 0xcb, 0x44, 0xe6, 0xa3, 0xd3, 0xb3, 0x33, 0xdd, + 0xc2, 0xe3, 0xb9, 0x97, 0x0a, 0xe9, 0x95, 0xe3, 0x45, 0x97, 0x09, 0x0b, 0xbc, 0x0f, 0x39, 0xf3, 0x2e, 0x16, 0x69, + 0x1e, 0x8d, 0xd9, 0xe9, 0xd9, 0xd9, 0x85, 0x27, 0x32, 0xef, 0x62, 0x94, 0xe7, 0x17, 0x1e, 0x4f, 0x73, 0xc9, 0xa2, + 0x38, 0x40, 0xb8, 0xab, 0x26, 0x1b, 0xe5, 0xf9, 0x7b, 0x76, 0x23, 0xa9, 0x24, 0xea, 0x51, 0x52, 0x56, 0x4c, 0x98, + 0xf4, 0xf2, 0x72, 0x5d, 0x3e, 0x5e, 0x26, 0x4c, 0x7a, 0x92, 0xaa, 0x7a, 0xd1, 0xd5, 0xb8, 0x67, 0xfa, 0x51, 0x76, + 0xf9, 0xd8, 0x67, 0xf2, 0xe0, 0x40, 0x96, 0x78, 0xc6, 0x7a, 0x69, 0x1e, 0xa7, 0x6c, 0xcf, 0x96, 0x1d, 0x1c, 0xb0, + 0x20, 0x61, 0xe9, 0x44, 0x4e, 0x29, 0xa5, 0xed, 0x2e, 0x3f, 0x38, 0xf0, 0x25, 0x4d, 0x64, 0x30, 0x61, 0xd2, 0x67, + 0x18, 0x93, 0xaa, 0xf7, 0xc1, 0x81, 0xaf, 0x91, 0x20, 0xa8, 0x46, 0x5c, 0x0d, 0xc7, 0x38, 0x30, 0xd8, 0x3f, 0xbb, + 0x4d, 0x47, 0xbe, 0x0b, 0x3f, 0x26, 0xfc, 0xe0, 0x20, 0x91, 0x41, 0x0e, 0x23, 0x12, 0x89, 0x71, 0x91, 0x31, 0xb9, + 0xc8, 0x52, 0x4f, 0x16, 0x52, 0x9c, 0xc9, 0x8c, 0xa7, 0x13, 0x1f, 0x2f, 0x6d, 0x99, 0xd3, 0xb1, 0x28, 0x34, 0xb8, + 0x5f, 0x4b, 0x9a, 0xd1, 0x1e, 0xcc, 0x78, 0x29, 0x7d, 0xd8, 0x45, 0x31, 0xf6, 0x32, 0x4a, 0x51, 0xae, 0xfa, 0xa2, + 0x7e, 0x16, 0x66, 0x0d, 0x84, 0x88, 0x86, 0x92, 0x70, 0x89, 0xc9, 0x47, 0xea, 0x67, 0x24, 0x08, 0x02, 0x89, 0x69, + 0x6f, 0x69, 0xb1, 0x92, 0x39, 0xeb, 0xec, 0x67, 0x83, 0xd6, 0x30, 0x94, 0x41, 0xc6, 0xe2, 0xc5, 0x88, 0xf9, 0x3e, + 0x27, 0x39, 0x49, 0x31, 0xed, 0xf1, 0x86, 0x2f, 0x68, 0x0f, 0xb6, 0x5b, 0xd4, 0xf7, 0x9a, 0xd2, 0xbd, 0x16, 0x36, + 0x30, 0x0a, 0x0b, 0x20, 0x60, 0xd8, 0xc0, 0x23, 0x28, 0x45, 0xe9, 0x62, 0x76, 0xc9, 0x32, 0x54, 0x36, 0xeb, 0xd6, + 0xc8, 0x62, 0x91, 0x33, 0x6f, 0x94, 0xe7, 0xde, 0x78, 0x91, 0x8e, 0x24, 0x17, 0xa9, 0x87, 0x1a, 0xa2, 0x81, 0x34, + 0x39, 0x94, 0xd4, 0x80, 0x70, 0x81, 0xfd, 0x1c, 0x37, 0xb2, 0x41, 0xda, 0x68, 0x0f, 0x09, 0x40, 0x89, 0xbb, 0x66, + 0x3c, 0x83, 0x00, 0x46, 0x32, 0x58, 0x63, 0x41, 0x3e, 0x48, 0x58, 0xa5, 0x5a, 0x22, 0x93, 0xfd, 0x2c, 0xd8, 0x3c, + 0x28, 0x54, 0x06, 0xb3, 0x68, 0xee, 0x33, 0xda, 0x63, 0x8a, 0xb8, 0xa2, 0x74, 0x04, 0xb0, 0xd6, 0xf6, 0xad, 0xcf, + 0x42, 0x16, 0x54, 0x24, 0x85, 0x43, 0x19, 0x8c, 0x45, 0xf6, 0x22, 0x1a, 0x4d, 0xa1, 0x5f, 0x49, 0x30, 0xb1, 0x3d, + 0x6f, 0xa3, 0x8c, 0x45, 0x92, 0xbd, 0x48, 0x18, 0x3c, 0xf9, 0x48, 0xf5, 0x44, 0x98, 0xe4, 0xf4, 0x55, 0x90, 0x70, + 0xf9, 0x46, 0xa4, 0x23, 0xd6, 0xcd, 0x1d, 0xea, 0xe2, 0xb0, 0xef, 0x27, 0x52, 0x66, 0xfc, 0x72, 0x21, 0x99, 0x8f, + 0x52, 0x68, 0x81, 0x48, 0x8e, 0x09, 0x0f, 0x24, 0xbb, 0x91, 0xa7, 0x22, 0x95, 0x2c, 0x95, 0x94, 0x59, 0xa4, 0x92, + 0x2c, 0x88, 0xe6, 0x73, 0x96, 0xc6, 0xa7, 0x53, 0x9e, 0xc4, 0x3e, 0xc7, 0x05, 0x2e, 0x48, 0x24, 0x29, 0xac, 0x91, + 0xf6, 0xb2, 0x10, 0xfe, 0xd9, 0xbd, 0x1a, 0x5f, 0xd2, 0x9e, 0x3a, 0x14, 0x8c, 0x22, 0xd4, 0x1d, 0x8b, 0xcc, 0x37, + 0x2b, 0xf0, 0xc4, 0xd8, 0x93, 0x30, 0xc7, 0xbb, 0x45, 0xc2, 0x72, 0xcc, 0x1a, 0x94, 0x97, 0xdb, 0x68, 0x10, 0xfc, + 0x35, 0x50, 0x7c, 0x81, 0xfd, 0x0c, 0x87, 0x59, 0xf7, 0x2a, 0xca, 0xbc, 0x2f, 0xcc, 0x89, 0xfa, 0xc9, 0x72, 0xb3, + 0xa9, 0xa4, 0x3f, 0x05, 0x32, 0x5b, 0xe4, 0x92, 0xc5, 0xef, 0x6f, 0xe7, 0x2c, 0x27, 0xef, 0x25, 0x9d, 0xca, 0xfe, + 0x54, 0x06, 0x6c, 0x36, 0x97, 0xb7, 0x67, 0x8a, 0x31, 0x86, 0x08, 0x91, 0x11, 0xb4, 0xcc, 0x58, 0x34, 0x02, 0x66, + 0x66, 0xb0, 0xf5, 0xb5, 0x48, 0x6e, 0xc7, 0x3c, 0x49, 0xce, 0x16, 0xf3, 0xb9, 0xc8, 0x24, 0xf9, 0x2b, 0x5d, 0x4a, + 0x51, 0xa1, 0x06, 0xf6, 0x72, 0x99, 0x5f, 0x73, 0x39, 0x9a, 0xfa, 0x12, 0x2f, 0x47, 0x51, 0xce, 0xbc, 0x67, 0x42, + 0x24, 0x2c, 0x4a, 0xc3, 0x8c, 0x66, 0xfd, 0xf7, 0x32, 0x4c, 0x17, 0x49, 0xd2, 0xbd, 0xcc, 0x58, 0xf4, 0xb1, 0xab, + 0xaa, 0xdf, 0x5e, 0xfe, 0xc4, 0x46, 0x32, 0x54, 0xbf, 0x4f, 0xb2, 0x2c, 0xba, 0x85, 0x86, 0x94, 0x42, 0xb3, 0x7e, + 0x16, 0x7e, 0x75, 0xf6, 0xf6, 0x4d, 0xa0, 0x0f, 0x09, 0x1f, 0xdf, 0xfa, 0x59, 0x79, 0xf0, 0xb2, 0x82, 0x8c, 0x33, + 0x31, 0x5b, 0x9b, 0x5a, 0x63, 0x2d, 0xeb, 0xee, 0x00, 0x81, 0xd1, 0x6c, 0x4f, 0x0f, 0xed, 0x42, 0xf0, 0x46, 0xd1, + 0x3c, 0x54, 0x52, 0x33, 0x2f, 0xfc, 0x13, 0xea, 0x62, 0x3f, 0xc3, 0x77, 0x43, 0x2b, 0xb3, 0xdb, 0x25, 0xa3, 0x0a, + 0xce, 0x39, 0x48, 0x18, 0x80, 0x71, 0x14, 0xc9, 0xd1, 0x74, 0xc9, 0xd4, 0x60, 0x85, 0x85, 0x98, 0x15, 0x05, 0xb9, + 0x2e, 0xe9, 0x5d, 0xee, 0x51, 0x9a, 0x29, 0x46, 0x45, 0xe5, 0x6a, 0x95, 0x51, 0x9a, 0x61, 0xf2, 0x1d, 0x5d, 0x46, + 0x76, 0x3d, 0xe1, 0x5e, 0x8b, 0xc0, 0xb9, 0x0c, 0x35, 0x77, 0x21, 0x23, 0x91, 0x5e, 0xb1, 0x4c, 0xb2, 0x2c, 0xfc, + 0x2b, 0xc9, 0xd8, 0x38, 0x01, 0x28, 0xf6, 0xda, 0x64, 0x1a, 0xe5, 0xa7, 0xd3, 0x28, 0x9d, 0xb0, 0x38, 0xbc, 0x96, + 0x05, 0xf9, 0x3b, 0x45, 0x63, 0x9e, 0x46, 0x09, 0xff, 0x85, 0xc5, 0xc8, 0x48, 0x83, 0x13, 0x8f, 0xdd, 0x48, 0x96, + 0xc6, 0xb9, 0xf7, 0xf2, 0xfd, 0xeb, 0x57, 0x66, 0x1f, 0x6b, 0x02, 0x02, 0x2f, 0xf3, 0xc5, 0x9c, 0x65, 0x3e, 0x26, + 0x46, 0x40, 0xbc, 0xe0, 0x8a, 0x39, 0xbe, 0x8e, 0xe6, 0xba, 0x84, 0xe7, 0x1f, 0xe6, 0x71, 0x24, 0xd9, 0xd7, 0x2c, + 0x8d, 0x79, 0x3a, 0xa1, 0x7b, 0x6d, 0x5d, 0x3e, 0x8d, 0x4c, 0x45, 0x5c, 0x16, 0x9d, 0xef, 0xbf, 0x48, 0xd4, 0xba, + 0xcb, 0xc7, 0x85, 0x8f, 0x8b, 0x5c, 0x46, 0x92, 0x8f, 0xbc, 0x28, 0x8e, 0xbf, 0x4c, 0xb9, 0xe4, 0x0a, 0xc0, 0x0c, + 0xb6, 0x07, 0x48, 0x94, 0x69, 0x51, 0x61, 0x01, 0xf7, 0x31, 0xf1, 0x7d, 0x23, 0x00, 0xa6, 0xd8, 0xec, 0xd7, 0xc1, + 0x41, 0xc5, 0xee, 0xfb, 0x2c, 0xd4, 0x95, 0x74, 0x30, 0xc4, 0xc1, 0x7c, 0x91, 0xc3, 0x46, 0xdb, 0x29, 0x40, 0xba, + 0x88, 0xcb, 0x9c, 0x65, 0x57, 0x2c, 0x2e, 0x89, 0x23, 0xf7, 0xf1, 0x72, 0x6d, 0x0e, 0x73, 0x2c, 0x24, 0x1d, 0x0c, + 0xbb, 0x2e, 0xdf, 0x66, 0x86, 0xce, 0x33, 0x31, 0x67, 0x99, 0xe4, 0x2c, 0x2f, 0x59, 0x89, 0x0f, 0x52, 0xb4, 0x64, + 0x27, 0x39, 0xb5, 0xeb, 0x9b, 0xfb, 0x9c, 0x30, 0x5c, 0x63, 0x18, 0x56, 0xd0, 0xbe, 0xb8, 0x52, 0x12, 0x23, 0x27, + 0x1c, 0x13, 0xa9, 0x21, 0xcd, 0x31, 0x2e, 0x30, 0x91, 0x16, 0x5c, 0xcd, 0x8a, 0xcc, 0x6c, 0xb7, 0x20, 0xaa, 0xe9, + 0x77, 0x4a, 0x54, 0x03, 0x43, 0x8b, 0x24, 0x3b, 0x38, 0xf0, 0x59, 0x50, 0x12, 0x05, 0xdd, 0x6b, 0x9b, 0x3d, 0x72, + 0x90, 0xb5, 0x03, 0x6c, 0x98, 0x58, 0x12, 0x86, 0xc9, 0x1e, 0x0b, 0x52, 0x71, 0x32, 0x1a, 0xb1, 0x3c, 0x17, 0xd9, + 0xc1, 0xc1, 0x9e, 0x6a, 0x5f, 0x6a, 0x13, 0xb0, 0x87, 0x6f, 0xaf, 0xd3, 0x0a, 0x02, 0x5c, 0x49, 0x58, 0x23, 0x17, + 0x24, 0xc8, 0x29, 0xa5, 0x70, 0xa0, 0xbe, 0x55, 0x3c, 0x42, 0x74, 0x7e, 0x8e, 0x1a, 0x92, 0x18, 0x34, 0x4c, 0x98, + 0x9d, 0xfa, 0xf6, 0x39, 0xd3, 0xaa, 0x95, 0x52, 0x3c, 0x36, 0x30, 0xa3, 0xcf, 0x4f, 0x10, 0xb3, 0x31, 0x4f, 0x9d, + 0x65, 0xd7, 0x40, 0x22, 0x92, 0xe4, 0xb8, 0x70, 0x36, 0x74, 0xeb, 0xd0, 0x4a, 0xa7, 0xd1, 0x3b, 0xb7, 0x9c, 0x28, + 0x3d, 0xc2, 0xd9, 0xc6, 0x01, 0x1b, 0x16, 0x44, 0xa1, 0xde, 0xae, 0x26, 0x55, 0x80, 0x0e, 0xe4, 0xb0, 0x6b, 0xea, + 0x69, 0xae, 0x31, 0x97, 0xb1, 0x9f, 0x17, 0x2c, 0x97, 0x9a, 0x8e, 0x7d, 0x49, 0x52, 0xc2, 0x71, 0x01, 0xc7, 0x6d, + 0xcc, 0x27, 0x8b, 0x0c, 0xd4, 0x1d, 0x38, 0x8a, 0x2c, 0x5d, 0xcc, 0x98, 0x7d, 0xda, 0x06, 0xdb, 0xdb, 0x39, 0x08, + 0xc4, 0x1c, 0x68, 0xfa, 0x6e, 0x72, 0x02, 0x58, 0x25, 0x5e, 0xad, 0xbe, 0xb3, 0x83, 0x54, 0x5b, 0x59, 0xaa, 0x68, + 0x6b, 0x7b, 0xf2, 0x77, 0x6c, 0xe4, 0xf1, 0x5e, 0x5b, 0x43, 0xff, 0xf7, 0x21, 0xdd, 0x6b, 0x95, 0x14, 0x6c, 0x70, + 0xaa, 0x81, 0xd1, 0x28, 0x7c, 0xab, 0x07, 0xc2, 0x4a, 0xba, 0xd7, 0x88, 0x25, 0x98, 0x6e, 0xd0, 0xe9, 0x94, 0x0e, + 0x40, 0xcf, 0x08, 0xa6, 0xc3, 0x5d, 0xc4, 0x64, 0xb9, 0x81, 0x2f, 0x37, 0xeb, 0x2a, 0xa6, 0x71, 0x55, 0x67, 0x1a, + 0x6b, 0x8b, 0x40, 0xf3, 0xb2, 0x0b, 0x2a, 0x69, 0xcc, 0x1c, 0xf3, 0xaa, 0x8a, 0x70, 0x05, 0x4c, 0xb5, 0x24, 0x67, + 0x88, 0x37, 0xd1, 0x8c, 0xe5, 0x3e, 0xc3, 0x64, 0x57, 0x03, 0x4d, 0x9c, 0xd0, 0x64, 0xe8, 0x88, 0xcd, 0x1c, 0xc4, + 0x26, 0xc7, 0x5a, 0x2b, 0xab, 0x1f, 0xb7, 0x9c, 0xb0, 0x41, 0x3e, 0xac, 0x94, 0x39, 0x67, 0xf1, 0x4a, 0x1e, 0x1b, + 0xea, 0xb6, 0xf8, 0xd3, 0x65, 0x1a, 0x69, 0x4a, 0x69, 0xc8, 0x31, 0xd9, 0x6b, 0xad, 0xef, 0xa3, 0x6d, 0x55, 0xad, + 0x71, 0x30, 0x84, 0x7d, 0x50, 0xe2, 0x22, 0xe0, 0xb9, 0xfa, 0xbf, 0x76, 0xce, 0x00, 0x6d, 0x67, 0x40, 0x16, 0xc1, + 0x38, 0x89, 0xa4, 0xdf, 0x3e, 0x6c, 0x81, 0x26, 0x7a, 0xc5, 0x40, 0x9a, 0x60, 0xbc, 0xb9, 0x14, 0x16, 0x2c, 0xd2, + 0x7c, 0xca, 0xc7, 0xd2, 0x8f, 0xa4, 0x62, 0x28, 0x2c, 0xc9, 0x99, 0x27, 0x6b, 0xfa, 0xb0, 0x62, 0x36, 0x11, 0x90, + 0x5a, 0xa9, 0x7c, 0x31, 0x0b, 0xa9, 0x62, 0x5a, 0xc0, 0x1b, 0x2a, 0x5d, 0xba, 0xe2, 0x31, 0xb6, 0x35, 0x07, 0x7d, + 0xb1, 0xdd, 0xd7, 0x23, 0x86, 0x86, 0x15, 0x70, 0x47, 0x65, 0xe5, 0xa1, 0xcb, 0x1f, 0x4c, 0xa1, 0x0c, 0xa4, 0x78, + 0x25, 0xae, 0x59, 0x76, 0x1a, 0x01, 0xf0, 0xa1, 0xee, 0x5e, 0x68, 0x31, 0xa0, 0xb8, 0xbd, 0xec, 0x5a, 0x7a, 0x39, + 0x57, 0x0b, 0xff, 0x3a, 0x13, 0x33, 0x9e, 0x33, 0xd0, 0xd4, 0x34, 0xfe, 0x53, 0x38, 0x65, 0xea, 0x38, 0x82, 0xa8, + 0x61, 0x25, 0x7d, 0x9d, 0xbc, 0xaa, 0xd3, 0xd7, 0xf9, 0xfe, 0x8b, 0x89, 0x65, 0x7f, 0xf5, 0x43, 0x8c, 0x89, 0x6f, + 0xec, 0x09, 0x47, 0xca, 0x05, 0x53, 0x6c, 0xc4, 0xfb, 0x6a, 0x25, 0x1d, 0xb3, 0xad, 0xa6, 0x2b, 0x32, 0x7d, 0x6c, + 0x70, 0x11, 0xc5, 0x31, 0x68, 0x75, 0x99, 0x48, 0x12, 0x47, 0x50, 0x11, 0xde, 0x2d, 0x45, 0xd3, 0xf9, 0xfe, 0x8b, + 0xb3, 0xbb, 0xa4, 0x13, 0xd4, 0xbb, 0x02, 0xca, 0x02, 0x9a, 0xc6, 0x2c, 0x03, 0x33, 0xd2, 0xd9, 0x2d, 0x23, 0x63, + 0x4f, 0x45, 0x9a, 0xb2, 0x91, 0x64, 0x31, 0x58, 0x29, 0x9c, 0xca, 0x60, 0x2a, 0x72, 0x59, 0x16, 0x56, 0xd0, 0x73, + 0x07, 0x7a, 0x1e, 0x8c, 0xa2, 0x24, 0xf1, 0xb5, 0x45, 0x32, 0x13, 0x57, 0x6c, 0x0b, 0xd4, 0xdd, 0x1a, 0xc8, 0xe5, + 0x30, 0xcc, 0x19, 0x86, 0x05, 0xf9, 0x3c, 0xe1, 0x23, 0x56, 0x0a, 0xae, 0xb3, 0x80, 0xa7, 0x31, 0xbb, 0x01, 0x3e, + 0x82, 0x7b, 0xbd, 0x5e, 0x8b, 0xb4, 0x71, 0xa1, 0x11, 0xbe, 0xdc, 0x40, 0xec, 0x1d, 0x22, 0x13, 0x88, 0x8c, 0xf6, + 0x96, 0xdb, 0xf8, 0x01, 0xc3, 0x8e, 0x9c, 0xe4, 0xd6, 0xb2, 0xd2, 0xbc, 0x19, 0x93, 0x98, 0x25, 0x4c, 0x32, 0xcb, + 0xcb, 0x41, 0x7f, 0xd6, 0x47, 0xf7, 0x5d, 0x89, 0xbf, 0x92, 0x9c, 0xec, 0x29, 0xb3, 0x7b, 0x9e, 0x97, 0x96, 0x7a, + 0xb5, 0x3d, 0x15, 0xb6, 0xfb, 0x52, 0x6f, 0x4f, 0x24, 0x65, 0x34, 0x9a, 0x6a, 0x13, 0xdd, 0xdf, 0x58, 0x52, 0x35, + 0x86, 0xe1, 0xeb, 0xe5, 0x21, 0xfa, 0x60, 0xc1, 0xdc, 0x86, 0x82, 0x33, 0xc3, 0x14, 0x18, 0x58, 0x7d, 0x7a, 0xdb, + 0x4e, 0xa3, 0x24, 0xb9, 0x8c, 0x46, 0x1f, 0xeb, 0xd4, 0x5f, 0x91, 0x01, 0x5d, 0xe7, 0xc6, 0x4e, 0x95, 0xc3, 0xb2, + 0xdc, 0x75, 0x5b, 0x2e, 0x5d, 0x3b, 0x28, 0xfe, 0x5e, 0xab, 0x22, 0xfb, 0xfa, 0x46, 0xef, 0xa4, 0x76, 0x05, 0x11, + 0x37, 0x2b, 0xf3, 0x81, 0x0b, 0x7c, 0x92, 0xe2, 0x2c, 0x3f, 0x30, 0x74, 0x07, 0xb6, 0x46, 0xb1, 0x06, 0x88, 0xc4, + 0xcb, 0x22, 0xe6, 0xf9, 0x6e, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x77, 0x66, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x33, 0x2a, + 0x73, 0x09, 0x99, 0xd1, 0x26, 0x2c, 0xa3, 0xf9, 0x1b, 0x68, 0x2e, 0x8a, 0xde, 0xdf, 0xea, 0x2a, 0xd0, 0xc9, 0x00, + 0x8a, 0xbc, 0xeb, 0x2a, 0x13, 0x35, 0x0a, 0x30, 0x3c, 0x95, 0x2b, 0x91, 0x9b, 0xd6, 0x8c, 0x47, 0xa3, 0xae, 0x6b, + 0xfb, 0xdb, 0xb0, 0x5c, 0x41, 0x7d, 0xdf, 0xcf, 0xc1, 0x7e, 0xb3, 0x7a, 0x7d, 0xb5, 0x88, 0x7c, 0x63, 0x11, 0x79, + 0xe0, 0x18, 0x59, 0xb8, 0xa2, 0x65, 0xa7, 0x7b, 0xf8, 0x57, 0xec, 0x36, 0x02, 0x65, 0x35, 0x00, 0xfe, 0x8c, 0x4b, + 0x76, 0x9b, 0x50, 0x49, 0x84, 0x31, 0x70, 0x0c, 0xa5, 0x01, 0xc3, 0xa8, 0xba, 0xa4, 0x58, 0x1f, 0x8d, 0x9a, 0xb1, + 0x9b, 0x12, 0x81, 0xd7, 0x34, 0xfb, 0xa2, 0x30, 0x38, 0x62, 0xd8, 0xec, 0x4d, 0x4d, 0x25, 0x76, 0xb0, 0x42, 0x52, + 0x6a, 0xd4, 0x60, 0xad, 0xf5, 0xac, 0xe3, 0xa6, 0x1c, 0x17, 0x0e, 0x6a, 0x85, 0x9a, 0x9a, 0x3e, 0x69, 0x15, 0xab, + 0x14, 0x93, 0xa9, 0xd5, 0x48, 0x45, 0xb5, 0x6e, 0x4a, 0x91, 0xf5, 0x46, 0xa0, 0xfe, 0xb2, 0x66, 0x12, 0x86, 0x4e, + 0xb3, 0x22, 0x04, 0x96, 0x2a, 0xb6, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xc6, 0x71, 0x10, 0x2e, 0x5c, 0x84, 0x3b, 0x98, + 0x4d, 0x35, 0xe7, 0x4a, 0x87, 0x74, 0x5a, 0xef, 0xeb, 0x33, 0x22, 0xf4, 0x3e, 0x6c, 0x20, 0x71, 0x5d, 0xf1, 0x54, + 0x24, 0x08, 0x06, 0x6c, 0x0e, 0xca, 0x9d, 0x2b, 0x1f, 0x7c, 0x80, 0x9d, 0xaf, 0x56, 0x1b, 0x44, 0xb7, 0x55, 0xff, + 0xc4, 0x41, 0x65, 0x14, 0xae, 0x56, 0xd7, 0x12, 0xfb, 0x46, 0xf3, 0x25, 0x0c, 0xf7, 0x2d, 0xc7, 0x3d, 0x79, 0x05, + 0xad, 0x94, 0x22, 0x5a, 0x95, 0x94, 0x26, 0x43, 0x9d, 0x66, 0xeb, 0xfb, 0x24, 0x1d, 0xb6, 0x7d, 0xba, 0xc1, 0xbd, + 0x54, 0xa1, 0x11, 0xd3, 0xd5, 0x92, 0x4f, 0xcd, 0xd0, 0x1c, 0x63, 0x1c, 0xe6, 0xca, 0x8a, 0xd9, 0xdb, 0x66, 0x58, + 0x1e, 0x1c, 0xe4, 0xce, 0x40, 0xe7, 0x25, 0x9b, 0xf8, 0xc9, 0x07, 0x91, 0x9c, 0xdf, 0xa6, 0x4a, 0x77, 0xf9, 0xc9, + 0x0a, 0xa1, 0x0d, 0xb3, 0xb4, 0xd5, 0x05, 0x6b, 0x3c, 0xba, 0x8e, 0xb8, 0xf4, 0xca, 0x51, 0xb4, 0x35, 0xee, 0x33, + 0xbc, 0x34, 0xaa, 0x46, 0x90, 0x31, 0x50, 0x1e, 0x81, 0x27, 0x58, 0x15, 0x5a, 0xd3, 0xfd, 0x68, 0xca, 0xc0, 0x11, + 0x6c, 0xb5, 0x88, 0xd2, 0x2e, 0xdc, 0x33, 0x52, 0xc4, 0x0c, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, 0x7b, 0xcd, 0x0e, 0x98, + 0xb3, 0x6c, 0x2c, 0xb2, 0x99, 0xad, 0x2b, 0xd6, 0x9e, 0x0d, 0x67, 0xe4, 0x63, 0x7f, 0xeb, 0xd8, 0x46, 0xfd, 0xef, + 0xae, 0x19, 0xdd, 0x95, 0xb9, 0x5e, 0x13, 0xa5, 0xa5, 0xf4, 0xd5, 0xfe, 0x40, 0x4b, 0x99, 0xb9, 0x6b, 0xde, 0x1b, + 0x67, 0x6a, 0x57, 0x3b, 0x4c, 0xf6, 0xda, 0xdd, 0xd2, 0xe6, 0xb3, 0xd4, 0xd0, 0xd5, 0x8e, 0x0d, 0x23, 0x52, 0xc5, + 0x22, 0x89, 0x0d, 0xb0, 0x1c, 0x13, 0x66, 0xe8, 0xe8, 0x9a, 0x27, 0x49, 0x55, 0xfa, 0x6b, 0xf8, 0x7a, 0x6e, 0xf8, + 0x7a, 0x6a, 0xf9, 0x3a, 0x70, 0x0a, 0xe0, 0xeb, 0x7a, 0xb8, 0xaa, 0x7b, 0xba, 0x71, 0x3a, 0x53, 0xcd, 0xd1, 0x73, + 0x65, 0x47, 0xc3, 0x7c, 0x0b, 0x0b, 0x01, 0x2e, 0x35, 0xaf, 0x8f, 0xbe, 0x71, 0xc2, 0x80, 0x01, 0xa8, 0x5d, 0x98, + 0xcc, 0x75, 0x51, 0x7c, 0xf4, 0x31, 0xc9, 0x0b, 0x56, 0x52, 0xf6, 0xc9, 0x0b, 0x70, 0xd2, 0x39, 0xcb, 0x01, 0x21, + 0xa6, 0x8a, 0x7f, 0x95, 0x12, 0x65, 0x57, 0xc7, 0xcd, 0xea, 0x72, 0xbb, 0x3a, 0xe0, 0xf4, 0xd5, 0xea, 0xe2, 0xbb, + 0x79, 0xbd, 0x5a, 0x1e, 0x2f, 0x97, 0x57, 0xed, 0xf7, 0x6a, 0xe5, 0xaf, 0x95, 0x80, 0xff, 0xde, 0x98, 0x28, 0x59, + 0x39, 0x3a, 0xf0, 0x00, 0x17, 0x33, 0x50, 0x50, 0xe8, 0x45, 0x97, 0x22, 0xee, 0xd5, 0xa7, 0x1c, 0x3c, 0xca, 0x4d, + 0xaf, 0xfb, 0x9f, 0x8a, 0xd9, 0x1c, 0xb4, 0xb1, 0x35, 0x92, 0x9e, 0x30, 0x33, 0x61, 0x55, 0x5f, 0x6c, 0x29, 0xab, + 0xf5, 0x51, 0xe7, 0xb1, 0x46, 0x4d, 0xa5, 0xbd, 0xbc, 0xd7, 0x2a, 0x16, 0x65, 0x51, 0xc9, 0x38, 0xb6, 0x39, 0x55, + 0x4e, 0xd7, 0x5d, 0x32, 0xb6, 0xe2, 0xad, 0xcf, 0x35, 0x1f, 0xe6, 0xc0, 0xeb, 0x1c, 0xf6, 0x63, 0xc9, 0xdd, 0xdd, + 0xff, 0xa2, 0x42, 0xce, 0xb2, 0x58, 0x43, 0xdf, 0xb2, 0x28, 0x4e, 0xb4, 0x91, 0x4d, 0x4e, 0x76, 0x5b, 0xc3, 0x55, + 0x9d, 0x31, 0x16, 0x07, 0x43, 0x72, 0xb2, 0xa9, 0x3a, 0xd2, 0xe5, 0x4c, 0xc4, 0x2c, 0x44, 0x62, 0xce, 0x52, 0x54, + 0x80, 0x57, 0xd5, 0xec, 0xfd, 0x48, 0xfa, 0xcb, 0x77, 0x75, 0xf7, 0x6a, 0x78, 0x52, 0x80, 0xf7, 0xeb, 0x8b, 0x4d, + 0xc7, 0xeb, 0xb7, 0x2c, 0xcb, 0x95, 0x22, 0x5a, 0xea, 0xb4, 0x5f, 0x54, 0x62, 0xe9, 0x8b, 0x70, 0x67, 0xfb, 0xca, + 0x04, 0x41, 0xed, 0xe0, 0x71, 0x70, 0x84, 0xb0, 0x72, 0x0b, 0x7f, 0x65, 0x0e, 0xfc, 0x73, 0xeb, 0x16, 0x7e, 0x41, + 0x9f, 0xd7, 0xbd, 0xc2, 0xb1, 0xa4, 0x2f, 0xfa, 0x2f, 0xac, 0xc5, 0x2c, 0x12, 0x3e, 0xba, 0xf5, 0x51, 0xc2, 0x65, + 0x13, 0x42, 0x6f, 0x88, 0x2c, 0x75, 0x05, 0xb8, 0x14, 0x95, 0x3b, 0xbb, 0xb0, 0xb6, 0x1e, 0x91, 0x92, 0xa2, 0xfd, + 0x84, 0xcb, 0x7d, 0x44, 0x66, 0xf4, 0x02, 0x7e, 0xec, 0x2f, 0xfd, 0xd7, 0x91, 0x9c, 0x06, 0x59, 0x94, 0xc6, 0x62, + 0xe6, 0xe3, 0x06, 0x42, 0x38, 0xc8, 0x95, 0xbd, 0xf1, 0x39, 0x2e, 0xf6, 0x2f, 0xc8, 0x8d, 0xa4, 0xa8, 0x8f, 0x1a, + 0x33, 0xf2, 0x52, 0xd2, 0x8b, 0xe3, 0xfd, 0xe5, 0x8d, 0x2c, 0x7a, 0x17, 0xe4, 0xa6, 0xf4, 0xd8, 0x93, 0xaf, 0xa9, + 0x8f, 0x69, 0xef, 0xc6, 0x40, 0x73, 0x2a, 0x66, 0xda, 0x73, 0x8f, 0x30, 0xf9, 0x00, 0x71, 0x95, 0xac, 0xe2, 0x36, + 0x26, 0xb4, 0xb2, 0x47, 0x91, 0x50, 0x2e, 0x02, 0x74, 0x70, 0xe0, 0x94, 0x95, 0xaa, 0x02, 0x39, 0x91, 0xb4, 0x66, + 0x90, 0x93, 0x37, 0x2a, 0x42, 0x73, 0x22, 0xfd, 0x0c, 0xdb, 0x61, 0x7c, 0xeb, 0x87, 0x36, 0x47, 0x33, 0x1b, 0x68, + 0x0f, 0x43, 0xc0, 0x25, 0xcb, 0x22, 0x29, 0xb2, 0x21, 0x76, 0xd5, 0x0f, 0xf2, 0x37, 0x7a, 0x31, 0xf0, 0xfe, 0xd3, + 0x3f, 0xfd, 0x38, 0xfe, 0x31, 0x1b, 0x5e, 0x90, 0xb7, 0xf4, 0xf0, 0xd8, 0xef, 0x87, 0xfe, 0x5e, 0xb3, 0xb9, 0xfa, + 0xf1, 0x70, 0xf0, 0x8f, 0xa8, 0xf9, 0xcb, 0x49, 0xf3, 0x87, 0x21, 0x5e, 0xf9, 0x3f, 0x1e, 0xf6, 0x07, 0xe6, 0x69, + 0xf0, 0x8f, 0xde, 0x8f, 0xf9, 0xf0, 0xcf, 0xba, 0x70, 0x1f, 0xe3, 0xc3, 0x09, 0x59, 0x48, 0x7a, 0xd8, 0x6c, 0xf6, + 0x0e, 0x27, 0x64, 0x2e, 0xe9, 0x21, 0xfc, 0x7f, 0x49, 0xdf, 0xb1, 0xc9, 0x8b, 0x9b, 0xb9, 0x7f, 0xd1, 0x5b, 0xed, + 0x2f, 0xff, 0x56, 0xc0, 0xa8, 0x83, 0x7f, 0xfc, 0xf8, 0x63, 0x8e, 0x1e, 0xf4, 0xe8, 0xe1, 0xb0, 0x81, 0x7d, 0x28, + 0xfd, 0x33, 0x55, 0xff, 0xfa, 0xfd, 0x70, 0xf0, 0x0f, 0x03, 0x05, 0x7a, 0xf0, 0xe3, 0xc5, 0x71, 0x8f, 0x0e, 0x57, + 0x3e, 0x5a, 0x3d, 0xc0, 0x2b, 0x8c, 0x57, 0xfb, 0xf8, 0x82, 0xa0, 0x09, 0xc2, 0x64, 0x22, 0xe9, 0xe1, 0x83, 0xc3, + 0x09, 0xb9, 0x92, 0xf4, 0x10, 0x1d, 0x4e, 0xc8, 0x0b, 0x49, 0x0f, 0xff, 0xe1, 0xf7, 0x43, 0xed, 0x61, 0x5b, 0x29, + 0xf7, 0xc6, 0x0a, 0x82, 0x1b, 0x51, 0xc6, 0xa2, 0x95, 0xe4, 0x32, 0x61, 0x78, 0xff, 0x90, 0x93, 0x33, 0x85, 0x26, + 0x5f, 0x82, 0x13, 0x06, 0x6c, 0x3b, 0x7f, 0x79, 0x0e, 0x9b, 0x0d, 0x34, 0xb3, 0x1f, 0x66, 0x44, 0xfb, 0x01, 0xf2, + 0x50, 0x92, 0xab, 0x28, 0x59, 0xb0, 0x3c, 0x64, 0x05, 0x26, 0x23, 0x7a, 0x26, 0xfd, 0x36, 0x26, 0xef, 0x24, 0xfc, + 0xe8, 0x60, 0x72, 0x66, 0x02, 0x98, 0x70, 0x90, 0x35, 0x51, 0xa5, 0x42, 0x6b, 0x2c, 0x08, 0x93, 0xf9, 0x96, 0x4a, + 0x39, 0x05, 0xef, 0x02, 0x26, 0xe3, 0x5a, 0xb8, 0x93, 0x5c, 0x53, 0x4b, 0x12, 0xef, 0x33, 0xc6, 0xbe, 0x8b, 0x92, + 0x8f, 0x2c, 0xf3, 0x6f, 0x48, 0xbb, 0xf3, 0x39, 0x51, 0x2e, 0xe8, 0xbd, 0x36, 0xee, 0x96, 0xb1, 0xaa, 0x53, 0xa9, + 0x63, 0x04, 0x20, 0x64, 0xeb, 0xbe, 0x18, 0xd8, 0xf1, 0xbd, 0x6c, 0xc3, 0x61, 0x95, 0x45, 0xd7, 0x08, 0xd7, 0xe3, + 0xa2, 0x3c, 0xbd, 0x8a, 0x12, 0x1e, 0x7b, 0x92, 0xcd, 0xe6, 0x49, 0x24, 0x99, 0x67, 0xd6, 0xeb, 0x45, 0x30, 0x10, + 0x2a, 0x55, 0x86, 0xd8, 0x31, 0x38, 0x63, 0x1b, 0x70, 0x82, 0xb3, 0xe2, 0x43, 0x74, 0xca, 0xa8, 0x1d, 0xaf, 0xab, + 0xe0, 0xd7, 0x7a, 0x7c, 0xaf, 0xd9, 0x06, 0x47, 0xd8, 0x50, 0x89, 0xe7, 0x9c, 0xa4, 0x14, 0x84, 0x68, 0xa7, 0x8f, + 0x8e, 0xf3, 0xab, 0x49, 0x0f, 0x41, 0x6c, 0x46, 0xd0, 0xb7, 0xca, 0x2f, 0x04, 0x0d, 0xa6, 0xb4, 0xd5, 0x9d, 0x1e, + 0xb3, 0xee, 0xb4, 0xd1, 0xb0, 0x3a, 0x74, 0x42, 0xb3, 0xc1, 0x54, 0x77, 0x8f, 0x48, 0x4c, 0x16, 0xb4, 0xd9, 0x26, + 0x13, 0xda, 0x52, 0x5d, 0xba, 0x93, 0xe3, 0xc4, 0x4c, 0x73, 0x70, 0xe0, 0x8b, 0x20, 0x89, 0x72, 0xf9, 0x25, 0x18, + 0xfb, 0x74, 0x42, 0x62, 0x2a, 0x02, 0x76, 0xc3, 0x46, 0x7e, 0x82, 0x49, 0x6c, 0x38, 0x0d, 0xee, 0xe2, 0x09, 0x75, + 0x9a, 0x81, 0x11, 0x41, 0xdf, 0xf6, 0xe3, 0x41, 0x7b, 0x48, 0x29, 0x45, 0x7b, 0xcd, 0x26, 0xea, 0x0b, 0xba, 0x90, + 0x21, 0x94, 0x38, 0xaa, 0x32, 0x9d, 0x43, 0x51, 0xc7, 0x29, 0xf2, 0x5f, 0xc8, 0x40, 0xb2, 0x5c, 0xfa, 0x50, 0x0c, + 0xe6, 0x7f, 0x6e, 0x09, 0x1b, 0x1d, 0x1f, 0xa2, 0x06, 0x94, 0x2a, 0xe2, 0xc4, 0x44, 0xd0, 0x4b, 0x1c, 0xc6, 0x83, + 0xa3, 0xa1, 0xcb, 0xff, 0x55, 0x21, 0x4c, 0x7e, 0xd9, 0x8f, 0x07, 0x2d, 0x35, 0x79, 0x0f, 0xf5, 0x7d, 0x41, 0x73, + 0xad, 0xa0, 0xf5, 0xf3, 0xf0, 0xad, 0x5a, 0x2a, 0x0e, 0x0d, 0x70, 0x66, 0xde, 0x05, 0x6d, 0x76, 0x42, 0x7f, 0xe1, + 0x2e, 0xa2, 0x09, 0x93, 0x19, 0x2c, 0x90, 0x88, 0x42, 0x7b, 0x22, 0x28, 0xcc, 0x58, 0x75, 0xbb, 0x0c, 0xcd, 0xf3, + 0x03, 0xf4, 0xa0, 0x7f, 0x25, 0xc3, 0x89, 0xd4, 0xd3, 0x5f, 0xc9, 0xd5, 0x0a, 0xfe, 0x9f, 0xc8, 0xbe, 0xa0, 0x97, + 0xaa, 0x68, 0x61, 0x8a, 0xe6, 0x50, 0xf4, 0x36, 0x04, 0x50, 0x49, 0x5e, 0x2a, 0x59, 0x7a, 0x4f, 0xae, 0xa8, 0x82, + 0xfd, 0xe0, 0x20, 0x1b, 0x4c, 0x1b, 0xed, 0x21, 0xf8, 0xf7, 0x33, 0x99, 0x7f, 0xc7, 0xe5, 0xd4, 0x47, 0x87, 0x3d, + 0x84, 0xfb, 0xc8, 0x83, 0xad, 0xed, 0xa6, 0x0d, 0xaa, 0x31, 0x9c, 0x34, 0x5e, 0xca, 0x70, 0xd1, 0xa3, 0xad, 0xbe, + 0xcf, 0x8d, 0x3f, 0x0f, 0x93, 0xc4, 0x30, 0xce, 0x16, 0x59, 0xe0, 0x86, 0x94, 0x0d, 0xfb, 0xbc, 0xc0, 0x8d, 0x59, + 0xe3, 0x0a, 0x87, 0x49, 0x63, 0xd6, 0xf0, 0x17, 0x94, 0xd2, 0x66, 0xa7, 0xec, 0x66, 0xa5, 0xdf, 0x14, 0x87, 0x57, + 0xd6, 0xd9, 0x39, 0x50, 0xc7, 0x21, 0x6d, 0xf8, 0xd9, 0x80, 0x0d, 0x57, 0x2b, 0x74, 0xdc, 0xef, 0x21, 0xdc, 0xf0, + 0x2d, 0xa1, 0x1d, 0x5a, 0x4a, 0xc3, 0x98, 0xf0, 0x61, 0x61, 0x42, 0x49, 0xef, 0x6b, 0x61, 0xa3, 0x65, 0x75, 0xd8, + 0x1d, 0x1e, 0xc0, 0x8a, 0xd2, 0x8e, 0xd1, 0xfa, 0xea, 0x1c, 0x96, 0x69, 0x89, 0x39, 0xa5, 0x2d, 0x22, 0xa8, 0xf5, + 0x5d, 0x4f, 0xa9, 0xac, 0x08, 0x3e, 0xa1, 0x55, 0x73, 0x32, 0x88, 0x48, 0x3c, 0xa4, 0xaf, 0xb5, 0x3d, 0xd2, 0xb5, + 0x7e, 0x71, 0x96, 0xd0, 0xf7, 0x6b, 0xd1, 0xdb, 0x08, 0x62, 0x2b, 0xd7, 0xc1, 0x68, 0x91, 0x65, 0x2c, 0x95, 0x6f, + 0x44, 0x6c, 0xd4, 0x34, 0x96, 0x80, 0xa5, 0x04, 0x61, 0x59, 0x02, 0x3a, 0x5a, 0xc7, 0x9e, 0x8c, 0xc5, 0x46, 0xf5, + 0x84, 0x2e, 0xb4, 0xfa, 0xa4, 0x82, 0xb5, 0xdd, 0x89, 0xb1, 0x8b, 0x7d, 0x4c, 0x16, 0x26, 0x8a, 0xeb, 0x07, 0x41, + 0x30, 0x09, 0x46, 0x50, 0x0d, 0x13, 0xe4, 0xb8, 0x50, 0xe7, 0xc8, 0xcf, 0xe9, 0x75, 0x90, 0xb2, 0x1b, 0x35, 0xab, + 0x8f, 0x2b, 0xc9, 0x6c, 0x8f, 0xd7, 0xf1, 0xb4, 0xab, 0xd8, 0x4d, 0x1e, 0xa4, 0x22, 0x66, 0x80, 0x1e, 0x88, 0xdb, + 0x9b, 0xa2, 0x69, 0x94, 0xbb, 0xf1, 0xa9, 0x0a, 0xbe, 0x81, 0xeb, 0xbc, 0x9e, 0x80, 0xc7, 0x57, 0xe9, 0x5a, 0x65, + 0x63, 0xed, 0x06, 0xc7, 0x98, 0x8f, 0xfd, 0x49, 0x00, 0x71, 0x3d, 0x45, 0x42, 0x12, 0x4c, 0xb9, 0x89, 0x4b, 0x54, + 0xb3, 0x72, 0xcc, 0x2b, 0x1a, 0x0f, 0x44, 0xa3, 0xa1, 0xbc, 0xd0, 0x0b, 0x4d, 0x12, 0x13, 0x4c, 0xae, 0xca, 0xb3, + 0x65, 0xdb, 0xbd, 0x95, 0xb4, 0x3e, 0x95, 0x7f, 0x55, 0x77, 0xe7, 0x36, 0xa4, 0xc4, 0xca, 0x53, 0x28, 0xfd, 0x19, + 0x26, 0xcf, 0xe8, 0xa1, 0x3f, 0x08, 0xfa, 0x7f, 0x19, 0xe2, 0xbe, 0x1f, 0xfc, 0x19, 0x1f, 0x6a, 0xce, 0x71, 0x85, + 0xbb, 0x89, 0x9e, 0x63, 0xa9, 0xe2, 0x97, 0x6d, 0xa2, 0x3c, 0x89, 0x61, 0x4a, 0xd2, 0x68, 0xc6, 0xc2, 0x67, 0x70, + 0xc8, 0x2d, 0xe1, 0xbc, 0x95, 0x04, 0x28, 0x29, 0x7c, 0x66, 0x78, 0x49, 0x80, 0xfa, 0xaf, 0x64, 0xf9, 0xd4, 0x47, + 0xfd, 0xe7, 0xd5, 0xd3, 0x5f, 0x50, 0xff, 0x17, 0x19, 0xfe, 0x5c, 0x18, 0x6f, 0x77, 0x6d, 0x8e, 0xc7, 0x76, 0x8e, + 0x42, 0x6f, 0x8d, 0x83, 0xbb, 0x05, 0xde, 0x74, 0x74, 0x4c, 0x70, 0xc1, 0xc7, 0x25, 0x33, 0xca, 0x03, 0x19, 0x4d, + 0x00, 0xa9, 0xce, 0x1e, 0xe4, 0x6e, 0x5c, 0xbf, 0x5a, 0x31, 0x90, 0x8a, 0xa5, 0x57, 0x40, 0xe6, 0xa4, 0xd7, 0xc2, + 0xcb, 0x5a, 0x5b, 0xa5, 0x33, 0xd5, 0xe3, 0xe8, 0x25, 0x9f, 0xbe, 0xa2, 0xad, 0xee, 0xd5, 0xf1, 0xa4, 0x7b, 0xd5, + 0x68, 0xe0, 0xdc, 0x92, 0xd6, 0x62, 0x70, 0x35, 0x24, 0x5f, 0x83, 0x53, 0xcf, 0xa5, 0x25, 0x52, 0x5b, 0x5e, 0xc7, + 0x2c, 0xaf, 0xd1, 0x48, 0x0b, 0xdc, 0x75, 0xba, 0x4e, 0x74, 0xd7, 0xa2, 0xd0, 0x38, 0x59, 0x27, 0xb5, 0xa7, 0x58, + 0x95, 0x40, 0x32, 0x14, 0xa5, 0xf4, 0x46, 0xe2, 0xad, 0xa3, 0xc2, 0x98, 0xd0, 0x5d, 0x9d, 0x59, 0x60, 0x9f, 0x5a, + 0x4a, 0xf8, 0x80, 0x05, 0xe8, 0x5a, 0x7a, 0x82, 0x67, 0x64, 0xd1, 0x68, 0x2b, 0x32, 0x6f, 0xb6, 0xbb, 0xf5, 0xb1, + 0x9e, 0x54, 0x63, 0x91, 0x45, 0x83, 0xce, 0x4a, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0x83, 0x9d, 0xf6, 0xe4, 0xd6, + 0x02, 0x10, 0x37, 0xeb, 0x49, 0x19, 0x56, 0xc2, 0x56, 0x32, 0x95, 0x07, 0x3c, 0x4d, 0x59, 0x06, 0x52, 0x94, 0x4a, + 0xc2, 0x8b, 0xa2, 0x92, 0xec, 0x20, 0x46, 0x09, 0xa3, 0x19, 0x70, 0x1e, 0x65, 0x77, 0x91, 0x94, 0x08, 0x32, 0x55, + 0x7c, 0x83, 0x52, 0x7a, 0x66, 0xd3, 0x59, 0xa4, 0xe2, 0x41, 0x09, 0xe5, 0x8e, 0x4c, 0xca, 0x29, 0x0b, 0xce, 0xf7, + 0x4f, 0xc5, 0x9d, 0x36, 0xd9, 0x80, 0x0f, 0x43, 0xd5, 0x2c, 0x31, 0x9c, 0x2b, 0xa2, 0x1f, 0x7c, 0x89, 0xcb, 0xe8, + 0x48, 0xa0, 0x18, 0xe0, 0x73, 0x9e, 0x31, 0xa5, 0x83, 0xef, 0x5b, 0xbb, 0x2f, 0xa9, 0x2b, 0x90, 0x89, 0xeb, 0xbd, + 0x01, 0x44, 0x46, 0xe0, 0xdc, 0x49, 0xe9, 0x46, 0xb3, 0xf3, 0xfd, 0x93, 0xb7, 0xdb, 0x6c, 0xe0, 0xd5, 0xca, 0x58, + 0xbf, 0x4a, 0xb7, 0x21, 0x51, 0x05, 0x69, 0x62, 0x7e, 0x84, 0x7e, 0xa2, 0x54, 0xa4, 0xc8, 0xcf, 0x80, 0x8a, 0xce, + 0xf7, 0x4f, 0xde, 0xfb, 0x99, 0xf2, 0x2d, 0x61, 0xe2, 0x2e, 0xdb, 0x17, 0xd4, 0x9f, 0x52, 0x86, 0xf5, 0xda, 0x4b, + 0xd6, 0x25, 0x1c, 0x01, 0x1e, 0x4e, 0x55, 0x25, 0x58, 0x10, 0x03, 0x3e, 0xa4, 0x89, 0xc1, 0x00, 0x4d, 0x30, 0x49, + 0x6a, 0x76, 0x19, 0x85, 0x0d, 0x50, 0x73, 0x9d, 0xc1, 0x4e, 0x04, 0x5a, 0xf5, 0xc3, 0x24, 0x51, 0xb3, 0xca, 0x42, + 0x0b, 0x8f, 0x67, 0x1b, 0x59, 0x69, 0x95, 0x39, 0xfa, 0x2d, 0xd8, 0x4e, 0xf6, 0xe1, 0x0d, 0xb5, 0x96, 0x84, 0x29, + 0x78, 0x6e, 0xd3, 0xc7, 0xce, 0xf7, 0x4f, 0x5e, 0x9b, 0x0c, 0xb2, 0x79, 0x64, 0xf9, 0xfd, 0x86, 0x89, 0x79, 0xf2, + 0x3a, 0xa8, 0x6a, 0x55, 0xe3, 0xf3, 0xfd, 0x93, 0x0f, 0xdb, 0x9a, 0x41, 0x79, 0xb1, 0xa8, 0x6c, 0x7c, 0x05, 0xdf, + 0x92, 0x25, 0xe1, 0xd2, 0x08, 0x87, 0x90, 0x17, 0x44, 0x09, 0xa4, 0x30, 0x2f, 0x4a, 0xd7, 0xc8, 0x73, 0x92, 0x52, + 0x15, 0x06, 0xaa, 0xef, 0x9a, 0x51, 0xf3, 0xb8, 0x48, 0xcf, 0x46, 0x62, 0xce, 0x76, 0xc4, 0x86, 0x6e, 0x70, 0xc0, + 0x67, 0x90, 0x3a, 0xa3, 0x40, 0xe7, 0x64, 0xaf, 0x85, 0xbb, 0x75, 0xf1, 0x95, 0x2a, 0x22, 0x15, 0x35, 0xd9, 0x42, + 0xa6, 0xb4, 0x45, 0x12, 0xda, 0x22, 0x11, 0xcd, 0x07, 0x2d, 0x2d, 0x20, 0xba, 0x51, 0x39, 0xae, 0x16, 0x33, 0x90, + 0x15, 0x66, 0x4e, 0xab, 0x16, 0xc0, 0x71, 0x37, 0x52, 0xbe, 0x47, 0x25, 0xd3, 0x63, 0x45, 0x16, 0x6f, 0x7c, 0x41, + 0x84, 0x1a, 0xf8, 0x8c, 0x5f, 0x26, 0x90, 0x58, 0x02, 0xab, 0x22, 0x12, 0x87, 0x65, 0xd3, 0xb6, 0x69, 0x1a, 0x05, + 0x6a, 0x9f, 0x04, 0x89, 0x02, 0xe0, 0xdc, 0x24, 0x32, 0x79, 0x38, 0xf9, 0x66, 0x97, 0xc7, 0x07, 0x07, 0xbe, 0xee, + 0xf4, 0xa5, 0xf4, 0x85, 0xad, 0xaf, 0x22, 0x77, 0xdf, 0x6a, 0x5e, 0x11, 0x63, 0x05, 0x7f, 0xa3, 0x91, 0x0c, 0x0b, + 0x08, 0x43, 0xfb, 0x51, 0x1d, 0x83, 0x16, 0x78, 0xa5, 0xeb, 0xd5, 0x97, 0xdf, 0x68, 0x94, 0x51, 0xda, 0x3a, 0xb6, + 0x6e, 0x48, 0x5a, 0x5c, 0xf9, 0x65, 0xea, 0x4f, 0x6b, 0x23, 0x5f, 0xca, 0x82, 0x80, 0xb9, 0x4b, 0xb3, 0xdc, 0x2e, + 0xc6, 0x39, 0x12, 0x1c, 0xda, 0x7d, 0x69, 0xb2, 0x16, 0x88, 0xca, 0xae, 0x32, 0x8d, 0x2c, 0x3b, 0xeb, 0xe0, 0xd0, + 0x36, 0x82, 0xa8, 0x14, 0x34, 0x6a, 0x14, 0x86, 0xbc, 0xdf, 0x6c, 0xe6, 0x5c, 0x92, 0x1c, 0x1b, 0x27, 0x97, 0x82, + 0x42, 0x21, 0xab, 0x53, 0x22, 0xe5, 0x25, 0x9d, 0xef, 0x26, 0xf9, 0x13, 0x87, 0xe4, 0x9f, 0x51, 0xe6, 0x90, 0xbf, + 0x76, 0x71, 0x04, 0xc2, 0x38, 0x17, 0x72, 0x5b, 0x75, 0x3a, 0xa7, 0xe0, 0x44, 0xab, 0x63, 0xb4, 0x16, 0x56, 0xdc, + 0xc1, 0x50, 0xdc, 0x13, 0xa2, 0xdc, 0x90, 0xc4, 0xc6, 0x80, 0xfd, 0x2a, 0xa8, 0x06, 0x53, 0x6f, 0xf3, 0xe9, 0xb9, + 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0xf1, 0xd0, 0xd3, 0xf9, 0xe6, 0xc9, 0x75, 0x72, 0x3f, 0x61, 0xd5, 0xce, 0xc1, 0xad, + 0x67, 0x82, 0xc2, 0xfc, 0x65, 0x1c, 0xbb, 0xce, 0x7c, 0xd6, 0x0e, 0xa1, 0x95, 0x7f, 0x00, 0x6d, 0xbb, 0xad, 0x5a, + 0x30, 0x67, 0x58, 0xe0, 0x47, 0x3a, 0x03, 0x35, 0xca, 0x76, 0xb0, 0x8f, 0x13, 0xd5, 0x80, 0xa5, 0xf1, 0xf6, 0xea, + 0x67, 0x85, 0x21, 0x13, 0x0d, 0x1a, 0x5e, 0x02, 0xff, 0xd3, 0x24, 0x0f, 0x74, 0xa3, 0xe4, 0x02, 0x20, 0x68, 0xae, + 0xf0, 0x54, 0x21, 0x0c, 0xa1, 0xca, 0xfb, 0xfe, 0x72, 0x8f, 0xd2, 0x79, 0xe5, 0x7d, 0x7c, 0x57, 0xa5, 0x5e, 0x01, + 0x59, 0xe0, 0x10, 0xcc, 0xc7, 0xb2, 0x40, 0x87, 0x2f, 0xcf, 0x6c, 0x73, 0x65, 0x42, 0x06, 0x95, 0xc6, 0xed, 0x84, + 0x36, 0x95, 0x5b, 0x4e, 0xd7, 0x5b, 0x34, 0xac, 0xd5, 0xee, 0x43, 0xed, 0x1b, 0xa9, 0x60, 0x84, 0xe7, 0xf7, 0xaa, + 0xb5, 0x1d, 0xb7, 0xf8, 0xb8, 0x9e, 0xbf, 0xb2, 0xb6, 0x29, 0x01, 0x4f, 0x73, 0x96, 0xc9, 0x67, 0x6c, 0x2c, 0x32, + 0x88, 0x59, 0x94, 0x38, 0xc1, 0xc5, 0xbe, 0xe3, 0xb7, 0x53, 0xeb, 0x73, 0x02, 0x05, 0x6b, 0x0b, 0x54, 0xbf, 0x3e, + 0xaa, 0xa0, 0xf5, 0xf9, 0x7a, 0xaf, 0xf9, 0xc1, 0xc1, 0x87, 0x0a, 0x4d, 0x06, 0x4a, 0x05, 0x85, 0xc3, 0xb4, 0xb4, + 0x4a, 0x63, 0x22, 0xb9, 0xfb, 0x7e, 0xe9, 0x04, 0xb0, 0x0c, 0xc3, 0xe5, 0x3d, 0x2f, 0xa9, 0x2c, 0x26, 0xeb, 0x2c, + 0xde, 0x38, 0x27, 0xb8, 0x6b, 0xb8, 0x00, 0x87, 0x07, 0x53, 0x5b, 0x7b, 0x8b, 0xf2, 0x2a, 0x19, 0xb6, 0x84, 0xe1, + 0x14, 0x90, 0xe5, 0x2b, 0x33, 0xc4, 0xa1, 0xc0, 0xad, 0x66, 0xc9, 0x29, 0xe8, 0x95, 0x53, 0x92, 0x07, 0x53, 0x48, + 0x7f, 0xad, 0x1d, 0x59, 0x8c, 0x89, 0x4e, 0xcc, 0x71, 0x52, 0x09, 0x4e, 0x5e, 0x6e, 0x73, 0x29, 0x5b, 0xa2, 0x66, + 0x4a, 0xea, 0xa8, 0x16, 0xb8, 0xec, 0x10, 0x5c, 0xf9, 0xdc, 0x28, 0x6e, 0x36, 0x6e, 0x06, 0x0c, 0xf8, 0x99, 0xf4, + 0x75, 0x30, 0x0a, 0x64, 0x86, 0x08, 0x16, 0x7e, 0x6d, 0xea, 0xae, 0x50, 0xdd, 0x88, 0x41, 0xdc, 0xd4, 0x45, 0x93, + 0x50, 0x71, 0xbd, 0xd3, 0x8a, 0x97, 0x8e, 0x75, 0x06, 0xb5, 0xb4, 0x5c, 0xb0, 0x4a, 0x24, 0x71, 0x96, 0x3f, 0xd6, + 0x49, 0xd1, 0x65, 0x23, 0xc2, 0x14, 0x18, 0xef, 0xd5, 0x1e, 0xb0, 0x02, 0xfe, 0x5f, 0x9e, 0x48, 0x67, 0x47, 0xad, + 0x13, 0x5b, 0xcd, 0xe9, 0x48, 0xfd, 0x77, 0x90, 0xea, 0xb2, 0x7e, 0xe6, 0x5f, 0x2a, 0x59, 0xc8, 0x49, 0x5e, 0x63, + 0xec, 0xa9, 0x62, 0xec, 0x18, 0xf4, 0x34, 0x9b, 0xf8, 0xdd, 0x37, 0x19, 0x2f, 0xdc, 0x48, 0x39, 0x43, 0x62, 0x5f, + 0x97, 0xd1, 0x72, 0xe7, 0xf7, 0xda, 0x6e, 0x84, 0x9c, 0x42, 0x16, 0x10, 0x31, 0x9c, 0x3d, 0xc5, 0x24, 0x6f, 0x34, + 0xba, 0xf9, 0x31, 0xab, 0x9c, 0x24, 0x15, 0x8c, 0x1c, 0x02, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x21, 0x7f, 0x9b, + 0x99, 0x9d, 0x83, 0xaf, 0xfd, 0xe4, 0x9d, 0xef, 0x72, 0x35, 0xb7, 0x6d, 0x19, 0x34, 0x85, 0xf5, 0xf8, 0x55, 0xc0, + 0xe5, 0xeb, 0xbb, 0x13, 0x3c, 0x00, 0xee, 0xbd, 0x36, 0x81, 0x54, 0x34, 0xdc, 0x95, 0x9a, 0x25, 0x94, 0xa7, 0xaf, + 0x8b, 0xab, 0xac, 0x44, 0x77, 0xb2, 0xae, 0xac, 0x8c, 0x59, 0x49, 0xf3, 0xa2, 0xc8, 0x59, 0x15, 0xde, 0x5f, 0x4b, + 0xbf, 0x54, 0xc2, 0x65, 0xd3, 0xdb, 0x7e, 0x3a, 0xa7, 0x92, 0x38, 0x84, 0xfa, 0xf5, 0xae, 0xd8, 0x47, 0x05, 0x26, + 0x9c, 0x6b, 0x23, 0x14, 0x7f, 0xde, 0x26, 0x14, 0x49, 0x6a, 0x8e, 0xbc, 0x12, 0x88, 0xed, 0x7b, 0x08, 0x44, 0xe3, + 0x66, 0xb7, 0x32, 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x6f, 0x29, 0x4d, 0x09, 0x37, 0xbb, 0xd1, 0xeb, 0xac, 0x56, + 0x7c, 0xd0, 0x02, 0x37, 0x12, 0x42, 0xf0, 0xb3, 0xad, 0x7f, 0x3a, 0x9c, 0x58, 0xbb, 0x81, 0x7d, 0x5e, 0x9a, 0x2c, + 0x38, 0x80, 0x04, 0x67, 0x5f, 0x25, 0x65, 0x29, 0x9a, 0x36, 0x14, 0x64, 0x08, 0x9c, 0xf2, 0x32, 0xcc, 0x04, 0x10, + 0x2b, 0x59, 0x61, 0x0c, 0x48, 0x7f, 0x6b, 0xee, 0x9f, 0x35, 0x2f, 0x3f, 0xad, 0x89, 0xd6, 0xe4, 0x8a, 0x56, 0x1f, + 0x6a, 0xf9, 0x06, 0x06, 0x02, 0xa3, 0x1f, 0xee, 0x29, 0x13, 0xb4, 0x12, 0xe5, 0xd8, 0x95, 0x43, 0xa4, 0x05, 0x4e, + 0xb4, 0xbd, 0x0f, 0x3a, 0xc2, 0xbb, 0x45, 0x9a, 0x10, 0xe1, 0xd0, 0xf5, 0x4b, 0x2a, 0x6b, 0xac, 0x64, 0x4a, 0x8d, + 0xa5, 0x44, 0x22, 0x45, 0xa6, 0x92, 0xa6, 0x83, 0xd6, 0x10, 0x14, 0xd0, 0x6e, 0x72, 0x9c, 0x56, 0x26, 0x70, 0xd2, + 0x68, 0xe0, 0xc8, 0xce, 0x3a, 0x1d, 0xf0, 0x46, 0x32, 0x24, 0x8c, 0x24, 0xda, 0x30, 0x39, 0x3b, 0x38, 0xf0, 0xa3, + 0x6a, 0xde, 0x41, 0x32, 0xc4, 0x44, 0xac, 0x56, 0xbe, 0x02, 0x2b, 0xc2, 0xab, 0x55, 0xe4, 0x82, 0xa5, 0xaa, 0xa1, + 0xdb, 0xbc, 0x2f, 0xe9, 0x5c, 0x09, 0xc0, 0x39, 0x40, 0xd8, 0xa0, 0x7e, 0x64, 0xdc, 0x7b, 0x11, 0xb8, 0xa3, 0x1a, + 0xe9, 0x20, 0x69, 0xb4, 0x87, 0x0e, 0xe3, 0x1a, 0x24, 0x43, 0x1a, 0x15, 0xe2, 0xe0, 0x60, 0x2f, 0x37, 0x22, 0xf2, + 0x27, 0x10, 0x65, 0x3f, 0x29, 0xc9, 0xa2, 0x07, 0x74, 0x77, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0xd9, 0x56, 0xdb, + 0xae, 0x96, 0x05, 0x51, 0x36, 0x22, 0x26, 0x18, 0xdc, 0x07, 0xcb, 0xbe, 0x24, 0xf3, 0x57, 0xb2, 0xcc, 0xb1, 0xfe, + 0x79, 0x6b, 0x66, 0x75, 0x10, 0x04, 0x51, 0x36, 0x51, 0xb1, 0x0c, 0x1b, 0x86, 0x55, 0xc4, 0x7f, 0x64, 0xc0, 0x74, + 0x26, 0x1e, 0x94, 0x73, 0x0d, 0xa9, 0x06, 0xdf, 0xaa, 0x36, 0xf6, 0x2e, 0xc9, 0x4f, 0x5b, 0xbd, 0x0c, 0x1a, 0x92, + 0xe7, 0xbf, 0x15, 0x92, 0x87, 0x06, 0x12, 0x4d, 0x1e, 0x6b, 0x38, 0xdb, 0x81, 0x8b, 0x9f, 0xe4, 0x1a, 0xce, 0x76, + 0xe3, 0xd6, 0x62, 0xea, 0x97, 0x5d, 0xf0, 0x39, 0xbc, 0x41, 0x03, 0x5a, 0x15, 0x38, 0x50, 0x3e, 0x5a, 0xd7, 0xbd, + 0x34, 0x2b, 0x05, 0x61, 0x2a, 0xa9, 0xcf, 0xeb, 0x07, 0xa0, 0xd2, 0x46, 0x1d, 0xc3, 0x97, 0x87, 0x73, 0xec, 0xb8, + 0x04, 0xea, 0xa9, 0x2b, 0x40, 0x4e, 0xc6, 0xdb, 0x3e, 0x3f, 0x38, 0x00, 0xdb, 0x00, 0x94, 0xb8, 0x60, 0x14, 0xcd, + 0xe5, 0x22, 0x03, 0x55, 0x2a, 0xb7, 0xbf, 0xa1, 0x18, 0x6e, 0x81, 0xa8, 0x32, 0xf8, 0x01, 0x05, 0xf3, 0x28, 0xcf, + 0xf9, 0x95, 0x2e, 0x33, 0xbf, 0x89, 0xa0, 0x96, 0x94, 0x73, 0xad, 0x13, 0xa6, 0xb8, 0x9b, 0x1a, 0x3a, 0xad, 0xa3, + 0xed, 0xc5, 0x15, 0x4b, 0xe5, 0x2b, 0x9e, 0x4b, 0x96, 0xc2, 0xf2, 0x2b, 0x8a, 0x83, 0x15, 0xe5, 0x18, 0x0e, 0x6c, + 0xad, 0x57, 0x14, 0xc7, 0x77, 0x76, 0x91, 0x75, 0x1d, 0x68, 0x1a, 0xa5, 0x71, 0xa2, 0x27, 0x71, 0xf3, 0x19, 0x6d, + 0x0e, 0x67, 0xd9, 0xd2, 0xcd, 0xa7, 0xa9, 0x94, 0x0d, 0xc5, 0xdd, 0x7d, 0x4e, 0xad, 0x24, 0xb0, 0xd2, 0xf3, 0x4e, + 0xad, 0x05, 0x22, 0xde, 0x3b, 0x36, 0xc1, 0x5d, 0x09, 0x91, 0x0e, 0x47, 0x0d, 0xea, 0x70, 0x5a, 0xba, 0xf9, 0x72, + 0xeb, 0x95, 0xb6, 0x6d, 0xc2, 0x41, 0xd1, 0xc9, 0xe3, 0xdd, 0x96, 0xd5, 0x6b, 0x2b, 0x39, 0xac, 0xb4, 0xe0, 0xf7, + 0x65, 0xcc, 0x78, 0x69, 0xc9, 0x0b, 0xdb, 0xa3, 0xb8, 0x2f, 0xe9, 0x73, 0xb8, 0x33, 0xf4, 0x52, 0xce, 0x92, 0xb5, + 0xab, 0x31, 0xdd, 0xfd, 0x52, 0xfb, 0xdf, 0x97, 0xfe, 0x7b, 0xf2, 0x06, 0x02, 0xbb, 0x5f, 0x55, 0xcd, 0x37, 0x03, + 0xba, 0x5f, 0x55, 0x08, 0xfa, 0x2a, 0xdc, 0x68, 0xe7, 0x04, 0x72, 0x3b, 0xc1, 0xd3, 0xa0, 0x85, 0xac, 0xb6, 0xf4, + 0xb3, 0x0e, 0x23, 0xe9, 0x4c, 0x4b, 0x75, 0x1e, 0x48, 0x95, 0xa7, 0x06, 0xf9, 0x72, 0x75, 0x0b, 0x89, 0x99, 0x0c, + 0x43, 0xad, 0xc3, 0xef, 0xda, 0x1e, 0x23, 0x63, 0x52, 0x6d, 0x67, 0x7c, 0x1d, 0x65, 0x72, 0x1f, 0x4e, 0x99, 0xd8, + 0xb8, 0x87, 0x37, 0xa5, 0xe0, 0x41, 0xbb, 0xdf, 0x14, 0x8e, 0xb1, 0x9d, 0xeb, 0x7b, 0x40, 0xee, 0xf8, 0x54, 0x58, + 0xdd, 0xad, 0x6e, 0x65, 0x7c, 0x0d, 0xf6, 0x3f, 0x26, 0x53, 0x7b, 0x39, 0x8e, 0x19, 0x0e, 0xcc, 0xc2, 0x65, 0x51, + 0x3a, 0x05, 0x84, 0x56, 0xde, 0x32, 0x4c, 0x44, 0xa1, 0x02, 0xdc, 0x3f, 0x90, 0x6f, 0x0c, 0x4b, 0x1c, 0x97, 0x1c, + 0xe7, 0xe4, 0xbe, 0x1c, 0x51, 0x83, 0x5f, 0xc6, 0xef, 0x81, 0x8e, 0x15, 0x85, 0x16, 0x96, 0x8a, 0x9e, 0x0b, 0xb3, + 0x90, 0x9d, 0x69, 0xa9, 0x84, 0x95, 0x29, 0x35, 0x6a, 0x9a, 0x2d, 0x79, 0x9c, 0xd6, 0xca, 0x96, 0xe5, 0xa9, 0xaa, + 0xcd, 0x8b, 0x77, 0x60, 0xb1, 0x0a, 0x2d, 0xae, 0x56, 0x7e, 0x1d, 0xd5, 0x94, 0x3b, 0x91, 0x0c, 0x4c, 0xb8, 0x93, + 0x51, 0x51, 0xd3, 0xac, 0x75, 0x1f, 0x1f, 0xaf, 0x27, 0x14, 0x59, 0xdd, 0xbc, 0x06, 0x87, 0xeb, 0x42, 0xd0, 0xdd, + 0x5d, 0x9f, 0x02, 0xd1, 0xab, 0x2b, 0x27, 0x72, 0x30, 0xf4, 0x73, 0x99, 0x2a, 0x5b, 0xe5, 0xb4, 0x6e, 0xc1, 0x2f, + 0xbe, 0x23, 0x59, 0xd6, 0xa0, 0x6e, 0xb3, 0xde, 0x49, 0x36, 0x7a, 0x2e, 0x76, 0x25, 0x1b, 0xd5, 0xb4, 0xdd, 0xbd, + 0x16, 0xbe, 0x3b, 0x2d, 0x55, 0xcf, 0xb5, 0xbd, 0xc9, 0x6f, 0x98, 0xae, 0x0d, 0xb4, 0xa9, 0xd1, 0x6c, 0xb9, 0xca, + 0x59, 0x51, 0x8c, 0xcb, 0xcb, 0x04, 0x2a, 0x77, 0x67, 0xac, 0xe9, 0xdf, 0x58, 0x8d, 0xea, 0x3a, 0xae, 0xff, 0x03, + 0x9d, 0x24, 0xe2, 0x32, 0x4a, 0xde, 0xc3, 0x7c, 0x55, 0xe5, 0xcb, 0xdb, 0x38, 0x8b, 0x24, 0x33, 0xdc, 0xa5, 0x82, + 0xe1, 0x07, 0x07, 0x86, 0x1f, 0x34, 0x9f, 0xae, 0xfa, 0x93, 0xe5, 0xab, 0x72, 0x80, 0x70, 0x5c, 0x58, 0x96, 0x71, + 0x2e, 0xb7, 0xcf, 0xb1, 0xce, 0xc2, 0xce, 0x4b, 0x16, 0x76, 0x2e, 0xfd, 0xf5, 0xa1, 0x7c, 0xff, 0x9b, 0xed, 0xa3, + 0x6c, 0x72, 0xb6, 0x6f, 0xaa, 0x83, 0xff, 0x4d, 0x78, 0x67, 0x1f, 0x87, 0xcb, 0x1d, 0x05, 0x47, 0x2a, 0x5d, 0x45, + 0x83, 0xfc, 0x0e, 0xd2, 0x0e, 0x24, 0xed, 0x39, 0x77, 0x0e, 0x2a, 0x39, 0x65, 0x13, 0x81, 0xfc, 0xd1, 0x22, 0x97, + 0x62, 0x66, 0xc6, 0xcc, 0xcd, 0x35, 0x23, 0x55, 0x09, 0xae, 0x68, 0x15, 0x6d, 0x0f, 0xeb, 0x17, 0xb9, 0x96, 0x1f, + 0x79, 0x1a, 0x87, 0x39, 0x31, 0x52, 0x24, 0x0f, 0xd3, 0x82, 0xda, 0x64, 0xe3, 0xcd, 0x3a, 0x32, 0xe6, 0x29, 0xcf, + 0xa7, 0x2c, 0xf3, 0x05, 0x5e, 0xee, 0x9a, 0x4c, 0x40, 0x40, 0x46, 0x4f, 0x46, 0xbe, 0xad, 0x2e, 0xfc, 0x05, 0x30, + 0x1a, 0xf8, 0x81, 0x66, 0x4c, 0x4e, 0x45, 0x0c, 0x89, 0x29, 0x41, 0x5c, 0xde, 0x68, 0x3a, 0x38, 0xd8, 0xf3, 0x91, + 0x72, 0x4b, 0xc0, 0xd5, 0x6f, 0xb7, 0x06, 0xf7, 0x97, 0x70, 0x3d, 0xa7, 0x9a, 0x9a, 0xe1, 0x25, 0x5b, 0xbf, 0xc9, + 0x22, 0x83, 0x8f, 0xec, 0x96, 0x64, 0xb8, 0x28, 0x42, 0x0d, 0x35, 0x1a, 0x73, 0x96, 0xc4, 0x88, 0x7c, 0x64, 0xb7, + 0x61, 0x79, 0x5b, 0x5c, 0x5d, 0x6e, 0x56, 0x1b, 0x88, 0xc4, 0x75, 0x8a, 0x48, 0x35, 0x49, 0xb8, 0x2c, 0x88, 0xc8, + 0xf8, 0x04, 0x88, 0xf3, 0x6f, 0xec, 0x36, 0xd4, 0xe3, 0x71, 0xe7, 0xb2, 0x1e, 0x5e, 0x5a, 0xd4, 0x07, 0x4e, 0xb1, + 0xbb, 0x0d, 0xc6, 0xa0, 0x18, 0xa8, 0xbe, 0x43, 0x5a, 0x6b, 0x57, 0x99, 0x87, 0x18, 0x17, 0xf7, 0x5d, 0x0a, 0xf9, + 0xc2, 0x15, 0x6d, 0xb2, 0x96, 0xfa, 0xba, 0xd6, 0x89, 0x41, 0x87, 0x2a, 0xd7, 0xe3, 0xdc, 0xcf, 0xec, 0xa9, 0x33, + 0x77, 0x10, 0x1c, 0x47, 0xd8, 0x17, 0xd2, 0x0c, 0x1a, 0x7e, 0xab, 0x53, 0x42, 0xaa, 0x48, 0xd2, 0xeb, 0xaa, 0x9f, + 0x77, 0xee, 0x03, 0xde, 0x21, 0xa5, 0x25, 0x52, 0xd7, 0x31, 0x0b, 0x9b, 0x2e, 0xfa, 0x9d, 0xa4, 0xfe, 0xd2, 0x2e, + 0x21, 0xcc, 0x5c, 0x2c, 0xca, 0x02, 0xa8, 0xd0, 0xd0, 0x97, 0xce, 0x00, 0xe4, 0x63, 0x9f, 0x6f, 0x48, 0xcd, 0x54, + 0x49, 0xcd, 0xc0, 0xc1, 0xf8, 0x0e, 0x29, 0xc9, 0x14, 0x32, 0x94, 0x12, 0xa9, 0x84, 0x9e, 0xd9, 0x5c, 0x43, 0x42, + 0xee, 0x86, 0x96, 0xd7, 0xe7, 0xf4, 0x9e, 0xa7, 0x35, 0xb0, 0x7c, 0x35, 0x0e, 0x2e, 0x42, 0x58, 0x12, 0xd3, 0x0d, + 0x0a, 0xeb, 0xce, 0xc9, 0x6c, 0x7e, 0xab, 0x2f, 0x02, 0xbb, 0x2c, 0x6a, 0x51, 0xe2, 0x4f, 0xf1, 0x32, 0xf3, 0xa7, + 0x24, 0x85, 0x7c, 0x44, 0x51, 0x94, 0xf0, 0x33, 0x77, 0x37, 0x6a, 0xd9, 0xca, 0xdb, 0xaf, 0xf8, 0x81, 0x32, 0x2f, + 0x21, 0x47, 0x93, 0x64, 0x96, 0xa7, 0x64, 0xbe, 0xba, 0x6b, 0xe7, 0x6c, 0xdb, 0x57, 0x26, 0x45, 0xc7, 0x00, 0xf6, + 0x9d, 0xf4, 0x97, 0xce, 0x2a, 0xdc, 0xbb, 0xdc, 0xe6, 0xca, 0x9f, 0x09, 0xf6, 0x55, 0x49, 0xa4, 0x7e, 0x4e, 0xd7, + 0x24, 0xce, 0xdd, 0xb9, 0x96, 0x3f, 0x2f, 0x58, 0x76, 0x7b, 0xc6, 0x20, 0xd7, 0x59, 0xc0, 0x5d, 0xdf, 0x6a, 0x1b, + 0xaa, 0x3c, 0xf5, 0x7e, 0xaa, 0x94, 0x95, 0xa2, 0x7e, 0x09, 0x70, 0xfd, 0x8a, 0x60, 0xa1, 0xa2, 0x8d, 0x8e, 0x23, + 0x46, 0x9f, 0x16, 0xb6, 0xf3, 0xf2, 0x24, 0xeb, 0x72, 0xf0, 0xaf, 0x55, 0x98, 0x36, 0xc1, 0x02, 0x22, 0xdc, 0x0b, + 0xa9, 0x83, 0x7c, 0xb8, 0xee, 0x95, 0x81, 0x22, 0x08, 0xdf, 0xa5, 0xbb, 0x97, 0xba, 0x2d, 0x6b, 0x76, 0xf7, 0x52, + 0x6b, 0x41, 0x3f, 0x95, 0xf2, 0x43, 0xcc, 0x3c, 0xe5, 0xe5, 0x65, 0x5e, 0x14, 0xb8, 0x00, 0xf0, 0xbe, 0xef, 0xfa, + 0xfe, 0xf7, 0x26, 0x69, 0x30, 0x80, 0x58, 0xec, 0x59, 0x22, 0x2c, 0x13, 0xaf, 0xe6, 0xff, 0x7e, 0x63, 0xfe, 0xef, + 0x9d, 0x2b, 0xa7, 0x60, 0x1a, 0x4d, 0x52, 0x16, 0x5b, 0xd6, 0x89, 0x35, 0x01, 0x2a, 0xbd, 0x2d, 0x97, 0xf4, 0xe3, + 0x45, 0x08, 0x1a, 0xd7, 0x72, 0x2c, 0x52, 0xd9, 0x1c, 0x47, 0x33, 0x9e, 0xdc, 0x86, 0x0b, 0xde, 0x9c, 0x89, 0x54, + 0xe4, 0xf3, 0x68, 0xc4, 0x48, 0x7e, 0x9b, 0x4b, 0x36, 0x6b, 0x2e, 0x38, 0x79, 0xc9, 0x92, 0x2b, 0x26, 0xf9, 0x28, + 0x22, 0xe8, 0x24, 0xe3, 0x51, 0xe2, 0xbd, 0x89, 0xb2, 0x4c, 0x5c, 0x23, 0xf2, 0x4e, 0x5c, 0x0a, 0x29, 0xc8, 0xdb, + 0x9b, 0xdb, 0x09, 0x4b, 0xc9, 0x87, 0xcb, 0x45, 0x2a, 0x17, 0x24, 0x8f, 0xd2, 0xbc, 0x99, 0xb3, 0x8c, 0x8f, 0xbb, + 0x23, 0x91, 0x88, 0xac, 0x09, 0x29, 0xdb, 0x33, 0x16, 0x26, 0x7c, 0x32, 0x95, 0x5e, 0x1c, 0x65, 0x1f, 0xbb, 0xcd, + 0xe6, 0x3c, 0xe3, 0xb3, 0x28, 0xbb, 0x6d, 0xaa, 0x16, 0xe1, 0x67, 0xad, 0xa3, 0xe8, 0xf3, 0xf1, 0xc3, 0xae, 0xcc, + 0xa2, 0x34, 0xe7, 0xb0, 0x4d, 0x61, 0x94, 0x24, 0xde, 0xd1, 0xa3, 0xd6, 0x2c, 0xdf, 0xd3, 0x81, 0xbc, 0x28, 0x95, + 0xc5, 0x05, 0xf9, 0x08, 0x70, 0x07, 0x97, 0x32, 0x25, 0x97, 0x0b, 0x29, 0x45, 0xba, 0x1c, 0x2d, 0xb2, 0x5c, 0x64, + 0xe1, 0x5c, 0xf0, 0x54, 0xb2, 0xac, 0x7b, 0x29, 0xb2, 0x98, 0x65, 0xcd, 0x2c, 0x8a, 0xf9, 0x22, 0x0f, 0x1f, 0xce, + 0x6f, 0xba, 0xa0, 0x59, 0x4c, 0x32, 0xb1, 0x48, 0x63, 0x33, 0x17, 0x4f, 0xa7, 0x2c, 0xe3, 0xd2, 0xad, 0x50, 0xaf, + 0x30, 0x09, 0x13, 0x9e, 0xb2, 0x28, 0x6b, 0x4e, 0xa0, 0x33, 0x98, 0x45, 0xad, 0x98, 0x4d, 0x48, 0x36, 0xb9, 0x8c, + 0xfc, 0x76, 0xe7, 0x09, 0xb1, 0x7f, 0x83, 0x47, 0xd8, 0x6b, 0x6d, 0x2f, 0x6e, 0xb7, 0x5a, 0x7f, 0xc2, 0xdd, 0xb5, + 0x59, 0x14, 0x40, 0x61, 0x7b, 0x7e, 0xe3, 0xe5, 0x02, 0x72, 0xda, 0xb6, 0xf5, 0xec, 0xce, 0xa3, 0x18, 0x12, 0x82, + 0xc3, 0xce, 0xfc, 0xa6, 0x80, 0xd5, 0x85, 0x3a, 0xc9, 0xd4, 0x2c, 0xd2, 0x3c, 0x2d, 0x7f, 0x2b, 0xc4, 0x4f, 0xb7, + 0x43, 0xdc, 0xb1, 0x10, 0x57, 0x58, 0x6f, 0xc6, 0x8b, 0x4c, 0xc5, 0x56, 0xc3, 0x76, 0xae, 0x01, 0x99, 0x8a, 0x2b, + 0x96, 0x59, 0x38, 0xd4, 0xc3, 0x6f, 0x06, 0xa3, 0xb3, 0x1d, 0x8c, 0xa7, 0x9f, 0x02, 0x23, 0x4b, 0xe3, 0x65, 0x7d, + 0x5f, 0xdb, 0x19, 0x9b, 0x75, 0xa7, 0x0c, 0xe8, 0x29, 0xec, 0xc0, 0xef, 0x6b, 0x1e, 0xcb, 0xa9, 0xfe, 0xa9, 0xc8, + 0xf9, 0x5a, 0xd7, 0x3d, 0x6a, 0xb5, 0xf4, 0x73, 0xce, 0x7f, 0x61, 0x61, 0x3b, 0x80, 0x06, 0xc5, 0x05, 0xf9, 0x5b, + 0x79, 0x99, 0xb7, 0xce, 0x3d, 0xc9, 0x0f, 0xee, 0x2d, 0x5f, 0x27, 0x49, 0xb1, 0xba, 0x11, 0x4d, 0x32, 0x2b, 0x2b, + 0xb5, 0xf0, 0x01, 0xb7, 0x9d, 0x3a, 0x4f, 0x94, 0xf7, 0xca, 0x5b, 0x9c, 0xbc, 0xff, 0x83, 0xce, 0xbb, 0x08, 0x21, + 0xd2, 0xe1, 0x24, 0x1b, 0x8a, 0x6e, 0xda, 0xa3, 0xad, 0x6e, 0xda, 0x6c, 0x62, 0x5f, 0xd0, 0x6c, 0x90, 0x9a, 0xf4, + 0x3c, 0x9f, 0xf7, 0x85, 0x32, 0xb6, 0x73, 0x1c, 0x0a, 0xb8, 0x6a, 0xba, 0x5a, 0x55, 0x61, 0x00, 0xae, 0xae, 0x6b, + 0xfc, 0x4d, 0x9a, 0x06, 0x24, 0x77, 0x38, 0x79, 0x6a, 0x5f, 0xec, 0x92, 0x59, 0x5e, 0x91, 0x88, 0x91, 0xc2, 0x5c, + 0x30, 0x8f, 0xe4, 0x14, 0xbc, 0x14, 0xa5, 0xf8, 0xa9, 0x92, 0x98, 0xd0, 0x21, 0xc2, 0xfd, 0xac, 0xcc, 0x70, 0x83, + 0x4c, 0xbe, 0xac, 0x80, 0x51, 0xbe, 0x91, 0x14, 0x46, 0x24, 0xbf, 0x50, 0x6d, 0xd3, 0x59, 0x8b, 0x6e, 0x7c, 0x5f, + 0x8b, 0x8e, 0xa5, 0x92, 0xab, 0xdc, 0x6d, 0x1b, 0x71, 0x98, 0x46, 0xf9, 0xf9, 0x48, 0xdf, 0x95, 0xcc, 0xab, 0x9b, + 0x01, 0x91, 0x82, 0x5e, 0x1b, 0x69, 0x2c, 0x53, 0xf6, 0xe8, 0xf7, 0x72, 0xa7, 0x7d, 0x92, 0xdd, 0x65, 0x9f, 0x94, + 0x0b, 0xcf, 0xc5, 0x22, 0x1b, 0x41, 0x38, 0xd2, 0x48, 0xbd, 0x4d, 0xc7, 0x0d, 0x52, 0x2a, 0x06, 0x22, 0xd2, 0xc9, + 0x04, 0x95, 0x84, 0xbb, 0x2f, 0x95, 0x60, 0x2a, 0xe4, 0xa5, 0xef, 0x6b, 0x18, 0x11, 0x67, 0x97, 0x04, 0x32, 0x3b, + 0x56, 0x49, 0x8d, 0x7e, 0x4a, 0x7b, 0x69, 0xb0, 0x48, 0xf9, 0xcf, 0x0b, 0x76, 0xce, 0x41, 0xd7, 0xe4, 0x01, 0x8f, + 0x55, 0xac, 0x09, 0x64, 0x5f, 0xb3, 0x0d, 0xc1, 0x0b, 0x1e, 0xeb, 0x8d, 0x49, 0x55, 0xa5, 0xc9, 0x6d, 0x42, 0x4d, + 0x04, 0xfe, 0x62, 0xd0, 0x0e, 0x38, 0x89, 0xc5, 0x2c, 0xe2, 0x69, 0xa8, 0x5c, 0xbe, 0xe5, 0x60, 0x21, 0xb4, 0x26, + 0x3c, 0x0e, 0x53, 0xb3, 0x3d, 0x6d, 0x1c, 0xfc, 0x24, 0x78, 0xaa, 0xba, 0x16, 0x5d, 0xa1, 0x10, 0xaa, 0xd1, 0x47, + 0x2d, 0x82, 0x4f, 0xb4, 0x5c, 0x13, 0x98, 0xb8, 0xd5, 0xe5, 0xb5, 0xf3, 0xda, 0x0e, 0xb4, 0xd6, 0x36, 0x4a, 0x1b, + 0x01, 0x62, 0xbd, 0x34, 0x17, 0x99, 0xf4, 0xfd, 0x29, 0x49, 0x30, 0xed, 0x4d, 0x95, 0xb3, 0xeb, 0x38, 0x51, 0xff, + 0xf5, 0x9b, 0xed, 0xb0, 0x5d, 0x9a, 0xef, 0xb5, 0xdb, 0xc0, 0x3a, 0x39, 0xca, 0xdc, 0x28, 0x55, 0xcb, 0x28, 0x7f, + 0xeb, 0xa5, 0x56, 0xcf, 0xe5, 0x72, 0x89, 0x39, 0x6e, 0x5a, 0x54, 0xf9, 0x35, 0x20, 0x54, 0xb0, 0x68, 0xc7, 0x54, + 0xb8, 0xa8, 0xd6, 0x5d, 0xaa, 0x92, 0x17, 0x5a, 0x44, 0x9f, 0xef, 0x2f, 0x33, 0x33, 0x63, 0x71, 0xc1, 0xad, 0x93, + 0xa9, 0x4e, 0x72, 0x85, 0xc1, 0x88, 0xa3, 0x87, 0x6e, 0x6b, 0xa6, 0x61, 0xb9, 0xa5, 0xd9, 0x56, 0xba, 0x0d, 0xf4, + 0x23, 0xcb, 0x68, 0x15, 0xee, 0xda, 0x18, 0x00, 0x72, 0xf5, 0xb6, 0x01, 0x06, 0x66, 0x6b, 0x2e, 0xed, 0x12, 0x40, + 0x1b, 0x1b, 0x33, 0xb8, 0x48, 0x73, 0xb1, 0xbf, 0xfc, 0x46, 0x16, 0x87, 0x4e, 0x53, 0xf5, 0x9b, 0xc7, 0xf0, 0x3f, + 0x48, 0xc0, 0xa5, 0x56, 0x4a, 0x43, 0xf4, 0xf5, 0xdb, 0xb3, 0xf7, 0x88, 0x5c, 0x8a, 0xf8, 0x36, 0x44, 0x32, 0x5b, + 0x30, 0x54, 0xe0, 0x40, 0x4e, 0x59, 0x5a, 0xbe, 0x8c, 0x47, 0x24, 0x2c, 0x48, 0xc4, 0x44, 0x5f, 0xca, 0x5c, 0x37, + 0x92, 0x47, 0x17, 0xc7, 0xea, 0x25, 0x53, 0xbd, 0x63, 0xa9, 0x5f, 0xef, 0x25, 0x33, 0xf8, 0xd9, 0x83, 0x10, 0xca, + 0xf1, 0xa1, 0x9c, 0xaa, 0x87, 0x33, 0x38, 0x30, 0xea, 0x69, 0x7f, 0xb9, 0x41, 0x4c, 0x7d, 0x18, 0x62, 0xda, 0xd3, + 0x4b, 0xc8, 0x55, 0xab, 0x8b, 0x70, 0x74, 0x71, 0x51, 0x1c, 0x1f, 0xc2, 0x58, 0x87, 0x76, 0x5c, 0x80, 0xd0, 0xf6, + 0x2f, 0x09, 0x0c, 0x5e, 0x36, 0x94, 0xd1, 0x1e, 0x0c, 0x01, 0xf3, 0xc6, 0x3d, 0x58, 0x24, 0x10, 0x18, 0xf4, 0x8e, + 0xcb, 0x12, 0x75, 0x62, 0x75, 0xd1, 0x2e, 0x08, 0x74, 0xc3, 0x8a, 0xee, 0xb5, 0x37, 0xb5, 0xda, 0x5f, 0x0b, 0x52, + 0xec, 0x42, 0x77, 0x81, 0xe1, 0x7f, 0x05, 0xd9, 0xf1, 0xa1, 0xc6, 0xc3, 0x85, 0xfb, 0x6a, 0x13, 0xfd, 0xda, 0x81, + 0x12, 0x5b, 0x83, 0x5c, 0x92, 0x8f, 0x92, 0x7c, 0xbc, 0x50, 0x4d, 0xad, 0x30, 0x02, 0x2d, 0x09, 0x84, 0x76, 0xcb, + 0x6a, 0x1d, 0x23, 0x91, 0x24, 0xd1, 0x3c, 0x67, 0xa1, 0xfd, 0x61, 0xe4, 0x12, 0x88, 0xb7, 0x4d, 0x45, 0xc0, 0xa4, + 0xd7, 0x9c, 0x82, 0xba, 0xb0, 0xa9, 0xa5, 0x5c, 0x45, 0x99, 0xdf, 0x6c, 0x8e, 0x9a, 0x97, 0x13, 0x5c, 0xc8, 0xe9, + 0xd2, 0x95, 0x6a, 0x8f, 0x5b, 0xad, 0x2e, 0xe4, 0x42, 0x36, 0xa3, 0x84, 0x4f, 0xd2, 0x30, 0x61, 0x63, 0x59, 0x48, + 0xb8, 0xa5, 0xb6, 0xb4, 0x6a, 0x44, 0xd0, 0x79, 0x94, 0xb1, 0x99, 0x17, 0xc0, 0xbf, 0x77, 0x4f, 0x5c, 0xc8, 0x38, + 0x4c, 0xe5, 0xb4, 0xa9, 0xb2, 0x6e, 0xe1, 0xce, 0x80, 0x9c, 0xd6, 0x9e, 0x97, 0xce, 0x44, 0x23, 0x06, 0x2a, 0x56, + 0x21, 0x33, 0x4f, 0x4e, 0x89, 0xcc, 0xdc, 0x76, 0x29, 0x5e, 0x6e, 0xac, 0x60, 0x53, 0xd2, 0x1f, 0xe1, 0x22, 0x57, + 0x8a, 0xf1, 0x66, 0x63, 0xab, 0x2e, 0xd5, 0x9f, 0x36, 0xd0, 0xe7, 0x28, 0x76, 0x85, 0x76, 0x2c, 0x2f, 0x75, 0x8f, + 0xfb, 0x20, 0xb3, 0xa6, 0x72, 0x12, 0xb7, 0x07, 0x2e, 0x78, 0x3a, 0x5f, 0xc8, 0x81, 0x72, 0x6a, 0x67, 0x70, 0x41, + 0x62, 0x48, 0x9c, 0x12, 0xc0, 0xc1, 0x70, 0xa9, 0x81, 0x19, 0x45, 0xc9, 0xc8, 0x07, 0x88, 0xbc, 0xa6, 0xf7, 0x34, + 0x63, 0x33, 0xdc, 0x9d, 0xf1, 0xb4, 0xa9, 0xeb, 0x1e, 0x39, 0x6a, 0x49, 0xf0, 0x04, 0x9e, 0x8a, 0x40, 0x8d, 0x46, + 0x54, 0xee, 0xea, 0x16, 0x5c, 0x5e, 0x0c, 0x8b, 0xa2, 0x9b, 0x49, 0x7f, 0xf0, 0xda, 0xc7, 0x43, 0xf2, 0x8b, 0xf3, + 0x72, 0x16, 0x64, 0x8f, 0x0a, 0x22, 0x1d, 0xbc, 0xa3, 0x89, 0x7b, 0x16, 0x54, 0xb3, 0x5f, 0x28, 0x34, 0x7c, 0xe7, + 0x23, 0x96, 0xcf, 0x9b, 0x9a, 0x77, 0x35, 0x15, 0xc9, 0x22, 0xe8, 0x8a, 0x8d, 0xa7, 0xf6, 0x7b, 0xb9, 0x54, 0x6c, + 0xc9, 0x5c, 0xd2, 0xd0, 0xce, 0x84, 0x61, 0x79, 0xa9, 0xc7, 0x3c, 0xbb, 0xd7, 0x78, 0x70, 0x8d, 0x9f, 0x5c, 0x9c, + 0xd4, 0x79, 0x1c, 0xf0, 0xa5, 0xf2, 0x05, 0x76, 0x51, 0x92, 0xc0, 0x84, 0x17, 0x56, 0x7d, 0x71, 0x5f, 0xfa, 0x31, + 0x90, 0x43, 0x1f, 0x17, 0xe6, 0x9c, 0x3e, 0x53, 0x2a, 0xa5, 0xf3, 0xd6, 0xbc, 0x3d, 0x69, 0x83, 0x45, 0x5a, 0xfa, + 0x72, 0x08, 0x77, 0xd7, 0xf2, 0xa2, 0xbb, 0x15, 0xef, 0xd2, 0x0a, 0xa9, 0xa7, 0x16, 0x44, 0x51, 0x96, 0xc6, 0xc8, + 0xfb, 0xcb, 0x28, 0xe1, 0xa3, 0x8f, 0x14, 0xed, 0x2f, 0x7d, 0xbc, 0x79, 0xed, 0x51, 0x71, 0x05, 0xcb, 0xb0, 0x71, + 0xdd, 0x91, 0x9e, 0x06, 0x0e, 0x2f, 0xd6, 0x6f, 0xc5, 0x41, 0xbd, 0xfd, 0x25, 0x30, 0x1e, 0x3d, 0x4f, 0xef, 0xa2, + 0x38, 0xaf, 0xde, 0x75, 0x55, 0x41, 0x01, 0x68, 0xd6, 0xe5, 0x9e, 0x22, 0x2a, 0x8a, 0x3e, 0x49, 0x69, 0xc8, 0xd3, + 0x4c, 0x0d, 0xe0, 0x94, 0x86, 0xbf, 0x21, 0xef, 0x2f, 0x65, 0x19, 0x2b, 0x3d, 0x1a, 0x2a, 0x25, 0x83, 0x22, 0x98, + 0x0b, 0xcc, 0xd8, 0x20, 0x66, 0x32, 0xe2, 0x89, 0xee, 0xd2, 0xb5, 0x06, 0xf8, 0xda, 0x8a, 0x56, 0xab, 0xbc, 0xbe, + 0x16, 0x5e, 0xc7, 0xa0, 0x5a, 0xd9, 0xf1, 0x61, 0x05, 0xb7, 0x5a, 0x99, 0x3a, 0x93, 0x6e, 0x68, 0xb0, 0x5a, 0xa1, + 0xae, 0xf3, 0xfe, 0x32, 0x52, 0xd7, 0x86, 0x00, 0x40, 0x61, 0x00, 0x84, 0xa0, 0xb5, 0xbe, 0x16, 0xe3, 0x27, 0x54, + 0x04, 0x32, 0xca, 0x26, 0x4c, 0xae, 0x21, 0x36, 0xd1, 0x39, 0xaa, 0x5d, 0x1b, 0xa0, 0xde, 0x80, 0x36, 0xaa, 0x43, + 0x7b, 0x01, 0x48, 0xef, 0xef, 0x2f, 0x79, 0x41, 0xf7, 0x97, 0x2c, 0x1d, 0x89, 0x98, 0x7d, 0x78, 0xf7, 0x25, 0x5c, + 0x72, 0x14, 0x29, 0x18, 0x16, 0x53, 0x0c, 0x82, 0x53, 0x6d, 0x8e, 0x16, 0x21, 0x42, 0x89, 0x10, 0xcd, 0x09, 0x3c, + 0x35, 0x97, 0x02, 0xb1, 0x40, 0x5e, 0x5f, 0x43, 0xce, 0x62, 0x0d, 0x33, 0x4d, 0x55, 0x2f, 0x51, 0x1c, 0x1f, 0xea, + 0xd6, 0x5a, 0x04, 0xe8, 0x46, 0x80, 0x04, 0x75, 0x4e, 0x2b, 0x1c, 0x40, 0x5e, 0xb3, 0x8b, 0x87, 0x98, 0x5f, 0x95, + 0xc4, 0xa6, 0x2e, 0x50, 0xf5, 0x8e, 0x93, 0xe8, 0x92, 0x25, 0xbd, 0xfd, 0x65, 0xba, 0x5a, 0xb5, 0x8a, 0xe3, 0x43, + 0xfd, 0xe8, 0x1d, 0x2b, 0xbe, 0xa1, 0x5f, 0x78, 0xa9, 0xb6, 0x18, 0x6e, 0x25, 0x42, 0xb6, 0xa7, 0x4d, 0x73, 0x0a, + 0xcd, 0x00, 0x05, 0xf2, 0x54, 0x82, 0x85, 0x6a, 0x54, 0x2a, 0x44, 0x05, 0xf2, 0x78, 0xbc, 0x59, 0x96, 0x4b, 0x36, + 0x87, 0xd2, 0xe9, 0x6a, 0xd5, 0x2e, 0x90, 0x37, 0xe3, 0x29, 0x3c, 0xa5, 0xab, 0x95, 0xba, 0xf0, 0x37, 0xe3, 0xa9, + 0xdf, 0x02, 0xb2, 0x45, 0xde, 0x2c, 0xba, 0x51, 0x0b, 0xb6, 0x35, 0xd1, 0x8d, 0xdf, 0x36, 0x55, 0x41, 0x89, 0x9f, + 0x1c, 0x28, 0xae, 0xda, 0xd1, 0xc4, 0xec, 0x68, 0x4c, 0x16, 0xfa, 0x2a, 0x13, 0xf5, 0x63, 0x9a, 0x6c, 0xdf, 0xd1, + 0xd8, 0xee, 0xe8, 0x62, 0xc7, 0x8e, 0x2e, 0xee, 0xd8, 0xd1, 0xc8, 0xec, 0x9e, 0x57, 0xe2, 0x4e, 0xac, 0x56, 0xed, + 0x56, 0x85, 0xbd, 0xe3, 0xc3, 0x98, 0x5f, 0xc1, 0x6e, 0x80, 0x9a, 0x27, 0xf9, 0x8c, 0x6d, 0x27, 0xca, 0x3a, 0x8a, + 0xd9, 0xaf, 0xc2, 0x64, 0x85, 0x85, 0xb4, 0x8e, 0x05, 0x97, 0xae, 0xcb, 0x98, 0xdb, 0x1f, 0x49, 0xd9, 0x1c, 0xf0, + 0x90, 0x03, 0x1e, 0xa6, 0xf6, 0x05, 0x98, 0x3e, 0x7a, 0x8f, 0x08, 0xf2, 0x90, 0x25, 0xeb, 0x8b, 0xe2, 0x1c, 0x64, + 0x84, 0x5a, 0xdf, 0xbd, 0x68, 0x11, 0x5a, 0xa3, 0xde, 0x6e, 0x9a, 0x83, 0xf0, 0xf8, 0xb5, 0xc8, 0x62, 0x14, 0xea, + 0xa6, 0xbf, 0x0a, 0x55, 0x33, 0x9e, 0x9a, 0x64, 0xab, 0x9d, 0xb4, 0x56, 0xd5, 0xbb, 0x14, 0xd7, 0x79, 0xf4, 0x48, + 0xb7, 0x98, 0x47, 0x52, 0xb2, 0x2c, 0x35, 0x94, 0x8b, 0xd0, 0xff, 0x17, 0x54, 0xb8, 0x85, 0xaf, 0x44, 0x76, 0x03, + 0x2c, 0x01, 0x1a, 0x85, 0xdd, 0xf0, 0x7c, 0x2d, 0x9e, 0xf6, 0x2a, 0x0d, 0xf6, 0x16, 0xbb, 0x46, 0x83, 0x2e, 0x02, + 0x1b, 0x66, 0x31, 0x63, 0xf1, 0xb9, 0x62, 0xd0, 0xfd, 0xd1, 0x85, 0x51, 0x58, 0xd7, 0xc4, 0x5d, 0xd5, 0x81, 0xa0, + 0x1f, 0x17, 0x9d, 0x27, 0x0f, 0x4f, 0x11, 0xd1, 0x3c, 0x5e, 0x8c, 0xc7, 0x08, 0x17, 0xde, 0xfd, 0xba, 0xb5, 0x1f, + 0xfe, 0xb8, 0xf8, 0xe2, 0x45, 0xeb, 0x8b, 0xb2, 0x73, 0x0a, 0x44, 0x64, 0xe2, 0xfb, 0x56, 0x54, 0x39, 0xf0, 0xda, + 0x15, 0x8d, 0xa3, 0x74, 0xf7, 0x72, 0x06, 0xee, 0x72, 0xf2, 0x39, 0x63, 0x31, 0x10, 0x27, 0xd9, 0x28, 0x3d, 0x4f, + 0xd8, 0x15, 0xb3, 0x6f, 0x1e, 0xdc, 0x32, 0xd9, 0x96, 0x1e, 0x23, 0xb1, 0x48, 0xa5, 0x49, 0x74, 0x30, 0xac, 0xd6, + 0x59, 0xd2, 0x85, 0x5a, 0x83, 0x6b, 0x23, 0xdc, 0x6a, 0x39, 0x57, 0x97, 0x5e, 0xc5, 0x05, 0x41, 0x0e, 0x00, 0x3b, + 0x21, 0xeb, 0xef, 0x28, 0x0f, 0x5b, 0xa4, 0xb5, 0x0b, 0x36, 0xd2, 0xc6, 0x21, 0x42, 0x43, 0x8b, 0x27, 0xe5, 0xab, + 0xac, 0xbd, 0x30, 0x62, 0x27, 0xbe, 0x3e, 0x89, 0x81, 0xcb, 0x0c, 0x06, 0x4b, 0x59, 0x9e, 0xef, 0x44, 0x40, 0xb9, + 0x89, 0x04, 0x55, 0xad, 0xd1, 0x8e, 0x51, 0x48, 0x8b, 0xc0, 0x09, 0x53, 0x00, 0x97, 0x11, 0x53, 0xd3, 0x8a, 0x8d, + 0xc7, 0x6c, 0x54, 0xba, 0x7a, 0x21, 0xf6, 0x35, 0xe6, 0x89, 0x84, 0x10, 0x90, 0x8a, 0xcd, 0xa0, 0x37, 0x22, 0x65, + 0x08, 0xdb, 0x6c, 0x4e, 0x03, 0xbf, 0x91, 0xff, 0xdb, 0xe1, 0xd1, 0x23, 0xd6, 0x61, 0x31, 0xb3, 0xac, 0x56, 0xd6, + 0xcd, 0x53, 0x2b, 0xaf, 0x23, 0x52, 0x28, 0x3f, 0xce, 0xae, 0x03, 0x74, 0xbf, 0x63, 0xb2, 0x6c, 0x7f, 0xf1, 0xa8, + 0xdd, 0x2a, 0x10, 0x41, 0x30, 0xdc, 0x7d, 0x4f, 0x89, 0xea, 0x75, 0x04, 0xbd, 0x16, 0xe9, 0xaf, 0xe9, 0xd7, 0x69, + 0x7f, 0xde, 0x46, 0x44, 0xbf, 0x48, 0x00, 0x17, 0x25, 0x33, 0x18, 0x81, 0xf3, 0xf3, 0x77, 0x2f, 0xa5, 0x3e, 0xf8, + 0xfd, 0xe0, 0x79, 0xdc, 0x6e, 0x21, 0x82, 0x72, 0x29, 0xe6, 0xbf, 0x62, 0x09, 0x47, 0x88, 0xa0, 0x51, 0x22, 0x72, + 0xe6, 0xae, 0x41, 0xab, 0xb3, 0xbf, 0x7f, 0x11, 0x1a, 0xa2, 0x79, 0xc6, 0xf2, 0xdc, 0x73, 0xc7, 0x37, 0xa4, 0xf4, + 0x09, 0x86, 0xb9, 0x95, 0xe2, 0x72, 0x26, 0x15, 0x5e, 0xf4, 0x1d, 0x7f, 0x97, 0xaa, 0x74, 0xd9, 0x06, 0xb1, 0x29, + 0x11, 0x50, 0x32, 0x36, 0xad, 0x5d, 0x7d, 0x72, 0xe6, 0x2d, 0x47, 0x4f, 0x4f, 0xac, 0x63, 0xc2, 0x9b, 0x13, 0xd4, + 0x4a, 0x66, 0x3c, 0x3d, 0xdf, 0x52, 0x1a, 0xdd, 0x6c, 0x29, 0x05, 0x95, 0xad, 0x84, 0xce, 0xbc, 0x7e, 0xe6, 0xd3, + 0x58, 0xaf, 0x14, 0x1f, 0x17, 0xc4, 0x58, 0xf9, 0x2d, 0x3f, 0x01, 0xa9, 0xb3, 0x0d, 0x6a, 0x84, 0xdf, 0x3e, 0x1d, + 0x94, 0xfc, 0x9a, 0xe9, 0xca, 0x51, 0x7e, 0xdf, 0x0a, 0xa1, 0xb4, 0x09, 0xfe, 0xeb, 0xe4, 0x57, 0xad, 0x95, 0xdd, + 0x7c, 0x9a, 0xe0, 0x1c, 0xad, 0xea, 0x77, 0x6c, 0xbd, 0xb9, 0xc7, 0xbe, 0xbe, 0xf7, 0x5b, 0x8a, 0x8d, 0xe2, 0x53, + 0xee, 0xff, 0x28, 0xe1, 0xb3, 0x8a, 0x04, 0x36, 0xc1, 0x54, 0x1a, 0x0f, 0x24, 0x33, 0xb9, 0x83, 0x68, 0xd5, 0xe7, + 0x1c, 0xae, 0x68, 0xc2, 0x7b, 0x30, 0x16, 0x19, 0x3b, 0x4f, 0xc4, 0xf5, 0xfa, 0x7b, 0xbd, 0x76, 0x37, 0x9e, 0xf2, + 0xc9, 0xd4, 0xb9, 0x77, 0xc5, 0x68, 0xb9, 0x09, 0x77, 0x4e, 0x50, 0xfc, 0xeb, 0xbf, 0x04, 0xc1, 0xbf, 0xfe, 0xcb, + 0x27, 0x9b, 0xc2, 0xf0, 0xc5, 0x05, 0x91, 0xd5, 0xb0, 0xbb, 0x4f, 0xd7, 0xf6, 0x99, 0xea, 0x38, 0xdf, 0xde, 0x66, + 0x63, 0x13, 0xa0, 0x7e, 0x63, 0x0b, 0x36, 0x0a, 0xf5, 0xe9, 0xf3, 0x7e, 0x0b, 0x60, 0xb0, 0xae, 0x4f, 0x42, 0x06, + 0x8d, 0x7e, 0x17, 0x68, 0x17, 0x38, 0xbc, 0xd7, 0x8e, 0xfc, 0x76, 0x0c, 0x7f, 0x6a, 0x0d, 0xbf, 0x13, 0x7c, 0xe3, + 0x9f, 0x18, 0x5d, 0x5c, 0x94, 0x09, 0x76, 0x6e, 0x57, 0xb8, 0xc0, 0xdf, 0xdf, 0x28, 0x31, 0x8a, 0x47, 0xd8, 0xc2, + 0x3d, 0x75, 0x3d, 0x90, 0x8e, 0x2e, 0x5e, 0xc3, 0x5b, 0x7b, 0x8e, 0x2f, 0x33, 0xeb, 0xe0, 0xbd, 0x43, 0x38, 0xc0, + 0x10, 0xf5, 0x55, 0xa9, 0x41, 0x37, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0x92, 0xd1, 0x85, 0xb1, 0x36, 0x4f, + 0xb5, 0x1b, 0x26, 0x5c, 0x27, 0x6d, 0xe3, 0x9e, 0xa9, 0x21, 0x9d, 0x78, 0xef, 0x15, 0xbe, 0x54, 0x63, 0x56, 0x59, + 0xf7, 0xca, 0xd5, 0x05, 0x76, 0xc4, 0x45, 0xa1, 0xc2, 0xf4, 0x7f, 0xdd, 0x15, 0x49, 0xfc, 0xfb, 0xa7, 0x23, 0x89, + 0xe2, 0x5e, 0x91, 0xc4, 0xbf, 0xff, 0xe1, 0x91, 0xc4, 0xbf, 0xba, 0x91, 0x44, 0xd8, 0xc4, 0x2f, 0xef, 0x15, 0xed, + 0xb3, 0x91, 0x18, 0x71, 0x9d, 0xd3, 0xb6, 0x51, 0xa3, 0x13, 0x31, 0x81, 0x50, 0xdf, 0xbf, 0x7f, 0xe4, 0x2e, 0x11, + 0x13, 0x37, 0x6e, 0x07, 0x6f, 0x6d, 0x85, 0x40, 0x5d, 0xd7, 0x46, 0xd8, 0x4c, 0xac, 0xac, 0x55, 0xde, 0x48, 0x69, + 0x3e, 0xb4, 0x6f, 0x50, 0x40, 0x61, 0xf9, 0x16, 0xa4, 0x16, 0xe9, 0xd8, 0x68, 0x5a, 0xa8, 0x02, 0x71, 0x65, 0xc7, + 0x4e, 0xc3, 0x5e, 0xb7, 0x70, 0x47, 0xe8, 0xda, 0xb7, 0xbc, 0xe8, 0xdb, 0xf7, 0x4b, 0xf4, 0xe3, 0x4d, 0xfb, 0xd9, + 0xa0, 0xdd, 0x3d, 0x6a, 0xcf, 0x50, 0x88, 0x40, 0x44, 0xaa, 0x82, 0x56, 0xf7, 0xe8, 0x08, 0x0a, 0xae, 0x9d, 0x82, + 0x0e, 0x14, 0x70, 0xa7, 0xe0, 0x11, 0x14, 0x8c, 0x9c, 0x82, 0xc7, 0x50, 0x10, 0x3b, 0x05, 0x4f, 0xa0, 0xe0, 0x0a, + 0x15, 0x03, 0x5e, 0x82, 0xfb, 0x04, 0x0f, 0x89, 0xb6, 0x5c, 0x6c, 0xd9, 0x13, 0xd2, 0x86, 0x10, 0x5e, 0x34, 0x51, + 0x99, 0x47, 0xe0, 0x10, 0x0c, 0x05, 0xb9, 0x9e, 0xb2, 0x34, 0x84, 0x20, 0xea, 0x73, 0x25, 0x63, 0x02, 0x29, 0xde, + 0xf3, 0x19, 0xb3, 0xdf, 0xcb, 0xb0, 0x78, 0xf0, 0x10, 0x1e, 0xb4, 0x86, 0x45, 0xb7, 0xdc, 0x39, 0x1d, 0xfb, 0x33, + 0x59, 0x28, 0x7a, 0x2f, 0xab, 0x3a, 0x3d, 0x5d, 0xb3, 0xdc, 0xf3, 0x1d, 0x31, 0x24, 0xc7, 0x17, 0x31, 0x4e, 0xc4, + 0x75, 0xf3, 0x06, 0xf5, 0xb6, 0xc7, 0x95, 0x00, 0xa2, 0x32, 0xae, 0xa4, 0xd6, 0x54, 0x3e, 0xbd, 0x8f, 0x26, 0xe5, + 0xef, 0xd7, 0x2c, 0xcf, 0xa3, 0x89, 0x69, 0xb9, 0x3b, 0x8e, 0xa4, 0x40, 0x74, 0x63, 0x48, 0x16, 0x08, 0x88, 0x05, + 0xc1, 0x66, 0x81, 0x2d, 0x6f, 0x42, 0x43, 0x80, 0x9d, 0x7a, 0x54, 0x49, 0x4d, 0x5f, 0x2f, 0x92, 0xd1, 0xa4, 0x2a, + 0x38, 0x9e, 0x67, 0x4c, 0x95, 0x6a, 0x0c, 0x17, 0xc7, 0x87, 0x50, 0xa0, 0xab, 0x77, 0x44, 0x8f, 0xac, 0xe3, 0x60, + 0x77, 0x0c, 0xc9, 0xb3, 0xd1, 0x23, 0x37, 0xdf, 0xa6, 0x4c, 0xb6, 0xd9, 0x8c, 0x59, 0x7c, 0xd6, 0x1e, 0xc1, 0x1f, + 0x13, 0x11, 0xf9, 0x6c, 0x3c, 0x1e, 0xdf, 0x19, 0x4d, 0xfa, 0x2c, 0x1e, 0xb3, 0x0e, 0x7b, 0xd4, 0x85, 0x5c, 0x8c, + 0xa6, 0x89, 0x41, 0xb4, 0x0b, 0x85, 0xbb, 0xe5, 0xfd, 0x1a, 0x43, 0xb8, 0x42, 0x4e, 0x97, 0xf7, 0x8f, 0x2c, 0x15, + 0xf3, 0x8c, 0x2d, 0x67, 0x51, 0x36, 0xe1, 0x69, 0xd8, 0x2a, 0x82, 0x2b, 0x13, 0x8a, 0xf9, 0xec, 0xe9, 0xd3, 0xa7, + 0x45, 0x10, 0xdb, 0xa7, 0x56, 0x1c, 0x17, 0xc1, 0x68, 0x59, 0x2e, 0xa3, 0xd5, 0x1a, 0x8f, 0x8b, 0x80, 0xdb, 0x82, + 0xa3, 0xce, 0x28, 0x3e, 0xea, 0x14, 0xc1, 0xb5, 0xd3, 0xa2, 0x08, 0x98, 0x79, 0xca, 0x58, 0x5c, 0x4b, 0xe8, 0x78, + 0xd2, 0x6a, 0x15, 0x81, 0x26, 0xb4, 0x25, 0x98, 0x63, 0xfa, 0x67, 0x18, 0x2d, 0xa4, 0x00, 0x96, 0xdc, 0x15, 0xd2, + 0x1f, 0x9c, 0x9b, 0x97, 0x65, 0xe8, 0x0f, 0x4b, 0x14, 0x78, 0x48, 0xbe, 0x74, 0x83, 0x26, 0x40, 0xcc, 0x2a, 0x58, + 0x22, 0x6c, 0x4c, 0xa5, 0x56, 0x0d, 0x94, 0xa5, 0xaa, 0xbf, 0xa4, 0xa2, 0x8a, 0xa5, 0x00, 0xff, 0x81, 0x96, 0xfa, + 0xad, 0x6e, 0x92, 0xed, 0xe0, 0xfa, 0x8c, 0x7d, 0x92, 0xeb, 0xdf, 0xde, 0x87, 0xe9, 0x33, 0xf6, 0x47, 0x33, 0x7d, + 0xf3, 0xea, 0x53, 0xcd, 0xf4, 0x35, 0x5b, 0x9b, 0x49, 0x8a, 0x46, 0x53, 0x36, 0xfa, 0x78, 0x29, 0x6e, 0x9a, 0x70, + 0x24, 0x32, 0xa4, 0xf8, 0xe9, 0xfe, 0x6f, 0x4d, 0xfe, 0xb0, 0x83, 0x39, 0xdf, 0xa5, 0x50, 0x62, 0xf3, 0x6d, 0x4a, + 0xd1, 0x5b, 0x6b, 0xd3, 0xe9, 0x92, 0xf1, 0x98, 0xa2, 0xb7, 0xe3, 0x31, 0xb2, 0x57, 0xfe, 0x22, 0xc9, 0x54, 0xab, + 0x37, 0xb5, 0x12, 0xd5, 0xea, 0x8b, 0x2f, 0xdc, 0x32, 0xb7, 0xc0, 0x84, 0x5c, 0xdc, 0xf0, 0x8a, 0xa9, 0x89, 0x79, + 0x0e, 0x47, 0x0d, 0x3e, 0x97, 0x51, 0x7f, 0xe7, 0x60, 0x56, 0x7b, 0x3d, 0x74, 0x09, 0xf0, 0x96, 0x77, 0x5a, 0xaf, + 0xdf, 0x77, 0x9f, 0x30, 0x9b, 0x7e, 0xf7, 0xec, 0xf6, 0xcb, 0xd8, 0x9f, 0x49, 0x5c, 0xf0, 0xfc, 0x6d, 0xba, 0x76, + 0x97, 0x45, 0xc3, 0x48, 0xa9, 0xbb, 0xac, 0x42, 0x8a, 0xc9, 0x24, 0x81, 0x0f, 0x96, 0x2c, 0x6b, 0xef, 0x41, 0xd5, + 0xdd, 0xfb, 0xb5, 0xf5, 0x86, 0x6e, 0x47, 0xf3, 0xd6, 0x50, 0xf5, 0xfd, 0x24, 0x9d, 0x03, 0x7d, 0x65, 0x3e, 0xa4, + 0xa3, 0xcc, 0xc1, 0xa5, 0xe1, 0xff, 0x4b, 0x9d, 0x39, 0x2b, 0x21, 0x6b, 0x44, 0x0f, 0x1c, 0x17, 0x85, 0xb9, 0x73, + 0x10, 0xf3, 0x7c, 0x0e, 0xef, 0xe7, 0xd4, 0x3d, 0xd9, 0xa7, 0x58, 0x78, 0x7e, 0xed, 0xc4, 0x35, 0x6a, 0xdb, 0x55, + 0xd8, 0xc0, 0x86, 0x76, 0x14, 0xcf, 0x64, 0x81, 0x8c, 0xbf, 0xd9, 0x22, 0x11, 0x79, 0x1a, 0x9f, 0x3a, 0xe2, 0xe2, + 0xac, 0x10, 0x9c, 0xbe, 0xe5, 0x86, 0xd8, 0x2a, 0x5b, 0x50, 0xb8, 0x71, 0x3b, 0x55, 0xa3, 0xb1, 0xa5, 0xa2, 0x04, + 0xf9, 0x3c, 0x4a, 0x35, 0x1b, 0xa5, 0x48, 0xf3, 0x83, 0xfd, 0x65, 0xb5, 0xf3, 0x05, 0xb2, 0x60, 0x6b, 0xe2, 0xed, + 0x1d, 0x1f, 0x42, 0x87, 0x9e, 0x57, 0x03, 0x3d, 0xdd, 0x08, 0x2e, 0x7c, 0x22, 0xcc, 0x7f, 0x11, 0xe4, 0xd7, 0x24, + 0xc8, 0xaf, 0xbd, 0x3f, 0x2f, 0x9b, 0xd7, 0xec, 0xf2, 0x23, 0x97, 0x4d, 0x19, 0xcd, 0x9b, 0xa0, 0xf0, 0x2b, 0xa7, + 0xa0, 0x61, 0xcf, 0x2a, 0x59, 0x4d, 0xdf, 0xd8, 0xef, 0x2e, 0x72, 0xc8, 0x06, 0x50, 0x6a, 0x6b, 0x98, 0x8a, 0x94, + 0x75, 0xeb, 0x49, 0x89, 0x6e, 0x70, 0xd9, 0x62, 0x6b, 0xb8, 0x14, 0x90, 0x3d, 0x20, 0x6f, 0xc3, 0x96, 0x61, 0xeb, + 0x2d, 0x1b, 0x39, 0x6e, 0x6d, 0x6d, 0x1f, 0x1a, 0xe4, 0x36, 0x94, 0xf4, 0xca, 0x36, 0x23, 0xe8, 0xbb, 0x22, 0xe0, + 0x9f, 0x4a, 0xd1, 0x03, 0x57, 0xa2, 0xfd, 0xeb, 0xe4, 0x36, 0xae, 0x17, 0xab, 0x14, 0xbd, 0xfb, 0x40, 0x16, 0x46, + 0x63, 0xc9, 0x32, 0x72, 0x9f, 0x96, 0x97, 0xea, 0x36, 0xcd, 0x12, 0xc4, 0x4c, 0xd8, 0x7e, 0x3a, 0xbf, 0xb9, 0xff, + 0xf0, 0x77, 0x2f, 0xbf, 0x30, 0x38, 0xb2, 0x6f, 0x97, 0x41, 0xa8, 0x0b, 0x07, 0x21, 0x89, 0x6e, 0x43, 0x9e, 0x2a, + 0x99, 0x77, 0x09, 0xfe, 0xc0, 0xee, 0x5c, 0x98, 0x5c, 0xd3, 0x8c, 0x25, 0xea, 0x53, 0x72, 0x66, 0x2b, 0x8e, 0x1e, + 0xcf, 0x6f, 0xec, 0x6e, 0xb4, 0xd7, 0x72, 0x48, 0xff, 0xd0, 0x54, 0xd1, 0xdd, 0xb9, 0xa9, 0xf5, 0x74, 0xc7, 0x47, + 0xf3, 0x9b, 0xae, 0x16, 0xb4, 0xcd, 0x4c, 0x43, 0xd5, 0x9a, 0xdf, 0xb8, 0xc9, 0xb2, 0xd5, 0x40, 0x5e, 0x70, 0x94, + 0x7b, 0x2c, 0xca, 0x59, 0x17, 0xde, 0x9f, 0xcd, 0x47, 0x51, 0x62, 0x84, 0xf9, 0x8c, 0xc7, 0x71, 0xc2, 0xba, 0x56, + 0x5e, 0x7b, 0xed, 0xc7, 0x90, 0x6b, 0xea, 0x6e, 0x59, 0x7d, 0x57, 0x1c, 0xe4, 0x95, 0x78, 0x8a, 0x2e, 0x73, 0x91, + 0xc0, 0xc7, 0x2b, 0xb6, 0xa2, 0xd3, 0x24, 0x61, 0xb6, 0x2a, 0xe4, 0xa9, 0xdf, 0xf5, 0xb5, 0x3c, 0x6a, 0xfd, 0xa9, + 0xab, 0x36, 0xbc, 0xd5, 0x95, 0x62, 0x1e, 0x36, 0x8f, 0xea, 0x0b, 0x81, 0xaa, 0x72, 0x09, 0x64, 0xcb, 0xb2, 0x08, + 0x48, 0x2b, 0xcd, 0xa7, 0xbd, 0xa0, 0x6d, 0xca, 0xd4, 0x00, 0xf0, 0xa2, 0xe7, 0xb2, 0xa8, 0xa8, 0x2f, 0xe6, 0xdf, + 0xe7, 0xb4, 0x7c, 0xbe, 0xfd, 0xb4, 0x7c, 0x6e, 0x4f, 0xcb, 0xdd, 0x14, 0xfb, 0xd9, 0xb8, 0x0d, 0x7f, 0xba, 0xd5, + 0x82, 0xc2, 0x96, 0x77, 0x34, 0xbf, 0xf1, 0x40, 0x4f, 0x6b, 0x76, 0xe6, 0x37, 0x3a, 0x55, 0x18, 0x62, 0x16, 0x2d, + 0x48, 0x9e, 0x25, 0x2d, 0x0f, 0x0a, 0xe1, 0x6f, 0xab, 0x56, 0xd5, 0x7e, 0x08, 0x75, 0xd0, 0xeb, 0xd1, 0x66, 0x5d, + 0xe7, 0xee, 0x43, 0x1b, 0xa6, 0x42, 0xfa, 0xa1, 0xe5, 0xc6, 0x38, 0x90, 0xd1, 0xe5, 0x25, 0x8b, 0xc3, 0xb1, 0x18, + 0x2d, 0xf2, 0x7f, 0x36, 0xf0, 0x1b, 0x24, 0xde, 0x79, 0xa4, 0xd7, 0xc6, 0xb1, 0x5d, 0x75, 0xe2, 0xb2, 0x1d, 0x61, + 0x59, 0xee, 0x53, 0x98, 0x8f, 0xa2, 0x84, 0xf9, 0x9d, 0xe0, 0xe1, 0x96, 0x43, 0xf0, 0x1f, 0xb2, 0x37, 0x5b, 0x17, + 0xf3, 0x7b, 0x91, 0x71, 0x27, 0x12, 0x7e, 0x15, 0x0e, 0xdc, 0x3d, 0x6c, 0x3d, 0xdd, 0x0e, 0xee, 0xc0, 0xce, 0x34, + 0xb4, 0x42, 0xc1, 0xc8, 0x9d, 0x98, 0x8d, 0xa3, 0x45, 0x22, 0xef, 0x1e, 0x75, 0x17, 0x65, 0x6c, 0x8c, 0x7a, 0x07, + 0x43, 0xaf, 0xda, 0xde, 0x93, 0x4b, 0x7f, 0xf6, 0xf9, 0x43, 0xf8, 0xa3, 0xf3, 0x9e, 0x6e, 0x2b, 0x5d, 0x5d, 0xdb, + 0xaa, 0xa0, 0xab, 0xef, 0xd7, 0x94, 0x71, 0x2d, 0xc2, 0x95, 0x3e, 0x7e, 0xdf, 0xd6, 0xa0, 0x55, 0xde, 0xab, 0xb9, + 0xd1, 0xb2, 0x7e, 0x55, 0xeb, 0x5f, 0x37, 0xf8, 0x3d, 0xdb, 0x8e, 0xb4, 0xe6, 0x5a, 0x6f, 0x6b, 0xbe, 0xa5, 0xb7, + 0xd1, 0xd8, 0x62, 0x5c, 0xb5, 0xdf, 0xa7, 0xb7, 0xa5, 0x89, 0xa2, 0xa3, 0x90, 0x60, 0xa5, 0xec, 0x6b, 0x2b, 0x85, + 0x33, 0xfa, 0x00, 0xde, 0x64, 0xeb, 0xdd, 0xcc, 0x92, 0x34, 0xa7, 0x68, 0x2a, 0xe5, 0x3c, 0xd4, 0x1f, 0x5f, 0xbd, + 0x3e, 0x0a, 0x44, 0x36, 0x39, 0xec, 0xb4, 0x5a, 0x2d, 0x78, 0x03, 0x29, 0xf2, 0xae, 0x38, 0xbb, 0x7e, 0x26, 0x6e, + 0x28, 0x7a, 0xe2, 0x3d, 0xf5, 0x9e, 0x1c, 0x79, 0x8f, 0x1e, 0x23, 0x4f, 0xb1, 0x73, 0x8a, 0x9e, 0x1c, 0x21, 0x4f, + 0xb3, 0x73, 0x8a, 0x1e, 0x3d, 0x46, 0xbd, 0xe3, 0x89, 0x55, 0xc9, 0xe0, 0x0a, 0xa3, 0xd6, 0x77, 0x72, 0x99, 0x89, + 0x8f, 0xac, 0x7e, 0x70, 0x75, 0x99, 0xc9, 0x8c, 0xeb, 0xd8, 0x47, 0x38, 0xbd, 0xa3, 0x68, 0x1e, 0x2a, 0xa2, 0x70, + 0x0b, 0xc1, 0x2d, 0xa3, 0x4b, 0xd5, 0x14, 0xa0, 0x66, 0x5e, 0xa2, 0xde, 0x31, 0x64, 0xb1, 0x7b, 0x31, 0x45, 0xaf, + 0x3b, 0x4f, 0xbc, 0xf6, 0xe3, 0xab, 0xe6, 0xc3, 0x51, 0xab, 0xd9, 0xf6, 0xda, 0xcd, 0x4e, 0xf0, 0xc4, 0xeb, 0xe8, + 0x7f, 0xbd, 0x96, 0x77, 0xe4, 0xb5, 0x83, 0x27, 0xde, 0x91, 0xd7, 0x09, 0x9e, 0x5c, 0x3d, 0xd4, 0xc9, 0x0c, 0x11, + 0x3a, 0xec, 0x1d, 0xc3, 0x87, 0x34, 0x6f, 0x28, 0xfa, 0x1c, 0xe9, 0xcf, 0xd5, 0xa2, 0xcf, 0xdc, 0xd2, 0xf6, 0xd3, + 0xad, 0xc5, 0x9d, 0x27, 0x5b, 0x8b, 0x8f, 0x1e, 0x6f, 0x2d, 0x7e, 0xf8, 0xa8, 0x5e, 0x7c, 0x38, 0xd1, 0x55, 0xe5, + 0x29, 0xa7, 0x68, 0x16, 0xc9, 0x8c, 0xdf, 0xf8, 0x6d, 0xaf, 0xe5, 0xb5, 0xbc, 0x26, 0xfc, 0xf7, 0xa4, 0x83, 0xcb, + 0x5e, 0x97, 0xd0, 0xab, 0x5c, 0xe5, 0x93, 0xa7, 0x5e, 0xfb, 0xf1, 0xcb, 0xce, 0xe3, 0x11, 0xb4, 0x53, 0x0b, 0x6d, + 0x7b, 0xed, 0xab, 0xa3, 0xa7, 0xa3, 0x96, 0x07, 0x1d, 0xdb, 0xf0, 0x67, 0xfa, 0xa8, 0x33, 0xd2, 0x0f, 0x2d, 0xa8, + 0xff, 0xb6, 0xfd, 0x24, 0x6f, 0x35, 0xdb, 0xf0, 0xe7, 0x97, 0x52, 0x23, 0x06, 0x7d, 0xdc, 0x1d, 0xf7, 0x61, 0xcb, + 0x3b, 0x7a, 0x3a, 0xed, 0x04, 0x9f, 0x5f, 0x3d, 0x09, 0x9e, 0x4e, 0xdb, 0x4f, 0xbe, 0xd5, 0x4f, 0x49, 0xb3, 0x13, + 0x7c, 0x0e, 0x7f, 0xbf, 0x3d, 0x6a, 0x4d, 0x9b, 0xed, 0xe0, 0xe9, 0xd5, 0x51, 0x70, 0x94, 0x34, 0x1f, 0x07, 0x4f, + 0xe1, 0x6f, 0x35, 0xdc, 0x54, 0xcc, 0x18, 0xf2, 0x60, 0xbf, 0xd7, 0xcc, 0x2d, 0x77, 0x8e, 0xce, 0x43, 0xef, 0xd1, + 0xc3, 0x97, 0x4f, 0xaf, 0x9a, 0x0f, 0xa7, 0xed, 0xce, 0x55, 0x73, 0xe7, 0xcf, 0x6f, 0x01, 0xf1, 0x66, 0xe0, 0x88, + 0xc1, 0x75, 0x22, 0x8b, 0x38, 0xf5, 0x36, 0xdc, 0x07, 0x24, 0xdf, 0x65, 0x5e, 0x67, 0x9f, 0x36, 0xaf, 0x53, 0x76, + 0x1f, 0xfb, 0x3a, 0xfb, 0xc3, 0xed, 0xeb, 0x9c, 0xad, 0x39, 0x55, 0x6f, 0xe5, 0x86, 0x19, 0xbd, 0x6e, 0x7b, 0xbd, + 0x93, 0xfe, 0x80, 0xc3, 0x57, 0x97, 0x8a, 0xee, 0x2d, 0xbc, 0x70, 0xdb, 0xf5, 0x36, 0x08, 0x38, 0xc8, 0xb7, 0x52, + 0x9f, 0x64, 0xb1, 0x0b, 0x21, 0xc9, 0xa7, 0x11, 0xf2, 0xed, 0x7d, 0xf0, 0x91, 0xfc, 0xe1, 0xf8, 0x10, 0x2e, 0x3e, + 0x6a, 0x7e, 0x5e, 0x65, 0xcf, 0x2a, 0x7b, 0xf4, 0x4c, 0x3d, 0xfb, 0x70, 0xe3, 0xa4, 0x81, 0x0e, 0x19, 0x14, 0xe5, + 0x48, 0xc7, 0x15, 0x5e, 0xfe, 0x1a, 0x97, 0xb4, 0xbe, 0x5e, 0x46, 0x91, 0x31, 0xfe, 0xe7, 0xf0, 0x65, 0x05, 0xfb, + 0x70, 0xa5, 0x2f, 0x3c, 0x53, 0xd4, 0x09, 0x5a, 0x41, 0xab, 0x74, 0x1c, 0xc0, 0x95, 0x42, 0xba, 0x14, 0x32, 0x82, + 0x8f, 0x7b, 0x26, 0x62, 0xa2, 0x3e, 0x03, 0x0a, 0x2f, 0x5f, 0x57, 0x1f, 0x64, 0xd5, 0xef, 0xbd, 0x0f, 0x11, 0x32, + 0x2f, 0x22, 0x80, 0x2b, 0x6b, 0xdf, 0xc0, 0xb5, 0x3e, 0xeb, 0xb1, 0x9e, 0x81, 0x4d, 0xfd, 0x9a, 0xc5, 0x3c, 0xf2, + 0x91, 0x3f, 0xcf, 0xd8, 0x98, 0x65, 0x79, 0xb3, 0x76, 0xd7, 0x4d, 0x5d, 0x73, 0xc3, 0xc8, 0x7e, 0x46, 0x32, 0x83, + 0x97, 0x09, 0xd3, 0x81, 0xf1, 0x6a, 0x21, 0xa3, 0xe6, 0xa3, 0x82, 0xd8, 0x92, 0x0c, 0x38, 0x7a, 0xa5, 0x1a, 0x20, + 0xad, 0x1b, 0xb4, 0x83, 0xce, 0x23, 0xac, 0x79, 0x09, 0xbc, 0xa4, 0xf5, 0x7b, 0xbf, 0x79, 0xd4, 0xfa, 0x13, 0x76, + 0xba, 0x95, 0x03, 0x0d, 0x8d, 0x53, 0x27, 0xab, 0x3e, 0xbf, 0x5b, 0xbf, 0x88, 0x88, 0x34, 0x45, 0x7c, 0xa6, 0xd7, + 0x0e, 0xaf, 0x7b, 0x35, 0xf1, 0x43, 0x7d, 0x9d, 0x7e, 0xcc, 0x27, 0xbe, 0xfb, 0x71, 0x55, 0xfd, 0x12, 0x58, 0xf5, + 0x4d, 0x66, 0x5c, 0x54, 0x4d, 0x32, 0xbc, 0x54, 0xbe, 0x78, 0x9e, 0x7a, 0xd9, 0x6a, 0xe5, 0x67, 0xe0, 0x88, 0xa5, + 0x0e, 0x4e, 0xe1, 0x19, 0xd7, 0x90, 0x9c, 0x91, 0x12, 0x20, 0x85, 0x60, 0x9a, 0xe9, 0xff, 0xab, 0x62, 0xfb, 0xc3, + 0xb8, 0x57, 0x82, 0x24, 0x4a, 0x27, 0x40, 0x85, 0x51, 0x3a, 0xd9, 0x70, 0xde, 0xe8, 0x70, 0xc2, 0x5a, 0x69, 0x35, + 0x54, 0xe5, 0xa4, 0xc9, 0x9f, 0xdd, 0xbe, 0x37, 0x6f, 0x8b, 0x42, 0xe0, 0x03, 0x55, 0xbe, 0xef, 0xea, 0xcd, 0xb6, + 0x0d, 0xfa, 0x40, 0x7f, 0xae, 0x5c, 0x65, 0xc3, 0x81, 0xf4, 0x83, 0x2b, 0x86, 0x9e, 0xb1, 0x79, 0x28, 0xd2, 0xb2, + 0x2f, 0x66, 0x57, 0x7c, 0x64, 0x44, 0x18, 0xf1, 0xcc, 0x35, 0xeb, 0xa6, 0xda, 0x1a, 0xda, 0x26, 0xda, 0xea, 0x1f, + 0x45, 0x2a, 0xdf, 0x99, 0xa6, 0x02, 0xf5, 0x1e, 0x94, 0xdf, 0x8a, 0xdc, 0xb5, 0x09, 0xf0, 0x0d, 0xf5, 0x41, 0xc6, + 0x92, 0x7f, 0xa6, 0x0f, 0xe0, 0x2b, 0xea, 0x0f, 0x86, 0xf0, 0x01, 0xef, 0x40, 0x89, 0x82, 0x07, 0xd5, 0xc7, 0xd4, + 0x81, 0x0f, 0x36, 0x6e, 0x66, 0x09, 0xb9, 0xaf, 0xf8, 0x36, 0xa2, 0xba, 0xf3, 0xa8, 0x12, 0xd5, 0x9d, 0x47, 0xae, + 0xf4, 0x6c, 0x7b, 0xed, 0x4e, 0xf0, 0xc8, 0x11, 0x00, 0x57, 0x4d, 0xf8, 0xbf, 0x26, 0x02, 0x1e, 0x06, 0x8f, 0x4a, + 0x19, 0xf0, 0xaa, 0xdd, 0x09, 0x8e, 0xb4, 0xb8, 0xe9, 0x04, 0x8f, 0x7e, 0x50, 0x0c, 0x5a, 0x33, 0xe7, 0xfa, 0x81, + 0xd8, 0x12, 0xaa, 0xd1, 0x19, 0x7d, 0x88, 0xf8, 0xe5, 0x17, 0xe9, 0xcc, 0xf9, 0x34, 0x2e, 0xa1, 0xe7, 0x51, 0x06, + 0x9f, 0x05, 0xa9, 0x9f, 0xdd, 0x5a, 0x1d, 0xa9, 0xf1, 0x8b, 0x2d, 0x53, 0xc0, 0x09, 0x47, 0xc4, 0xbd, 0xa7, 0x0c, + 0x97, 0x7c, 0xd5, 0x4b, 0x94, 0xed, 0xbb, 0xe4, 0x76, 0x93, 0xb6, 0x6e, 0x68, 0xdf, 0x57, 0xa7, 0x98, 0x05, 0x57, + 0x2f, 0xac, 0x57, 0x93, 0x7c, 0x19, 0x17, 0xeb, 0xf3, 0x43, 0x62, 0x61, 0x26, 0x9c, 0xab, 0xda, 0xac, 0x4a, 0x87, + 0x8f, 0x39, 0x5c, 0xae, 0x2f, 0x0a, 0x0b, 0x7a, 0xcd, 0x19, 0x58, 0x61, 0x49, 0xf1, 0x0b, 0x96, 0xf7, 0x11, 0x14, + 0xa1, 0x10, 0x29, 0x47, 0x12, 0x2a, 0x3f, 0x8d, 0x52, 0x12, 0x76, 0x55, 0x40, 0xd4, 0x95, 0x16, 0x38, 0xb5, 0x80, + 0x1f, 0x84, 0x0f, 0x0e, 0x76, 0x9e, 0x17, 0xa5, 0x8d, 0xc1, 0x5a, 0xab, 0x4f, 0x2a, 0xb8, 0xac, 0x08, 0xb9, 0x88, + 0x2e, 0xc7, 0x55, 0x28, 0xc4, 0x06, 0x4f, 0x97, 0x2c, 0x92, 0x41, 0x94, 0xea, 0x14, 0x05, 0x87, 0x61, 0x91, 0x36, + 0x3b, 0xc2, 0x85, 0x90, 0x91, 0xf3, 0xcd, 0x54, 0x73, 0xce, 0x85, 0x8c, 0xec, 0xc5, 0xc3, 0x54, 0xd6, 0x32, 0xf3, + 0xa7, 0x9d, 0xde, 0xdb, 0xf7, 0x27, 0x9e, 0x3e, 0x9e, 0xc7, 0x87, 0xd3, 0x4e, 0xef, 0x58, 0x59, 0xe6, 0xfa, 0xda, + 0x12, 0xd5, 0xd7, 0x96, 0x3c, 0x73, 0x85, 0x0d, 0xe2, 0x35, 0xc5, 0xa1, 0x5e, 0x36, 0xf2, 0x58, 0x3a, 0xd2, 0x3e, + 0xc5, 0xd9, 0x22, 0x91, 0x1c, 0x5e, 0x08, 0x7c, 0x08, 0x5d, 0x9b, 0xb0, 0x61, 0x65, 0x96, 0xab, 0xd5, 0x70, 0x64, + 0x6a, 0x3d, 0x90, 0x63, 0x9e, 0x30, 0x9b, 0xd7, 0x6a, 0x86, 0x2a, 0xf3, 0xb0, 0x37, 0x5b, 0xe7, 0x8b, 0xcb, 0x19, + 0x97, 0xc8, 0x66, 0x8b, 0x7f, 0x30, 0x1d, 0x8e, 0xd5, 0x54, 0xbd, 0x8b, 0xc2, 0xb8, 0x48, 0xed, 0xc7, 0x4f, 0xd6, + 0x3e, 0x37, 0xaf, 0x57, 0x6f, 0x24, 0x04, 0xdc, 0x3f, 0x9a, 0x1e, 0xf5, 0x4a, 0xa7, 0xa4, 0x5b, 0x57, 0x1c, 0x1f, + 0x4e, 0x8f, 0x7a, 0x17, 0xe1, 0xdc, 0x8c, 0xf7, 0x4a, 0x6c, 0x7c, 0xba, 0xbe, 0xe4, 0x98, 0x7d, 0x95, 0x68, 0xaf, + 0x6f, 0x74, 0x1a, 0x80, 0x47, 0x22, 0x41, 0xbd, 0x63, 0xa3, 0x0c, 0x78, 0x2a, 0xe8, 0x8a, 0x1e, 0xb5, 0x6c, 0xee, + 0x7e, 0x22, 0x94, 0xb6, 0xa4, 0xbb, 0x38, 0x93, 0xd4, 0xfc, 0xba, 0xd3, 0x76, 0xef, 0x38, 0x32, 0x6a, 0x26, 0x30, + 0x8f, 0x3c, 0x3c, 0x84, 0xce, 0xa0, 0xcb, 0x05, 0x5c, 0x1c, 0x5e, 0xb3, 0xcb, 0x66, 0x34, 0xe7, 0x95, 0x13, 0x15, + 0x94, 0x8e, 0x72, 0x4a, 0x51, 0xcd, 0x04, 0x3f, 0xa3, 0xb5, 0x45, 0x2a, 0x16, 0x5e, 0x18, 0x0f, 0xad, 0xd2, 0xd5, + 0x59, 0x24, 0x91, 0xa7, 0x39, 0xbc, 0xf5, 0xe4, 0x1a, 0xd9, 0x5b, 0xa0, 0xde, 0xbf, 0xfd, 0x8f, 0xff, 0x65, 0x9c, + 0xb3, 0xc7, 0x87, 0xd3, 0xb6, 0x1d, 0x6b, 0x0d, 0xd1, 0xc5, 0x31, 0x5c, 0x77, 0xab, 0xa2, 0x89, 0xec, 0xa6, 0x39, + 0xc9, 0x78, 0xdc, 0x9c, 0x46, 0xc9, 0x18, 0xf5, 0x76, 0x23, 0xc8, 0xbd, 0xe7, 0x62, 0xa0, 0xae, 0x17, 0x01, 0x09, + 0xfe, 0xa6, 0x9b, 0x1a, 0x36, 0xe1, 0x5f, 0x9d, 0x56, 0xf7, 0xde, 0x46, 0x75, 0xa0, 0x6a, 0x77, 0x37, 0x32, 0xf3, + 0x8d, 0x24, 0xc3, 0xd4, 0xb2, 0xda, 0x95, 0x8d, 0x02, 0x79, 0x65, 0x34, 0xe4, 0xff, 0xfe, 0xcf, 0xff, 0xf2, 0xdf, + 0xec, 0x23, 0x04, 0x39, 0xfe, 0xed, 0xbf, 0xff, 0xe7, 0xff, 0xf3, 0xbf, 0xff, 0x2b, 0xa4, 0xf9, 0x9b, 0x40, 0x88, + 0xe2, 0x13, 0x5e, 0x15, 0x05, 0xd1, 0x0c, 0xc3, 0x83, 0x4c, 0xb8, 0x19, 0xcf, 0x25, 0x1f, 0xd5, 0x2f, 0x71, 0x9c, + 0xa9, 0x09, 0xd5, 0x61, 0x33, 0xd0, 0xa9, 0x43, 0x5b, 0x54, 0x34, 0x52, 0x43, 0xb9, 0xa2, 0xc5, 0xe2, 0xf8, 0x10, + 0xf0, 0x7d, 0xbf, 0x7b, 0x6f, 0x41, 0xb9, 0x1d, 0x4b, 0xeb, 0xfa, 0x83, 0x92, 0xa2, 0x2a, 0xf7, 0xc0, 0x29, 0xbf, + 0x84, 0xc7, 0xb0, 0xe3, 0x14, 0xab, 0xdd, 0xab, 0xf5, 0xe9, 0xfe, 0xb4, 0xc8, 0x25, 0x1f, 0x03, 0xca, 0xb5, 0x83, + 0x51, 0xc5, 0x3f, 0x9b, 0xa0, 0xfe, 0x25, 0xb7, 0x85, 0x1a, 0x45, 0xdb, 0x8c, 0x0f, 0x9f, 0xfe, 0xa9, 0xf8, 0xcb, + 0x0c, 0x94, 0x2c, 0xcf, 0x9f, 0x45, 0x37, 0xc6, 0x92, 0x7c, 0xdc, 0x6a, 0xcd, 0x6f, 0xf0, 0xb2, 0x9a, 0x81, 0xec, + 0x9a, 0x4c, 0x39, 0x25, 0xdd, 0x01, 0x55, 0xe0, 0xb4, 0xf4, 0x7f, 0xb6, 0x3c, 0x70, 0xa2, 0x7a, 0xad, 0xa2, 0xf8, + 0xf3, 0x52, 0xb9, 0xe0, 0xf8, 0x2f, 0x10, 0xe0, 0x34, 0xde, 0xca, 0x4b, 0xe1, 0x2e, 0x6e, 0xe9, 0xf4, 0xea, 0xe8, + 0x5e, 0xd3, 0xf6, 0xe6, 0x75, 0x2e, 0x37, 0x40, 0xeb, 0x86, 0x56, 0x1f, 0x42, 0xb0, 0x74, 0xda, 0x26, 0xd3, 0xce, + 0xb2, 0x1c, 0x5e, 0x4a, 0x31, 0x73, 0x23, 0xb2, 0x2c, 0x62, 0x23, 0x36, 0xb6, 0x5e, 0x5e, 0x53, 0xaf, 0xa3, 0xad, + 0xc5, 0xf4, 0x68, 0xcb, 0x5c, 0x06, 0x24, 0x15, 0x89, 0xf5, 0x5a, 0xc5, 0x67, 0x70, 0x02, 0x97, 0xe3, 0x44, 0x44, + 0x32, 0x54, 0x04, 0xdb, 0x75, 0xe3, 0xba, 0x11, 0xb0, 0x19, 0xb1, 0x74, 0xe0, 0xe9, 0xea, 0xa6, 0xe0, 0x6f, 0xad, + 0x5f, 0xba, 0x2b, 0x02, 0xd5, 0xdd, 0x1d, 0x4a, 0xbb, 0x6b, 0xbe, 0x35, 0xe1, 0xd2, 0x97, 0x35, 0x3f, 0x87, 0x91, + 0x31, 0x1d, 0xbc, 0xbd, 0x5e, 0x8b, 0x6a, 0x5d, 0xfb, 0x95, 0xf4, 0x91, 0x02, 0x13, 0xad, 0xb7, 0x52, 0x85, 0xd0, + 0xea, 0x25, 0xfd, 0xb6, 0xb4, 0x82, 0xa2, 0xf9, 0x5c, 0x35, 0xc4, 0xdd, 0xe3, 0x43, 0xad, 0xbc, 0x02, 0xf7, 0x50, + 0xb9, 0x00, 0x3a, 0xf4, 0x6e, 0x1a, 0x99, 0xa3, 0xa0, 0x7f, 0x99, 0xa0, 0x3c, 0x7c, 0x3c, 0xab, 0xf7, 0xff, 0x00, + 0x08, 0x50, 0x84, 0x3d, 0xcd, 0x86, 0x00, 0x00}; } // namespace web_server } // namespace esphome diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index f2f278b08f..f649a9385e 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -3632,366 +3632,367 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe7, 0xec, 0xd8, 0x98, 0x31, 0x94, 0x4f, 0x43, 0x40, 0x9e, 0xd0, 0xf7, 0x01, 0xcd, 0x25, 0x67, 0x23, 0xad, 0x2b, 0xfb, 0x10, 0x17, 0x97, 0xdc, 0x84, 0x6a, 0x31, 0x6f, 0x2b, 0x3d, 0x2a, 0xc4, 0x1b, 0x16, 0x80, 0x65, 0xe9, 0x69, 0x93, 0x82, 0x6c, 0x94, 0x54, 0x45, 0xfe, 0x13, 0xbf, 0x03, 0xae, 0xad, 0xac, 0xe4, 0x0a, 0x78, 0xf5, 0xff, 0xd3, - 0xdc, 0xb3, 0x2e, 0xb7, 0x6d, 0x5c, 0xfd, 0xbf, 0x4f, 0x01, 0xc3, 0xae, 0x03, 0xd8, 0x00, 0x04, 0x90, 0xa2, 0x28, - 0x93, 0x22, 0x95, 0xc4, 0x76, 0xa6, 0xea, 0x28, 0x71, 0xc6, 0x56, 0x3d, 0x6d, 0x14, 0x8d, 0x08, 0x82, 0x4b, 0x12, - 0x35, 0x08, 0x60, 0x00, 0x50, 0xa2, 0x42, 0xa3, 0xcf, 0xd2, 0x67, 0xe9, 0x93, 0x7d, 0x73, 0xce, 0x5e, 0xb0, 0xb8, - 0x91, 0x54, 0xec, 0xb4, 0xdf, 0xa4, 0xaa, 0x89, 0xc5, 0xee, 0x62, 0xf7, 0xec, 0xee, 0xd9, 0x73, 0x3f, 0xee, 0x82, - 0xc9, 0x5e, 0x0c, 0x8d, 0x1c, 0xf6, 0xb9, 0xcf, 0x9f, 0x89, 0x85, 0x5b, 0x12, 0x08, 0x3e, 0x2b, 0x8b, 0x16, 0x8b, - 0x80, 0x68, 0x2a, 0x4f, 0x1e, 0xa2, 0x1a, 0xe2, 0x33, 0xe7, 0x4f, 0x6c, 0x1e, 0xb1, 0x53, 0xcf, 0xdb, 0x8e, 0x16, - 0x9f, 0x31, 0x11, 0x21, 0xed, 0x28, 0xe5, 0x8a, 0xb2, 0xd9, 0x3b, 0x54, 0x6f, 0xb0, 0x75, 0x29, 0x8e, 0xae, 0x39, - 0x8b, 0xd6, 0xd3, 0x80, 0x98, 0xb8, 0xdd, 0xe1, 0x93, 0xdb, 0xe9, 0x7a, 0x3a, 0x85, 0x2c, 0x2d, 0x4f, 0x6c, 0x03, - 0xe2, 0xce, 0x44, 0x29, 0xf2, 0x83, 0xb9, 0x3e, 0x84, 0x49, 0x59, 0x59, 0x75, 0xf8, 0x60, 0x2b, 0x02, 0xa2, 0x1e, - 0xfa, 0x81, 0x0c, 0x78, 0xbf, 0x86, 0x53, 0x3b, 0x52, 0x3f, 0xc0, 0xee, 0x4b, 0xd5, 0x61, 0xd3, 0xd1, 0x1f, 0x5d, - 0xab, 0x1f, 0x10, 0xc6, 0x98, 0xbd, 0xf8, 0x35, 0xdd, 0xbd, 0xaa, 0xa1, 0x52, 0xa5, 0xf7, 0x1a, 0xf3, 0x18, 0x80, - 0xd0, 0xf7, 0x8d, 0xef, 0x2e, 0xc2, 0x28, 0xcd, 0x7c, 0x4f, 0xbd, 0x19, 0x5e, 0xf8, 0xda, 0xf5, 0x2a, 0xd3, 0xf4, - 0x1b, 0xc3, 0xcb, 0xe4, 0x14, 0x28, 0x1c, 0x61, 0x62, 0x06, 0x94, 0xb6, 0x4a, 0xf2, 0x09, 0xda, 0x59, 0x91, 0xa3, - 0x66, 0xac, 0xe4, 0x65, 0x23, 0xa8, 0x57, 0xc9, 0xa7, 0x82, 0x89, 0xa1, 0x54, 0x6c, 0xa9, 0x0f, 0x29, 0xa7, 0xf2, - 0x7a, 0xbd, 0xc5, 0xab, 0x3c, 0x2b, 0x6e, 0x4b, 0x8c, 0x01, 0xcc, 0x1d, 0x67, 0xe8, 0xf3, 0x13, 0xd9, 0xe8, 0xb3, - 0x74, 0xef, 0x4e, 0xbe, 0x2b, 0xd3, 0x05, 0x70, 0x7f, 0x83, 0xc5, 0x45, 0x18, 0x65, 0x0a, 0x04, 0xb6, 0x81, 0x2f, - 0x4e, 0xaa, 0x46, 0x62, 0xac, 0x57, 0x4d, 0xcf, 0x19, 0x32, 0xf8, 0x1e, 0x2f, 0x3f, 0x8d, 0x85, 0x37, 0x2b, 0x45, - 0xb0, 0xa0, 0xcc, 0x42, 0x08, 0x0b, 0x98, 0x45, 0x97, 0xd1, 0x7d, 0x55, 0x0f, 0xf2, 0x7a, 0xb2, 0xff, 0xee, 0xd5, - 0x38, 0x99, 0xcc, 0xb3, 0xfa, 0x69, 0x2c, 0x31, 0x29, 0x27, 0x74, 0x2a, 0x67, 0x0a, 0x0d, 0x3f, 0x38, 0x0d, 0x93, - 0x81, 0x9d, 0x18, 0xde, 0x05, 0x80, 0x92, 0xd8, 0x35, 0x3d, 0xc9, 0x6f, 0x79, 0xea, 0x64, 0x9e, 0xb8, 0x58, 0xba, - 0x9c, 0x01, 0xbb, 0x86, 0xf1, 0x3a, 0xc3, 0x50, 0xbb, 0x30, 0x00, 0x92, 0xab, 0x0a, 0x86, 0xee, 0x04, 0x2c, 0x5d, - 0x90, 0x89, 0xb9, 0xaa, 0xf8, 0xb3, 0x7a, 0x19, 0x23, 0x7a, 0x01, 0x79, 0x21, 0x7e, 0x47, 0x41, 0x15, 0x3c, 0x26, - 0x6c, 0x1a, 0x9e, 0x51, 0xc4, 0xa9, 0xd7, 0x3c, 0x54, 0xe8, 0x34, 0x60, 0x06, 0x8f, 0xf6, 0x33, 0xd4, 0x82, 0xc6, - 0xc9, 0x42, 0xf8, 0xcd, 0xd2, 0x34, 0x27, 0xcf, 0xb6, 0x61, 0x7e, 0xfe, 0x6c, 0x9b, 0xe6, 0xa3, 0x67, 0x5b, 0x17, - 0x28, 0xb9, 0x5c, 0x85, 0x89, 0x16, 0x8e, 0x3a, 0xc5, 0xf4, 0x60, 0x53, 0xd1, 0x72, 0x05, 0x35, 0xf5, 0x23, 0xa6, - 0x8f, 0x8f, 0x13, 0x7f, 0xe5, 0x26, 0x0f, 0x54, 0x7d, 0x6f, 0xc8, 0x3a, 0x7e, 0x5d, 0x55, 0x28, 0x5e, 0xa7, 0xf3, - 0xa5, 0x28, 0x5e, 0x55, 0xbe, 0x15, 0x65, 0x84, 0x4d, 0x4e, 0xe8, 0x30, 0xe1, 0x5b, 0xb7, 0xea, 0x4b, 0x62, 0xcd, - 0x48, 0xe6, 0xfa, 0x01, 0x6d, 0x32, 0xe4, 0xc9, 0xe9, 0x6b, 0xb3, 0x49, 0xcb, 0xb3, 0x09, 0xcb, 0xdb, 0x05, 0x27, - 0x43, 0x31, 0x3e, 0x1d, 0x37, 0xce, 0x0c, 0x93, 0x56, 0x35, 0x2f, 0x20, 0x7d, 0xf7, 0x5f, 0x85, 0x3e, 0x01, 0xe8, - 0x87, 0x00, 0x7d, 0x12, 0x7a, 0xd1, 0x8c, 0xfc, 0xed, 0xfd, 0x85, 0xc8, 0x92, 0x05, 0x02, 0x9f, 0x09, 0xdb, 0x87, - 0x29, 0x92, 0x0b, 0x09, 0x92, 0x0a, 0x34, 0x9f, 0x95, 0x22, 0x76, 0x4c, 0x92, 0xab, 0xca, 0x39, 0x1d, 0x3b, 0x99, - 0xd1, 0x51, 0x8f, 0x22, 0x6c, 0x95, 0xe4, 0x67, 0x47, 0xb4, 0x36, 0xbd, 0xdc, 0x68, 0x25, 0x00, 0x43, 0x02, 0x33, - 0x2c, 0xa0, 0x00, 0x09, 0x3d, 0x47, 0x4e, 0xc1, 0x3f, 0x58, 0x2b, 0x14, 0xab, 0x3b, 0xe7, 0x65, 0xca, 0x04, 0x5b, - 0xa9, 0xe3, 0x33, 0x4c, 0xd1, 0x05, 0xd7, 0x33, 0x04, 0xf5, 0x38, 0x3b, 0xa2, 0x8f, 0x4a, 0xe5, 0x00, 0x14, 0x9d, - 0x70, 0x4e, 0x6e, 0xc0, 0x3a, 0x78, 0xd4, 0xc9, 0x80, 0x8c, 0xf0, 0x50, 0xea, 0xe6, 0xaa, 0xb2, 0x62, 0x94, 0x10, - 0x8b, 0x1e, 0x04, 0xa1, 0x05, 0x6c, 0x38, 0xaa, 0xaa, 0xb2, 0x72, 0x37, 0x38, 0x73, 0xfe, 0xc6, 0xdd, 0x68, 0x0e, - 0x7b, 0x55, 0x1c, 0xad, 0xb4, 0x7c, 0xb4, 0x3c, 0xb6, 0xb8, 0xe0, 0x37, 0x20, 0x18, 0xe9, 0x25, 0xea, 0x63, 0x1b, - 0x16, 0x77, 0xc9, 0x17, 0x77, 0xd6, 0xb2, 0xb8, 0xb3, 0x1d, 0x8b, 0x1b, 0xb0, 0x85, 0x54, 0x04, 0xe8, 0x12, 0xf4, - 0x05, 0x13, 0xc0, 0x63, 0x74, 0xc5, 0x80, 0x9d, 0x33, 0x84, 0x93, 0x99, 0x06, 0x60, 0x0b, 0xd5, 0x02, 0xab, 0x26, - 0xb8, 0x48, 0x80, 0xa8, 0x4f, 0x5c, 0x9c, 0x3a, 0x3e, 0x6f, 0x48, 0xb9, 0xa9, 0x05, 0xd5, 0xf9, 0xc2, 0x2e, 0xa5, - 0xe9, 0xc4, 0xb5, 0x65, 0xcb, 0x4c, 0x97, 0x3b, 0x66, 0xea, 0x95, 0x8e, 0x2e, 0x9b, 0x36, 0x3d, 0x84, 0xf2, 0xa4, - 0x60, 0x0f, 0x82, 0x7d, 0x28, 0x6e, 0x99, 0xf2, 0x3e, 0x6c, 0x47, 0xa9, 0xd2, 0x8e, 0x8a, 0xdd, 0x34, 0xbd, 0x8f, - 0x12, 0x50, 0xb0, 0x40, 0x37, 0x8f, 0xdb, 0x52, 0x2b, 0x3f, 0x64, 0xb1, 0x5b, 0x5a, 0x37, 0x53, 0xf1, 0x5e, 0xde, - 0x52, 0x9d, 0x5e, 0x8f, 0xd6, 0x88, 0xdd, 0x2c, 0x23, 0x09, 0x02, 0xdd, 0x85, 0x20, 0xdf, 0xff, 0x4f, 0xb6, 0x59, - 0x03, 0x0e, 0x09, 0xf4, 0x02, 0xab, 0x23, 0x86, 0x8e, 0x81, 0x94, 0x4a, 0xf8, 0xbd, 0x2b, 0xc5, 0x81, 0x4b, 0x04, - 0xe0, 0x7f, 0xc2, 0xe3, 0xaa, 0x25, 0x92, 0xa7, 0x92, 0x73, 0xa2, 0x5b, 0xb1, 0x3b, 0xfb, 0x00, 0x7a, 0x3c, 0xad, - 0x63, 0x80, 0x4d, 0xae, 0x1c, 0xf5, 0x2d, 0xa1, 0xb4, 0x9d, 0x57, 0x20, 0x49, 0xc4, 0x92, 0xcc, 0xe2, 0x09, 0x9c, - 0x25, 0x5d, 0x73, 0x7e, 0xb3, 0xed, 0xe4, 0x47, 0x0b, 0x5f, 0xaf, 0x61, 0x4d, 0x40, 0x6d, 0xc1, 0x68, 0x2c, 0x58, - 0xac, 0xc0, 0x70, 0x4e, 0x74, 0x10, 0xf4, 0x5e, 0x43, 0xfa, 0x52, 0x9b, 0xf3, 0xaf, 0x93, 0x04, 0x2e, 0xa9, 0x6b, - 0xfb, 0x26, 0x7f, 0xbe, 0xc0, 0x5f, 0xce, 0x4d, 0xfe, 0x7c, 0x8a, 0xbf, 0x3a, 0x37, 0x98, 0xa8, 0xae, 0x81, 0x6f, - 0x97, 0xe6, 0xac, 0x8e, 0x4b, 0xfb, 0x89, 0x9a, 0x9b, 0x3d, 0x62, 0xdb, 0xb0, 0x05, 0x7e, 0xfa, 0x6c, 0x9b, 0x82, - 0x83, 0xa5, 0x3c, 0x87, 0xd0, 0x4a, 0xf4, 0xbc, 0xb1, 0x7c, 0xd1, 0x52, 0x3e, 0xd5, 0xff, 0xcb, 0xf7, 0x3c, 0xee, - 0x92, 0xa8, 0xb8, 0x53, 0xca, 0x52, 0x87, 0xdb, 0xa9, 0x1f, 0xba, 0xc9, 0xc3, 0x2d, 0xe5, 0x26, 0x34, 0x4e, 0xaa, - 0x0b, 0x69, 0x0a, 0xa5, 0x26, 0xcb, 0xda, 0xad, 0x4c, 0x92, 0xe7, 0x3e, 0xb0, 0x8b, 0x7e, 0xf4, 0xf7, 0x44, 0xa2, - 0xd2, 0x4a, 0xfc, 0x26, 0x5b, 0x90, 0xd2, 0x87, 0x6e, 0x9f, 0x6d, 0x35, 0x52, 0xef, 0xa6, 0x32, 0xdb, 0x0a, 0x19, - 0x08, 0xcb, 0x83, 0xbc, 0xeb, 0x6a, 0xe6, 0x0f, 0x50, 0x7d, 0x35, 0x8d, 0x36, 0xe6, 0xb3, 0x6d, 0x76, 0xae, 0xae, - 0xdc, 0xe4, 0x13, 0x99, 0x99, 0x9e, 0x9f, 0x78, 0x01, 0x51, 0x07, 0xea, 0x34, 0x70, 0xc3, 0x4f, 0xec, 0xd1, 0x8c, - 0xd6, 0x19, 0x2a, 0xa4, 0xf7, 0xb2, 0xba, 0x1c, 0x26, 0x54, 0x42, 0x87, 0xb4, 0x69, 0x03, 0x14, 0x94, 0xd7, 0x42, - 0xbe, 0x55, 0xd0, 0x85, 0x45, 0x2d, 0x03, 0xec, 0x29, 0x41, 0x47, 0x0e, 0x0e, 0xaa, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, - 0xf2, 0x54, 0xa9, 0x6c, 0x52, 0x64, 0x58, 0xbc, 0xc5, 0x1e, 0x7e, 0xff, 0xe7, 0x68, 0xee, 0xeb, 0xc3, 0x3f, 0xc7, - 0x68, 0xbc, 0xf6, 0x0f, 0xca, 0x8d, 0xdd, 0x34, 0x5d, 0xaf, 0xc8, 0x8c, 0xea, 0xe2, 0xce, 0x8b, 0xa1, 0x94, 0x69, - 0x79, 0x79, 0x38, 0xbf, 0xae, 0x3b, 0xfd, 0xe3, 0xd7, 0x60, 0x23, 0x00, 0x34, 0x5d, 0x34, 0x9f, 0xab, 0x05, 0x57, - 0xbd, 0xa7, 0x99, 0x73, 0xfc, 0xeb, 0xfa, 0x87, 0xb7, 0xf6, 0x0f, 0xa2, 0x71, 0xa8, 0xea, 0xf9, 0x84, 0x2b, 0x3c, - 0x19, 0x69, 0x2a, 0x8d, 0x97, 0xcf, 0x68, 0xee, 0x86, 0xed, 0xd3, 0xb9, 0x2e, 0xed, 0xb2, 0x98, 0x90, 0x19, 0xd8, - 0xc2, 0x1a, 0xb5, 0xd2, 0xdb, 0x80, 0xdc, 0x11, 0xa1, 0x4c, 0xad, 0x7f, 0xac, 0xa1, 0x05, 0x46, 0x7b, 0x63, 0x4a, - 0x5a, 0x46, 0x58, 0x49, 0x53, 0x9a, 0xe0, 0x1c, 0xd8, 0xcc, 0xe5, 0x5d, 0x5e, 0xd9, 0xd5, 0x13, 0x43, 0x95, 0x06, - 0xd0, 0x3a, 0xb2, 0xf3, 0x96, 0xf2, 0x01, 0xa6, 0x7a, 0x6e, 0x1e, 0x9b, 0xe1, 0xe8, 0x03, 0x88, 0x8e, 0xcd, 0xe0, - 0x14, 0xc0, 0xe6, 0xd7, 0x0a, 0x01, 0x44, 0x1b, 0xc4, 0x9a, 0xc4, 0x52, 0x2a, 0x95, 0x77, 0x70, 0xfb, 0x42, 0x34, - 0xb4, 0xe5, 0x92, 0x9f, 0xc6, 0xb5, 0x51, 0xca, 0x33, 0x9f, 0x62, 0x0a, 0xd5, 0x90, 0xa4, 0x69, 0x2b, 0xc0, 0xc4, - 0xa2, 0x1b, 0x6a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0xb0, 0x0d, 0xb8, 0x95, 0x71, 0x82, 0xd5, 0x6f, 0x21, 0x86, - 0xbf, 0x5d, 0x31, 0x0b, 0x91, 0x64, 0x31, 0x55, 0x99, 0xf6, 0xbe, 0xed, 0xfd, 0xbd, 0xca, 0x06, 0x55, 0xba, 0x29, - 0x1b, 0x87, 0xa6, 0x95, 0xb0, 0x5f, 0x4d, 0x40, 0x83, 0x1d, 0xf0, 0x31, 0x55, 0x50, 0x1c, 0x99, 0xcf, 0x89, 0x97, - 0xa5, 0x3a, 0x17, 0xd7, 0x88, 0x78, 0xad, 0xe0, 0xa7, 0xf3, 0x64, 0xa4, 0xfe, 0x04, 0x5e, 0xeb, 0x3c, 0xac, 0x11, - 0x1b, 0x10, 0x67, 0x5b, 0x9a, 0xc1, 0x44, 0x7b, 0x2c, 0x83, 0x88, 0x7d, 0x05, 0xd2, 0x71, 0x37, 0x94, 0xe3, 0xd0, - 0xd8, 0x15, 0x50, 0xec, 0x8b, 0x48, 0xd8, 0x91, 0xec, 0x46, 0x40, 0xbb, 0x8e, 0xef, 0xd6, 0xf9, 0xa1, 0xe7, 0xd8, - 0xb9, 0x6a, 0x80, 0xb7, 0xd4, 0xa7, 0x43, 0x0f, 0x3d, 0xb6, 0xea, 0x42, 0xab, 0x75, 0xf8, 0x98, 0x76, 0x1d, 0xe7, - 0x95, 0xa3, 0x1a, 0xd4, 0x48, 0x4d, 0xc2, 0x6d, 0x5e, 0x74, 0x47, 0x92, 0x2f, 0x9e, 0x4a, 0xb9, 0xf3, 0xc3, 0xc6, - 0x73, 0xe2, 0xd8, 0x80, 0x84, 0xb3, 0x28, 0x7e, 0xc4, 0x14, 0xba, 0xaa, 0xa1, 0x7a, 0x41, 0x94, 0x12, 0x79, 0x0e, - 0x54, 0xec, 0xf0, 0x85, 0x93, 0xf8, 0xf9, 0xfd, 0xdb, 0x0f, 0x1f, 0x54, 0x03, 0x73, 0x6f, 0xa6, 0x72, 0xef, 0x6c, - 0x43, 0xed, 0xc1, 0xfe, 0x8d, 0xfb, 0x8e, 0xde, 0x30, 0x94, 0xaf, 0x2c, 0xef, 0x39, 0x5a, 0x56, 0xdb, 0x72, 0xec, - 0xe6, 0x61, 0x5f, 0xa6, 0xcc, 0xe0, 0x41, 0xf3, 0x6a, 0xc0, 0x0d, 0xbb, 0xaf, 0xb7, 0x52, 0xc9, 0xca, 0x0f, 0x6f, - 0x1b, 0x4a, 0xdd, 0x4d, 0x43, 0x29, 0x70, 0x53, 0x35, 0x5c, 0xb5, 0x8e, 0x56, 0xd2, 0xed, 0x0c, 0xa9, 0x93, 0xf7, - 0x81, 0x4b, 0x62, 0x69, 0xbe, 0x60, 0xd0, 0x2c, 0x76, 0x7a, 0x75, 0xd4, 0x0d, 0xc5, 0x8c, 0x0f, 0x11, 0xb0, 0xf5, - 0x02, 0x30, 0xb1, 0x23, 0xb2, 0x1e, 0xac, 0x4c, 0xb9, 0x09, 0x03, 0x59, 0xa9, 0x13, 0x4a, 0x61, 0xde, 0x66, 0x64, - 0x15, 0x93, 0xc4, 0xcd, 0xd6, 0x09, 0xb9, 0x0d, 0xa2, 0xfb, 0x27, 0x85, 0x01, 0xfb, 0x9e, 0xca, 0x4b, 0x7f, 0xb1, - 0x14, 0xb5, 0xcf, 0x35, 0x32, 0x12, 0x0b, 0xb8, 0xf3, 0x03, 0xf9, 0x7f, 0xfe, 0x6d, 0x59, 0xff, 0xf9, 0xf7, 0xde, - 0xaa, 0xd0, 0x7d, 0x3e, 0x31, 0xb2, 0xd1, 0x01, 0xfb, 0xa2, 0xf9, 0x4b, 0x65, 0x98, 0x37, 0xd7, 0xa9, 0x2d, 0x02, - 0xbc, 0xaf, 0x2d, 0x41, 0xad, 0xb0, 0xbc, 0x6f, 0x1e, 0x35, 0x30, 0x98, 0xd7, 0xde, 0x91, 0x41, 0xa5, 0x2f, 0x1a, - 0xda, 0x44, 0x1f, 0x1c, 0xb4, 0x22, 0xbf, 0x1f, 0xc2, 0xfb, 0xe6, 0xf0, 0x85, 0xc3, 0x67, 0xa2, 0xc1, 0xd7, 0x93, - 0x89, 0xc8, 0xe6, 0x26, 0x37, 0x05, 0xa3, 0xfa, 0xf3, 0x5a, 0x09, 0xbb, 0x3c, 0x07, 0xb6, 0x4e, 0xbd, 0xdd, 0x47, - 0xaf, 0x27, 0x68, 0xfe, 0x75, 0x36, 0x4d, 0x0a, 0x62, 0xa5, 0x15, 0xb5, 0x51, 0xf3, 0xed, 0x5a, 0xa7, 0x35, 0xbc, - 0x06, 0xa5, 0x98, 0xe2, 0x2b, 0x9f, 0xe8, 0xc6, 0xeb, 0x09, 0x93, 0xed, 0x30, 0x8b, 0xd3, 0x41, 0x75, 0x6b, 0x33, - 0xc9, 0x68, 0x09, 0xe8, 0x86, 0x42, 0x35, 0x2e, 0x58, 0x99, 0x14, 0xa2, 0x34, 0x14, 0xa9, 0x03, 0x53, 0x3f, 0xc9, - 0x31, 0xc3, 0xc8, 0xbb, 0x36, 0xab, 0xac, 0x9f, 0xf7, 0x5b, 0x65, 0x5d, 0x1d, 0x64, 0x95, 0xf5, 0xf3, 0x57, 0xb7, - 0xca, 0x7a, 0x27, 0x5b, 0x65, 0xc1, 0x22, 0xbe, 0x25, 0x07, 0x99, 0x4a, 0x71, 0x3b, 0x89, 0xe8, 0x3e, 0x1d, 0x39, - 0x8c, 0xa4, 0x4d, 0xbd, 0x25, 0x01, 0x36, 0x9d, 0xad, 0x4a, 0x10, 0x2d, 0xc0, 0x6c, 0xea, 0x8f, 0x37, 0x70, 0x0a, - 0xa2, 0x85, 0x6c, 0xde, 0x14, 0xb2, 0x18, 0xab, 0x45, 0xdc, 0x24, 0x6a, 0x52, 0x64, 0x1b, 0x3c, 0xca, 0x92, 0x79, - 0xac, 0x4b, 0x79, 0xa4, 0x85, 0xbd, 0x58, 0x87, 0x1b, 0x1d, 0x0d, 0xd0, 0x5e, 0x49, 0x34, 0xec, 0xbc, 0xe4, 0xd1, - 0x24, 0xe4, 0x1e, 0x84, 0x5d, 0x2e, 0x8d, 0xcc, 0xb0, 0x55, 0x7f, 0xdd, 0x38, 0xdf, 0x5f, 0x3b, 0xc3, 0xae, 0x03, - 0xee, 0xd0, 0xc0, 0xe4, 0x61, 0x81, 0x3d, 0xec, 0x76, 0xa1, 0xe0, 0x5e, 0x2a, 0xe8, 0x40, 0x81, 0x2f, 0x15, 0xf4, - 0xa0, 0xc0, 0x93, 0x0a, 0x4e, 0xa0, 0x60, 0x26, 0x15, 0xf4, 0xa1, 0xe0, 0x4e, 0xcd, 0xaf, 0x43, 0x31, 0xdc, 0xbe, - 0x7e, 0x63, 0x50, 0xa6, 0x82, 0x97, 0xf5, 0x0d, 0x07, 0xec, 0x94, 0xdc, 0xc5, 0x20, 0x32, 0xa8, 0x80, 0x6f, 0x90, - 0x18, 0xf7, 0x4b, 0x42, 0x43, 0x33, 0xbf, 0xc1, 0x3b, 0xc7, 0xca, 0x22, 0xb0, 0x54, 0xe6, 0x21, 0x0f, 0x38, 0x1c, - 0x14, 0x55, 0x07, 0x99, 0xcd, 0x50, 0xac, 0x1c, 0x0f, 0x1b, 0x21, 0xad, 0x65, 0xf1, 0x8e, 0x7e, 0xce, 0x14, 0x5b, - 0xa0, 0xb0, 0xf1, 0xd0, 0x64, 0xc1, 0xe0, 0xd7, 0xd0, 0xf4, 0xbf, 0x21, 0xd3, 0xf5, 0x42, 0xb9, 0x8c, 0x16, 0x7b, - 0x95, 0xf6, 0xf2, 0x2b, 0x18, 0xa5, 0x4a, 0x35, 0x20, 0x26, 0xdf, 0x96, 0xec, 0x5b, 0xf4, 0x31, 0x2f, 0xd7, 0xcf, - 0x60, 0x6c, 0x4a, 0x46, 0x4d, 0x46, 0xe0, 0x3b, 0x00, 0x23, 0x49, 0x6b, 0x7e, 0x09, 0x70, 0x96, 0x9e, 0xaf, 0x5c, - 0x69, 0x3c, 0xe3, 0x1f, 0x49, 0x9a, 0xba, 0x0b, 0x5e, 0xbf, 0x3e, 0x4e, 0x30, 0x93, 0x11, 0xfc, 0x17, 0x02, 0x10, - 0x84, 0x69, 0x7e, 0xcd, 0x1a, 0x22, 0x89, 0xee, 0x15, 0xb0, 0xb7, 0x81, 0x0d, 0x55, 0x58, 0x06, 0xf8, 0x16, 0x2c, - 0x61, 0x59, 0x87, 0x0f, 0x87, 0xff, 0x8e, 0x04, 0xd5, 0xc2, 0xcc, 0x5d, 0x54, 0x8b, 0xe8, 0x3e, 0xc8, 0xe5, 0xb1, - 0x09, 0x15, 0x7a, 0xa9, 0xf0, 0x4b, 0x74, 0xc2, 0x41, 0xb4, 0xf8, 0x43, 0x15, 0xc2, 0x3b, 0x14, 0xf9, 0x1f, 0x42, - 0xc3, 0xcf, 0x26, 0x16, 0xc2, 0x58, 0xb1, 0x00, 0x84, 0x83, 0x30, 0x5b, 0x9a, 0xe8, 0xcc, 0xa5, 0x75, 0x42, 0xdd, - 0xb0, 0x70, 0x6d, 0xb7, 0x55, 0x17, 0xd6, 0x41, 0xb2, 0x98, 0xba, 0x9a, 0xd3, 0xe9, 0x1b, 0xfc, 0xcf, 0xb2, 0x7b, - 0x7a, 0x8e, 0x3d, 0x28, 0x33, 0xff, 0x6e, 0x3b, 0x8f, 0xc2, 0xcc, 0x9c, 0xbb, 0x2b, 0x3f, 0x78, 0x18, 0xac, 0xa2, - 0x30, 0x4a, 0x63, 0xd7, 0x23, 0xc3, 0x82, 0xa1, 0x1e, 0x62, 0x70, 0x04, 0xe6, 0x9f, 0xe7, 0x58, 0x9d, 0x84, 0xac, - 0x68, 0x6b, 0x11, 0xfb, 0x60, 0x1e, 0x90, 0x4d, 0xce, 0x3e, 0x5f, 0xaa, 0x4c, 0xab, 0xe2, 0x96, 0xa3, 0x2d, 0x80, - 0x22, 0x65, 0x81, 0x15, 0x20, 0x9c, 0xd0, 0x30, 0x76, 0x67, 0x18, 0x0b, 0xd0, 0xea, 0xf4, 0x12, 0xb2, 0x52, 0xac, - 0x5e, 0x6b, 0xe7, 0x49, 0x74, 0x3f, 0x86, 0xd1, 0x62, 0x63, 0x33, 0x25, 0xc1, 0x1c, 0xdf, 0x98, 0xe8, 0xcb, 0xc1, - 0xfb, 0x31, 0x91, 0x11, 0x87, 0xde, 0xc8, 0x6a, 0x08, 0xaf, 0x07, 0x1d, 0xc5, 0x1e, 0xae, 0xfc, 0xd0, 0xa4, 0xd3, - 0xe9, 0xdb, 0xb1, 0xd4, 0x97, 0x0c, 0x3f, 0x7d, 0x8b, 0xd5, 0x1d, 0xc5, 0x1e, 0x02, 0xb3, 0x36, 0x0f, 0xa2, 0xfb, - 0xc1, 0xd2, 0x9f, 0xcd, 0x48, 0x38, 0xc4, 0x31, 0x8b, 0x42, 0x12, 0x04, 0x7e, 0x9c, 0xfa, 0xe9, 0x70, 0xe5, 0x6e, - 0x58, 0xaf, 0xc7, 0x6d, 0xbd, 0x76, 0x59, 0xaf, 0xdd, 0x83, 0x7b, 0x95, 0xba, 0x01, 0xbf, 0x11, 0xda, 0x0f, 0x1b, - 0x5a, 0x4f, 0xb1, 0x2b, 0xf3, 0x3c, 0xb8, 0xd7, 0x38, 0x21, 0xdb, 0x95, 0x9b, 0x2c, 0xfc, 0x70, 0x60, 0xe7, 0xd6, - 0xdd, 0x96, 0x6e, 0x8c, 0xa7, 0xa7, 0xa7, 0xa7, 0xb9, 0x35, 0xe3, 0x4f, 0xf6, 0x6c, 0x96, 0x5b, 0x1e, 0x7f, 0x9a, - 0xcf, 0x6d, 0x7b, 0x3e, 0xcf, 0x2d, 0x9f, 0x17, 0x74, 0x3b, 0xde, 0xac, 0xdb, 0xc9, 0xad, 0x7b, 0xa9, 0x46, 0x6e, - 0x11, 0xf6, 0x94, 0x90, 0xd9, 0x10, 0x37, 0x12, 0x35, 0xe4, 0x1c, 0xf4, 0x6d, 0x3b, 0x47, 0x0c, 0x70, 0x5d, 0xc2, - 0x4d, 0x28, 0xeb, 0xb9, 0xd9, 0x1e, 0x5c, 0x53, 0x29, 0x3e, 0xe7, 0x79, 0x8d, 0xf5, 0x66, 0x6e, 0xf2, 0xe9, 0x46, - 0x91, 0x66, 0xe1, 0xba, 0xb4, 0xda, 0x96, 0x83, 0xc1, 0xdc, 0x0c, 0x20, 0x48, 0xd6, 0x70, 0x1a, 0x25, 0x70, 0x66, - 0x13, 0x77, 0xe6, 0xaf, 0xd3, 0x81, 0xd3, 0x89, 0x37, 0xbc, 0x88, 0xed, 0xf5, 0xa2, 0x00, 0xcf, 0xde, 0x20, 0x8d, - 0x02, 0x7f, 0xc6, 0x8b, 0xda, 0xce, 0x92, 0xd3, 0xd1, 0x87, 0xe8, 0x22, 0xee, 0x63, 0xa0, 0x03, 0x37, 0x08, 0x14, - 0xab, 0x9b, 0x2a, 0xc4, 0x4d, 0x51, 0xc4, 0xab, 0xd8, 0x29, 0x85, 0x0b, 0xba, 0x83, 0x3b, 0xc7, 0xf1, 0x46, 0xec, - 0x79, 0xe7, 0x24, 0xde, 0xe4, 0xdf, 0xae, 0xc8, 0xcc, 0x77, 0x15, 0xad, 0xd8, 0x4d, 0x8e, 0x0d, 0x62, 0x60, 0x7d, - 0xdb, 0xb2, 0x4d, 0xf9, 0xb1, 0x80, 0x60, 0x82, 0x4f, 0xfc, 0x55, 0x1c, 0x25, 0x99, 0x1b, 0x66, 0x79, 0x3e, 0xb9, - 0xc9, 0xf3, 0xe1, 0x95, 0xaf, 0x5d, 0xff, 0x43, 0xa3, 0xf7, 0x34, 0x55, 0x9b, 0xe4, 0xfa, 0x8d, 0xf1, 0x96, 0xc8, - 0x56, 0x1a, 0x70, 0x8d, 0xa1, 0x85, 0x86, 0x5c, 0x99, 0xde, 0x92, 0xf5, 0xca, 0x14, 0xc8, 0xa2, 0x3a, 0xb5, 0xfa, - 0x28, 0x57, 0xc1, 0x1b, 0x08, 0x2a, 0xbc, 0x25, 0xa3, 0x2b, 0xc9, 0xe2, 0x03, 0x88, 0x15, 0xac, 0x4c, 0x2d, 0xf9, - 0x9f, 0xb5, 0xd1, 0x8c, 0xdf, 0xed, 0xa7, 0x19, 0x7f, 0xc9, 0x0e, 0xa1, 0x19, 0xbf, 0xfb, 0xea, 0x34, 0xe3, 0xb3, - 0xba, 0x25, 0xff, 0x45, 0x34, 0x52, 0x85, 0x90, 0x1f, 0xae, 0xa6, 0x84, 0xc6, 0xc8, 0xb9, 0xf8, 0xdd, 0x86, 0xf7, - 0xbc, 0x37, 0x9a, 0xf5, 0x8d, 0xde, 0xdc, 0x20, 0x8f, 0x7d, 0x17, 0x8e, 0xfe, 0x9e, 0xc8, 0xcf, 0xf3, 0xf9, 0xe8, - 0x4d, 0x24, 0x15, 0x88, 0x27, 0x66, 0xff, 0x50, 0x8a, 0x67, 0x40, 0xdf, 0x70, 0xbb, 0x47, 0xcc, 0xf8, 0x00, 0xee, - 0xd0, 0xd4, 0xce, 0x77, 0x26, 0xec, 0xbd, 0x86, 0xe5, 0x21, 0x68, 0xc2, 0xc8, 0x92, 0x3b, 0xbd, 0xd4, 0x44, 0x89, - 0x0b, 0x92, 0x31, 0x2f, 0xd5, 0xef, 0x1f, 0x2e, 0x66, 0xda, 0x45, 0xa4, 0xe7, 0x7e, 0xfa, 0xae, 0xea, 0x72, 0xc2, - 0xd4, 0x2f, 0x23, 0x79, 0x3a, 0x39, 0xb3, 0xd9, 0x92, 0x53, 0x3a, 0xc3, 0x6b, 0xda, 0xfc, 0xbc, 0x34, 0xd3, 0x81, - 0xdc, 0x90, 0xa5, 0x96, 0xaa, 0x5d, 0xc6, 0xcc, 0xde, 0x7f, 0xcb, 0x28, 0x40, 0xcc, 0x96, 0x85, 0x9e, 0xba, 0x33, - 0xda, 0xdc, 0x9f, 0xe5, 0xb9, 0x3e, 0xe4, 0x80, 0x90, 0x2e, 0x5a, 0xb2, 0x8f, 0x88, 0x4b, 0xef, 0x85, 0x59, 0x01, - 0x53, 0xd2, 0x51, 0x0d, 0xdc, 0x05, 0xe8, 0xb4, 0x99, 0xbe, 0x8e, 0xc1, 0x4c, 0x55, 0x28, 0xf8, 0xa8, 0xad, 0x83, - 0x34, 0x21, 0x50, 0xc2, 0x0a, 0xf8, 0xf3, 0x57, 0xbc, 0xa0, 0x6e, 0x35, 0x49, 0x81, 0x83, 0x4a, 0x79, 0xf0, 0xab, - 0xe7, 0x72, 0x6d, 0x8a, 0x76, 0x58, 0x1d, 0x7c, 0xc8, 0x55, 0x41, 0xfb, 0xe1, 0xf6, 0x1b, 0x9f, 0x1d, 0x41, 0x83, - 0x71, 0x45, 0x77, 0xbf, 0xc7, 0x26, 0x10, 0x48, 0x89, 0xf4, 0xde, 0xb0, 0xd2, 0x7b, 0xe5, 0xc5, 0x96, 0xc7, 0xa4, - 0xc8, 0xdc, 0xd8, 0x04, 0x16, 0x1f, 0x71, 0x2f, 0xc3, 0x78, 0x52, 0xf8, 0x8b, 0xe1, 0x3a, 0x05, 0xdc, 0x88, 0x8c, - 0x2a, 0xe2, 0x9f, 0xa1, 0xb7, 0x4e, 0xd2, 0x28, 0x19, 0xc4, 0x91, 0x1f, 0x66, 0x24, 0xc9, 0x11, 0x54, 0xd7, 0x08, - 0x1f, 0x0e, 0x9e, 0x9b, 0x6d, 0x14, 0xbb, 0x9e, 0x9f, 0x3d, 0x0c, 0x6c, 0x46, 0x52, 0xd8, 0x43, 0x46, 0x1d, 0xd8, - 0x8d, 0xf5, 0x07, 0x0c, 0x9a, 0x2f, 0x91, 0xf0, 0x4b, 0xea, 0xe4, 0x8c, 0xbc, 0xcd, 0x87, 0xd2, 0x5b, 0x1a, 0x95, - 0x03, 0xc8, 0x0f, 0x37, 0x31, 0x17, 0x80, 0xe5, 0x61, 0xa9, 0xed, 0x19, 0x59, 0x18, 0x88, 0xb5, 0x41, 0x2e, 0xcf, - 0xff, 0xac, 0x9e, 0xae, 0xd8, 0xcd, 0xc5, 0x40, 0xf1, 0xe8, 0x87, 0x8c, 0x6c, 0xe0, 0x42, 0x0e, 0x2b, 0xe3, 0x90, - 0x9a, 0x53, 0x32, 0x8f, 0x12, 0x42, 0x23, 0xb8, 0x3a, 0xa7, 0xf1, 0xe6, 0xf0, 0xee, 0x77, 0x4f, 0xbf, 0xb9, 0x9f, - 0x30, 0xca, 0x34, 0xde, 0x99, 0xbe, 0xa7, 0xb7, 0xfa, 0x7d, 0x06, 0xa4, 0x21, 0x85, 0xbc, 0x47, 0x83, 0x65, 0x0d, - 0x54, 0x75, 0xd8, 0x18, 0x28, 0x2b, 0x8e, 0xd8, 0x9d, 0x97, 0x90, 0xc0, 0xcd, 0xfc, 0x3b, 0x4e, 0x33, 0x76, 0x4f, - 0xe2, 0x0d, 0x5f, 0x63, 0xbc, 0xf0, 0x1e, 0xb1, 0x48, 0x95, 0xa1, 0xf0, 0x45, 0xaa, 0x16, 0xe3, 0x22, 0x0d, 0x6b, - 0xb3, 0xe1, 0xb1, 0x23, 0x2a, 0x37, 0x7d, 0x2f, 0xde, 0xc8, 0x57, 0x74, 0xd1, 0x4c, 0xdc, 0xd4, 0xd5, 0xa0, 0x5f, - 0x2b, 0x7f, 0x36, 0x0b, 0x48, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x4a, 0xc0, 0x11, 0x70, 0x70, 0xa7, 0x69, 0x14, 0xac, - 0x33, 0xd2, 0x0c, 0x2e, 0x0a, 0x9c, 0x8e, 0x5d, 0x00, 0x07, 0x7f, 0x97, 0xc7, 0xda, 0x03, 0x72, 0x1b, 0xb6, 0x89, - 0x3d, 0x84, 0x18, 0xbf, 0x66, 0xb7, 0x3c, 0x74, 0x78, 0x25, 0x06, 0x6d, 0x34, 0x4c, 0xc4, 0x80, 0x6b, 0x89, 0x62, - 0x6f, 0xc5, 0x72, 0x58, 0x99, 0x88, 0x73, 0x2a, 0x8a, 0xf2, 0xf2, 0x64, 0xfe, 0x98, 0x33, 0xf6, 0xaa, 0xf9, 0x8c, - 0xbd, 0xe2, 0x67, 0x6c, 0xf7, 0xce, 0x7c, 0x3a, 0x77, 0xe0, 0xbf, 0x61, 0x31, 0xa1, 0x81, 0xad, 0x74, 0xe3, 0x8d, - 0xe2, 0xc4, 0x1b, 0xc5, 0xec, 0xc4, 0x1b, 0x05, 0xbb, 0x46, 0x93, 0x0c, 0xc3, 0xea, 0xe8, 0x86, 0xad, 0x40, 0x21, - 0xfc, 0xd9, 0xa5, 0x57, 0xce, 0x31, 0xbc, 0x83, 0x56, 0xbd, 0xfa, 0xbb, 0xce, 0xee, 0xa3, 0x4e, 0xcf, 0x12, 0x47, - 0xda, 0xba, 0x95, 0xb9, 0xd3, 0x29, 0x99, 0x0d, 0xe6, 0x91, 0xb7, 0x4e, 0xff, 0xc5, 0xc6, 0xcf, 0x80, 0xb8, 0x13, - 0x11, 0x54, 0xfa, 0xe1, 0x4d, 0x41, 0x51, 0x72, 0x47, 0x78, 0x0f, 0x5b, 0xb1, 0x4e, 0x03, 0x1a, 0x90, 0xb8, 0x63, - 0x1d, 0x37, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xd4, 0x8e, 0x62, 0xbe, 0x00, 0x2c, 0x3b, 0xc1, 0xf1, 0x78, - 0x68, 0xb0, 0xd5, 0xb4, 0x4f, 0x9b, 0x87, 0x7b, 0xcd, 0xbf, 0x74, 0xc3, 0x2f, 0x15, 0x76, 0x6f, 0x31, 0x57, 0x90, - 0xdd, 0xbd, 0xb6, 0xed, 0x91, 0x5a, 0xaf, 0x3b, 0x2e, 0x84, 0xa2, 0xee, 0x81, 0x58, 0xfe, 0xe9, 0xab, 0x63, 0xf8, - 0x8f, 0x52, 0xf5, 0xbf, 0x64, 0x4d, 0x84, 0xfa, 0x45, 0xd9, 0xf6, 0x9a, 0x92, 0x4a, 0x48, 0x88, 0x1f, 0x5e, 0x7f, - 0x3e, 0x7f, 0x5c, 0x83, 0x83, 0x6b, 0x53, 0x6b, 0xa6, 0x6a, 0xed, 0xef, 0xa3, 0x08, 0x92, 0x65, 0xd6, 0xab, 0x73, - 0xf0, 0x50, 0xf3, 0xf2, 0x6c, 0x04, 0x8d, 0x38, 0x1f, 0x41, 0xb5, 0xf8, 0x2a, 0xb6, 0xa1, 0xac, 0xc4, 0xdb, 0x36, - 0x56, 0xe2, 0xcd, 0x7e, 0x56, 0xe2, 0xaf, 0x07, 0xb1, 0x12, 0x6f, 0xbe, 0x3a, 0x2b, 0xf1, 0xb6, 0xce, 0x4a, 0x5c, - 0x45, 0xdc, 0x84, 0xd5, 0xb8, 0x58, 0xb3, 0x9f, 0x1f, 0xa9, 0x52, 0xee, 0x32, 0x1a, 0xf5, 0x6c, 0x1a, 0x64, 0xf8, - 0xea, 0x77, 0x33, 0x16, 0xb8, 0x11, 0xdf, 0xa3, 0x45, 0x57, 0xc1, 0x5a, 0x30, 0xcc, 0x8e, 0xdf, 0x91, 0x8a, 0x83, - 0x28, 0x5c, 0xfc, 0x0c, 0x4a, 0x59, 0x10, 0x07, 0x26, 0xd2, 0x0b, 0x3f, 0xfd, 0x39, 0x8a, 0xd7, 0xf1, 0x05, 0xf4, - 0xf5, 0xd1, 0x4f, 0xfd, 0x69, 0x40, 0x84, 0xef, 0x2f, 0xb5, 0x40, 0x63, 0x32, 0x71, 0x30, 0xfa, 0xe4, 0x3f, 0xdd, - 0x0d, 0xff, 0x89, 0x66, 0xa1, 0xec, 0x37, 0x35, 0x6d, 0x53, 0x9b, 0x19, 0x11, 0xae, 0x04, 0x94, 0x06, 0xfd, 0x78, - 0x66, 0xe4, 0x2a, 0xd2, 0x1b, 0x66, 0xc9, 0xed, 0x1d, 0x5a, 0xfb, 0x21, 0x35, 0xa6, 0x66, 0xad, 0x1b, 0x22, 0xe8, - 0x55, 0x5d, 0x0c, 0xbf, 0x8a, 0xd6, 0x29, 0x99, 0x45, 0xf7, 0xa1, 0x6a, 0x84, 0xc2, 0xac, 0x1f, 0x34, 0x9c, 0xa2, - 0x0d, 0xa6, 0x6b, 0xfc, 0x80, 0x84, 0x72, 0x94, 0x68, 0x2a, 0x64, 0x0b, 0x5d, 0xc7, 0x26, 0x55, 0x35, 0x9b, 0x38, - 0x45, 0x55, 0xe4, 0x15, 0x7a, 0xa2, 0x69, 0xd1, 0xe8, 0x71, 0x2d, 0xb9, 0xa9, 0x46, 0x64, 0x31, 0xa9, 0x70, 0xaa, - 0x85, 0x5c, 0xb8, 0xc8, 0x23, 0x4f, 0x34, 0x2c, 0x1c, 0x7b, 0x43, 0x9d, 0x45, 0x8b, 0xb7, 0x10, 0xb7, 0x23, 0x5f, - 0xb3, 0xf5, 0x60, 0x71, 0x18, 0xe8, 0xe3, 0x6b, 0x09, 0x8c, 0xef, 0xee, 0x48, 0x12, 0xb8, 0x0f, 0x9a, 0x9e, 0x47, - 0xe1, 0x8f, 0x00, 0x80, 0x37, 0xd1, 0x7d, 0x28, 0x57, 0xc0, 0xf4, 0x28, 0x0d, 0x7b, 0xa9, 0x31, 0x62, 0x08, 0xb8, - 0x8a, 0x48, 0x23, 0x80, 0xc4, 0xb4, 0x0b, 0xf2, 0x77, 0x83, 0xfe, 0xfb, 0x0f, 0x3d, 0x37, 0x2e, 0x23, 0xf1, 0xa1, - 0xbf, 0xc5, 0x07, 0x7c, 0xe6, 0xf9, 0xf3, 0x27, 0xed, 0xd3, 0x2e, 0x27, 0x44, 0x6f, 0x68, 0xad, 0xb7, 0x9e, 0x02, - 0x18, 0xc5, 0x55, 0xb4, 0xf6, 0x96, 0x68, 0x6b, 0xfa, 0xf5, 0xe6, 0x9b, 0x41, 0x9f, 0x98, 0x17, 0x54, 0x4c, 0xbd, - 0x52, 0x54, 0x40, 0x01, 0xbf, 0xff, 0x16, 0x42, 0x5e, 0xfe, 0x0f, 0xc1, 0x50, 0xdf, 0x35, 0x8c, 0x8b, 0xf7, 0x1f, - 0xb7, 0x79, 0x87, 0x90, 0xbe, 0x92, 0x05, 0x93, 0xe0, 0xca, 0xb5, 0x66, 0x24, 0x93, 0x57, 0x81, 0x26, 0x07, 0x6e, - 0x6b, 0x8b, 0x49, 0xc7, 0xbf, 0x42, 0x2c, 0xca, 0xa6, 0x33, 0x5b, 0x7f, 0x83, 0x30, 0x6c, 0x55, 0x41, 0x32, 0xcc, - 0xe4, 0x81, 0x20, 0xfa, 0xaa, 0xbe, 0x5b, 0xf9, 0xa1, 0x81, 0x71, 0xd7, 0xeb, 0x6f, 0xdc, 0x0d, 0x44, 0x1e, 0x06, - 0xe4, 0x56, 0x7d, 0x05, 0x85, 0x86, 0xec, 0xa9, 0x06, 0xc9, 0x95, 0xd4, 0x46, 0x48, 0x70, 0x2d, 0xde, 0xe4, 0x4f, - 0x8a, 0xa2, 0x28, 0x82, 0x8d, 0x50, 0x04, 0x1f, 0x81, 0xe5, 0xc8, 0x0e, 0x80, 0xb6, 0x24, 0x8f, 0x37, 0xb4, 0x04, - 0x38, 0x03, 0xd4, 0xc9, 0xf2, 0x02, 0x16, 0x5c, 0xaf, 0x67, 0xf3, 0x02, 0xce, 0xd0, 0x43, 0x60, 0x34, 0x37, 0x81, - 0x18, 0xbc, 0x03, 0x05, 0x19, 0x76, 0x7c, 0xcb, 0x24, 0xc1, 0x8a, 0x4d, 0x1f, 0x27, 0x43, 0xd2, 0x1c, 0x85, 0x2d, - 0x94, 0xb0, 0x20, 0x68, 0x1d, 0x2a, 0x41, 0x95, 0x0d, 0xd2, 0x80, 0x1b, 0x91, 0x2f, 0xda, 0x64, 0x2b, 0x12, 0xae, - 0x55, 0xcc, 0xc2, 0x84, 0x51, 0xf1, 0xa0, 0xce, 0x1b, 0x4a, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0xb9, 0xa4, 0x77, 0x61, - 0xca, 0x50, 0xaa, 0x6b, 0x78, 0x4c, 0xb1, 0x99, 0x32, 0xdc, 0x56, 0xbd, 0x21, 0xd8, 0x92, 0x46, 0x55, 0xd7, 0x29, - 0x6a, 0x8c, 0x0c, 0x7d, 0xd0, 0x78, 0x14, 0x4c, 0x5c, 0xc4, 0xc1, 0xae, 0xb9, 0xd5, 0x45, 0x13, 0x1a, 0x19, 0xb7, - 0x22, 0x28, 0x4a, 0xf4, 0x7a, 0x37, 0x6c, 0x9c, 0x10, 0x0a, 0xa8, 0xb5, 0x1f, 0xaf, 0xd6, 0x4f, 0xcb, 0xa4, 0x3f, - 0x91, 0x07, 0x7a, 0x91, 0x50, 0x50, 0x7d, 0x22, 0x0f, 0x60, 0xfb, 0xf7, 0x16, 0xa4, 0x29, 0xea, 0x0e, 0x74, 0x6d, - 0x40, 0x70, 0x7d, 0x0f, 0xc2, 0x43, 0xed, 0x38, 0x40, 0x76, 0xbe, 0x03, 0x8b, 0x23, 0x88, 0x21, 0x8f, 0x32, 0x3f, - 0xc4, 0xcc, 0xca, 0x5e, 0x6b, 0x84, 0xb1, 0xd9, 0x70, 0x34, 0xf4, 0x17, 0x8e, 0x6d, 0x1f, 0xd5, 0xea, 0x83, 0x20, - 0xbb, 0xa9, 0xb6, 0x6e, 0x64, 0x23, 0xc7, 0x36, 0xfd, 0x17, 0x56, 0x67, 0x58, 0xbb, 0xa3, 0xa5, 0xe8, 0x8d, 0x13, - 0x14, 0x7f, 0x8d, 0x9f, 0x6d, 0xb5, 0xda, 0x81, 0xd4, 0xab, 0x56, 0xeb, 0x38, 0xb6, 0x9c, 0xc9, 0xbf, 0x26, 0xf5, - 0xab, 0x9f, 0xc6, 0x8e, 0xa4, 0x99, 0x44, 0x26, 0x10, 0x7f, 0x58, 0x83, 0x63, 0xf4, 0x67, 0xe5, 0xa5, 0xa2, 0xd1, - 0xe3, 0xa3, 0xeb, 0x13, 0x91, 0xa0, 0x9a, 0xbb, 0x75, 0xc9, 0x1d, 0x54, 0xbe, 0x98, 0x56, 0x31, 0x1c, 0x8b, 0x74, - 0x4a, 0x0a, 0x8d, 0xde, 0x4e, 0x6a, 0x01, 0xfb, 0x6f, 0xb9, 0x3e, 0xad, 0x29, 0x44, 0x02, 0x80, 0x1a, 0x10, 0xad, - 0x7c, 0x6f, 0x87, 0xeb, 0xb8, 0xdc, 0x5d, 0xf9, 0x92, 0x3c, 0xbc, 0x33, 0xbc, 0x74, 0x50, 0x87, 0x26, 0xfa, 0x6b, - 0xbe, 0xee, 0x1e, 0xd9, 0x25, 0x09, 0x67, 0xe5, 0x0e, 0x2b, 0xf7, 0xd7, 0xe1, 0xdd, 0x95, 0x30, 0x0a, 0x84, 0xf1, - 0x8f, 0x1a, 0x30, 0x4a, 0x1e, 0x85, 0xb8, 0xf9, 0xe9, 0x71, 0xf3, 0x0f, 0xa2, 0x62, 0xb0, 0x01, 0x8d, 0xc1, 0x25, - 0x9a, 0x49, 0x42, 0x71, 0x88, 0x15, 0x8d, 0x8e, 0xb8, 0x1a, 0x27, 0x44, 0x5b, 0x77, 0x62, 0xc6, 0x6d, 0x0a, 0x8b, - 0x36, 0x3e, 0x8b, 0xfe, 0x78, 0xa8, 0xd4, 0xda, 0xdf, 0x2f, 0xb5, 0xce, 0xf6, 0x49, 0xad, 0xa9, 0x47, 0xd3, 0x7d, - 0xe2, 0xc6, 0x92, 0x53, 0x1c, 0x27, 0xce, 0x65, 0xdf, 0xb8, 0x92, 0xa8, 0x1b, 0x1d, 0xa0, 0x78, 0xab, 0x5a, 0x6f, - 0xd4, 0x4a, 0x10, 0xc5, 0xdf, 0x12, 0x83, 0xc2, 0x15, 0xea, 0xb2, 0x6c, 0xfc, 0xaa, 0x90, 0x8d, 0x53, 0xae, 0xa6, - 0xf0, 0x65, 0xe1, 0xd4, 0xbf, 0xe4, 0x27, 0x26, 0xb8, 0x83, 0xc2, 0x5f, 0xac, 0x18, 0xa9, 0xe4, 0x01, 0x55, 0x30, - 0x1a, 0x92, 0x5f, 0x1d, 0xe7, 0x32, 0xca, 0xee, 0x75, 0xe5, 0xaa, 0x85, 0x03, 0x54, 0x51, 0x0e, 0x52, 0x77, 0x1c, - 0xb2, 0x28, 0x96, 0xb7, 0x4d, 0xd9, 0x03, 0x46, 0x7e, 0x2d, 0x6d, 0x12, 0xe1, 0xaa, 0x42, 0x01, 0xcc, 0xc5, 0xf4, - 0x15, 0xbd, 0xb6, 0xb0, 0x81, 0xc0, 0x41, 0x36, 0x78, 0xd6, 0xed, 0x97, 0xce, 0xd3, 0x0c, 0x05, 0x85, 0x16, 0x5e, - 0x96, 0x41, 0x20, 0x7c, 0x6f, 0xb6, 0x0d, 0xb7, 0x3c, 0x5e, 0xf2, 0xec, 0x7e, 0x07, 0xf1, 0xa2, 0x62, 0xcb, 0x8a, - 0x7c, 0x3c, 0x99, 0x26, 0x35, 0xcf, 0xc5, 0xaa, 0xf5, 0x4e, 0xa9, 0x10, 0x67, 0xcb, 0x9c, 0x53, 0xca, 0x32, 0x7a, - 0x56, 0x63, 0xc0, 0xbf, 0xcb, 0xb6, 0x4e, 0xb2, 0x0e, 0x31, 0x9a, 0xbc, 0x99, 0x25, 0xae, 0xf7, 0x49, 0x1a, 0x32, - 0x97, 0x73, 0x82, 0x0c, 0xb8, 0xac, 0x29, 0x18, 0xba, 0x18, 0x7c, 0x91, 0x0c, 0xac, 0x4e, 0x2a, 0x49, 0x5f, 0x06, - 0x4f, 0xed, 0xae, 0xfb, 0x6a, 0x7e, 0x5c, 0x11, 0x8a, 0x76, 0x7a, 0x65, 0x91, 0x79, 0xcb, 0x38, 0xb2, 0xe5, 0x7a, - 0x35, 0xdd, 0xca, 0xb2, 0x55, 0x49, 0xe4, 0x5a, 0x17, 0xb3, 0xca, 0x9f, 0x9d, 0xcf, 0xe7, 0x65, 0x41, 0xa3, 0xad, - 0x1c, 0xa3, 0xb0, 0xf0, 0xa9, 0x6d, 0xdb, 0xd5, 0xb1, 0xef, 0x06, 0xbb, 0x89, 0x72, 0xdb, 0xd3, 0xc6, 0x11, 0x23, - 0x6c, 0xf7, 0xc1, 0xaf, 0x0e, 0x8e, 0xdc, 0x2a, 0x4e, 0x76, 0xc9, 0x2c, 0x62, 0x48, 0x8d, 0x21, 0xfc, 0x8c, 0xac, - 0xd2, 0x81, 0x47, 0x50, 0x07, 0x63, 0x49, 0x07, 0x1a, 0x0d, 0x07, 0xcc, 0x05, 0x98, 0x8a, 0x38, 0x7c, 0x57, 0xd8, - 0x0a, 0xca, 0xc3, 0x6b, 0xc2, 0x7b, 0xfe, 0x11, 0x3c, 0x28, 0xdb, 0xba, 0x4c, 0x1b, 0xa7, 0xd5, 0xb3, 0xff, 0x5c, - 0xaa, 0xa7, 0xc0, 0x05, 0xb8, 0xe5, 0x0a, 0x6d, 0x2a, 0x9f, 0xc5, 0xff, 0x17, 0xf2, 0xff, 0x57, 0xf1, 0xa6, 0x6c, - 0x3f, 0x72, 0x0a, 0x12, 0xed, 0xe2, 0xb4, 0xd0, 0x51, 0x37, 0xed, 0x01, 0x61, 0x65, 0x30, 0x97, 0x15, 0xe8, 0xa0, - 0xa4, 0x2f, 0xa5, 0xdc, 0x68, 0x10, 0xbf, 0x23, 0xc5, 0x0c, 0x4b, 0x5c, 0x88, 0x10, 0x8b, 0x84, 0x71, 0x30, 0x07, - 0xe3, 0xe5, 0x29, 0xea, 0x0f, 0x4a, 0x7b, 0x02, 0xb4, 0xf1, 0xb5, 0xb9, 0x1d, 0x24, 0xee, 0xaf, 0xea, 0xb5, 0x78, - 0xc7, 0x00, 0x32, 0x07, 0x0e, 0x21, 0x1a, 0x12, 0x28, 0x95, 0xcd, 0x4d, 0x47, 0x29, 0xde, 0xca, 0x7a, 0x36, 0x3e, - 0x30, 0xec, 0xae, 0xb9, 0x0a, 0xed, 0x9b, 0x6b, 0x0b, 0x60, 0xb2, 0x6c, 0xfb, 0xe1, 0xb3, 0x09, 0x4b, 0x2c, 0xef, - 0x47, 0x07, 0x97, 0x1c, 0xf7, 0xaf, 0x89, 0x77, 0x67, 0x4a, 0xcf, 0x3f, 0xca, 0x17, 0xff, 0xda, 0x28, 0xd0, 0xbb, - 0x2a, 0x49, 0xe8, 0x98, 0xb5, 0x78, 0x47, 0x3f, 0xa8, 0xf6, 0xca, 0x0f, 0x0f, 0xaf, 0xeb, 0x6e, 0x0e, 0xae, 0x0b, - 0x17, 0xc6, 0xc1, 0x95, 0xe1, 0xc6, 0xa1, 0x96, 0x0b, 0xd9, 0xe8, 0xaf, 0x92, 0x40, 0x51, 0x76, 0xfc, 0x55, 0xb1, - 0x15, 0xa5, 0xf2, 0xaf, 0xd6, 0x40, 0x7c, 0x1e, 0x94, 0x52, 0x41, 0xe1, 0x59, 0xd1, 0xd4, 0xbe, 0x72, 0xaa, 0xf4, - 0xbb, 0xca, 0x89, 0xad, 0x52, 0x2e, 0x6c, 0xa4, 0xf6, 0x3a, 0x85, 0x43, 0xdf, 0xb1, 0xad, 0x8e, 0xcf, 0x16, 0xfc, - 0x92, 0x98, 0xfb, 0x41, 0x40, 0x51, 0x45, 0x9a, 0x25, 0xd1, 0x27, 0x52, 0x56, 0xb3, 0xd0, 0x32, 0x66, 0x04, 0xd2, - 0xe1, 0x8f, 0x70, 0x76, 0x3c, 0x37, 0x1e, 0xe0, 0xd9, 0x90, 0x0b, 0xc1, 0x80, 0x93, 0x96, 0xe2, 0x27, 0xe0, 0x0e, - 0x9e, 0xaa, 0xe3, 0x33, 0x08, 0x1a, 0xa8, 0xcc, 0x46, 0xea, 0x8f, 0x9d, 0xbe, 0xe2, 0xf4, 0xee, 0xcc, 0xae, 0x67, - 0x9b, 0x8e, 0x75, 0xac, 0xd8, 0xd6, 0x89, 0xd9, 0xb1, 0xfa, 0x4a, 0xc7, 0xea, 0xc1, 0xbf, 0x9e, 0x63, 0xbd, 0x52, - 0x6c, 0x78, 0x52, 0x1c, 0xab, 0x8b, 0xff, 0x76, 0xac, 0xfe, 0x5d, 0x97, 0xde, 0xf4, 0xae, 0x70, 0xab, 0xaa, 0x8c, - 0x02, 0x9c, 0x40, 0xd4, 0xa3, 0xf1, 0xd9, 0x3a, 0x25, 0xca, 0x66, 0xa4, 0xbe, 0x52, 0x95, 0x65, 0x42, 0xe6, 0x23, - 0xf5, 0xa9, 0x2b, 0x95, 0x3a, 0xa7, 0x8d, 0xc5, 0x9d, 0x7e, 0x63, 0x71, 0xf7, 0xa4, 0xb1, 0xf8, 0xb8, 0x57, 0x2e, - 0x3e, 0x5a, 0xd0, 0x57, 0x52, 0xce, 0xbe, 0x95, 0x9b, 0x25, 0xfe, 0x46, 0x73, 0x14, 0x40, 0xd7, 0x26, 0xfc, 0xd3, - 0xef, 0xe8, 0xa2, 0xd5, 0x14, 0x5a, 0x09, 0x68, 0xf4, 0x4f, 0x15, 0xe7, 0xe4, 0x2f, 0x9d, 0x13, 0x0f, 0xea, 0x41, - 0x86, 0x49, 0xf8, 0xbb, 0xeb, 0x9e, 0x7a, 0xb6, 0x02, 0x0d, 0x1d, 0xf8, 0x6f, 0xd9, 0xeb, 0x78, 0xf4, 0xc1, 0x86, - 0xf7, 0x1f, 0x9d, 0x7e, 0x6a, 0x9b, 0x0e, 0xfc, 0xf7, 0x9b, 0x50, 0xb9, 0x83, 0xc2, 0x5f, 0xee, 0xf7, 0xd8, 0x56, - 0xba, 0xa7, 0xcb, 0x8e, 0xf5, 0xea, 0xae, 0x6f, 0x9d, 0x2e, 0x9d, 0xfe, 0x47, 0xfa, 0x14, 0x98, 0x1d, 0xeb, 0x15, - 0xfc, 0x7d, 0xec, 0xda, 0x4b, 0xd3, 0xb1, 0x4e, 0xef, 0xba, 0x56, 0x37, 0x30, 0x4f, 0xac, 0x53, 0xf8, 0xfb, 0x0d, - 0xc0, 0x0b, 0x70, 0x65, 0x29, 0x41, 0x15, 0xd8, 0x18, 0x15, 0xfb, 0x0d, 0xf9, 0x23, 0x9d, 0x63, 0xa5, 0x77, 0xfc, - 0x97, 0xd3, 0x3b, 0xf3, 0x78, 0xe9, 0x74, 0xee, 0xcc, 0xd6, 0x9f, 0x1f, 0x01, 0xf2, 0xbb, 0x17, 0x0e, 0xc0, 0x88, - 0x39, 0x40, 0xfe, 0x34, 0x31, 0x2e, 0xdb, 0xc4, 0xe8, 0xef, 0xf7, 0x8b, 0xd1, 0x7f, 0x58, 0x1f, 0x22, 0x46, 0x7f, - 0xff, 0xd5, 0xc5, 0xe8, 0x97, 0x55, 0x2b, 0xee, 0xf7, 0xd5, 0x58, 0xe5, 0xbf, 0x6c, 0xab, 0x44, 0xb2, 0xef, 0x6a, - 0xd7, 0x57, 0xeb, 0x1b, 0x88, 0xb6, 0xf3, 0x3e, 0x1a, 0xfd, 0xb0, 0x2e, 0x99, 0x28, 0x45, 0x80, 0x01, 0xde, 0x47, - 0x14, 0x03, 0xfc, 0xb6, 0x1e, 0x81, 0x5d, 0x04, 0xbb, 0x35, 0xfd, 0x99, 0xb9, 0x74, 0x83, 0xb9, 0xb8, 0x71, 0xa1, - 0x64, 0x88, 0xc5, 0x60, 0x33, 0x0f, 0x97, 0x09, 0x28, 0x6b, 0xd6, 0xab, 0x30, 0x1d, 0x9c, 0xd8, 0x80, 0xe6, 0x3b, - 0xf3, 0x24, 0xaf, 0x34, 0xb6, 0x78, 0x7c, 0xa2, 0x5b, 0x66, 0xd3, 0xdf, 0xfa, 0x1e, 0x4d, 0xd6, 0x9a, 0x7b, 0x77, - 0xea, 0xfd, 0x2a, 0x60, 0x0b, 0xc2, 0x4d, 0xfa, 0x80, 0xd8, 0x68, 0x7a, 0x5f, 0x36, 0x1c, 0xab, 0x98, 0x0a, 0xb6, - 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x94, 0x0d, 0xcf, 0xf6, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x3b, 0xac, 0xde, - 0x44, 0xc7, 0x55, 0x50, 0x55, 0x32, 0x6d, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0xb1, 0x15, - 0xbc, 0x8d, 0x6d, 0xe9, 0x5d, 0xa9, 0x4f, 0xd9, 0x9c, 0xee, 0xc5, 0x16, 0xe9, 0x41, 0xff, 0x37, 0x20, 0x6c, 0xd8, - 0x7d, 0x3c, 0x8d, 0x64, 0x38, 0x6f, 0xa5, 0x7e, 0x29, 0xa9, 0x9d, 0x2f, 0x9d, 0x6d, 0x9d, 0xb4, 0x69, 0x35, 0xa4, - 0x75, 0xc8, 0x8a, 0xdf, 0xd1, 0xf8, 0x79, 0x6a, 0xb6, 0x9a, 0x53, 0xd3, 0x62, 0xb4, 0xcc, 0xdd, 0xd5, 0x19, 0xaf, - 0xf7, 0x14, 0x36, 0xb1, 0xc1, 0x1e, 0x64, 0xc7, 0xf1, 0xed, 0x1c, 0xb2, 0x22, 0x0f, 0x90, 0x88, 0x90, 0x28, 0xa8, - 0x0e, 0xda, 0xd8, 0x0e, 0x77, 0x98, 0x7f, 0xc8, 0x1d, 0xb3, 0x4e, 0xd0, 0x56, 0x77, 0x97, 0xc5, 0x88, 0x70, 0x6d, - 0xd8, 0x96, 0x14, 0xa8, 0x4e, 0xaf, 0x6f, 0x38, 0x27, 0x86, 0xd5, 0xef, 0xe9, 0x39, 0x3f, 0x70, 0x72, 0x97, 0x25, - 0x80, 0x80, 0xc9, 0xae, 0x18, 0xa6, 0x1f, 0xfa, 0x99, 0xef, 0x06, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, 0x75, - 0x9a, 0xc1, 0x1c, 0x39, 0x49, 0x86, 0xe6, 0xca, 0xe6, 0x94, 0x64, 0xf7, 0x84, 0x84, 0x2d, 0xaa, 0xdc, 0xaa, 0xf5, - 0xf3, 0x1f, 0x67, 0x0b, 0x9a, 0x53, 0x3b, 0x8b, 0x69, 0x16, 0xb2, 0xfd, 0xc1, 0x4d, 0x75, 0xf3, 0x89, 0xf1, 0x53, - 0x1b, 0xc2, 0xfd, 0xe7, 0x7e, 0x84, 0x9b, 0x91, 0x43, 0x10, 0xee, 0x3f, 0xbf, 0x3a, 0xc2, 0xfd, 0x49, 0x46, 0xb8, - 0x25, 0x4f, 0x95, 0x42, 0x26, 0xfa, 0x01, 0x9f, 0x35, 0x08, 0xf2, 0xfb, 0x52, 0x3d, 0xa2, 0xe4, 0xa5, 0x2a, 0x25, - 0x5f, 0xfd, 0x58, 0xca, 0x26, 0x83, 0x2c, 0x3b, 0x06, 0x25, 0xa5, 0x99, 0x2b, 0x20, 0x31, 0xa9, 0x48, 0xb1, 0x0d, - 0x7d, 0x5e, 0x84, 0x59, 0x60, 0xbd, 0x67, 0x6c, 0x09, 0xa8, 0x20, 0x7e, 0x88, 0x92, 0x95, 0x8b, 0x01, 0xd9, 0x54, - 0xcc, 0x42, 0x07, 0x0f, 0x36, 0x78, 0x47, 0x79, 0x51, 0x38, 0x13, 0x72, 0x74, 0x32, 0xba, 0xa6, 0xf4, 0xa0, 0xfa, - 0x40, 0xdc, 0x44, 0x35, 0xe8, 0x6b, 0x58, 0xdc, 0x17, 0x5d, 0xfb, 0x45, 0xe7, 0xf8, 0xc5, 0x89, 0x0d, 0xff, 0x73, - 0x48, 0x37, 0x37, 0x58, 0xc5, 0x55, 0x14, 0x42, 0x22, 0x0c, 0x5e, 0xb3, 0xad, 0xda, 0x3d, 0x21, 0x9f, 0x8a, 0x5a, - 0xfd, 0xe6, 0x4a, 0x33, 0xf7, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x19, 0xad, 0xa5, 0x61, 0x35, 0x8c, 0xc6, 0x0f, 0xd7, - 0x20, 0x19, 0x92, 0x6a, 0xc8, 0xaf, 0xd9, 0x74, 0x8b, 0x79, 0x91, 0x6e, 0x7e, 0x53, 0x64, 0xdb, 0xe1, 0x59, 0x3f, - 0xf6, 0x42, 0x90, 0x09, 0xd5, 0x6d, 0x8c, 0xd5, 0x8d, 0xf9, 0x66, 0x14, 0xc8, 0x75, 0x57, 0xa4, 0x54, 0xc7, 0x05, - 0xca, 0x92, 0x75, 0xe8, 0xd1, 0xac, 0xe9, 0xee, 0x34, 0xd5, 0xfc, 0x23, 0x88, 0xd6, 0x89, 0x1f, 0xd6, 0x71, 0xd5, - 0xdc, 0xb1, 0x5d, 0xa4, 0x26, 0x48, 0xf9, 0xaa, 0xb8, 0x2f, 0x32, 0x23, 0xa1, 0x09, 0x4d, 0x71, 0x69, 0xcd, 0x91, - 0xfb, 0x42, 0x34, 0x7c, 0x91, 0x19, 0x90, 0x54, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0x5a, 0x0b, 0xd2, 0xfc, 0xd1, 0x69, - 0x9d, 0x7b, 0x22, 0x35, 0x98, 0xaa, 0xb8, 0x8b, 0x48, 0xc5, 0xd4, 0x60, 0x03, 0xcf, 0x88, 0x5e, 0xbe, 0x1c, 0x8f, - 0x1c, 0x9d, 0x25, 0xa9, 0x2c, 0x65, 0x54, 0xba, 0x3c, 0x4c, 0x35, 0xae, 0x37, 0x3a, 0x6d, 0xc5, 0x7e, 0xb8, 0xe0, - 0x9a, 0x69, 0x81, 0xbd, 0x20, 0xc3, 0x01, 0x55, 0x81, 0xb9, 0x5c, 0x45, 0xcd, 0xeb, 0xdc, 0x91, 0x04, 0x12, 0x6c, - 0x8e, 0xd4, 0xae, 0x65, 0x5b, 0xb6, 0x2a, 0x1a, 0xce, 0xfd, 0xc5, 0x68, 0x1b, 0x65, 0x2e, 0xe4, 0x8a, 0x09, 0xa2, - 0x05, 0x78, 0x7e, 0x64, 0x7e, 0x16, 0x40, 0xe2, 0x11, 0x70, 0x01, 0x59, 0x51, 0xae, 0x31, 0x67, 0xf6, 0xb8, 0x6e, - 0xf2, 0x09, 0x93, 0xcf, 0x71, 0xa7, 0x2f, 0x0c, 0x49, 0xf3, 0x23, 0x5c, 0x86, 0x9a, 0xaa, 0x41, 0xea, 0x43, 0x92, - 0xa4, 0xa6, 0x6c, 0xdf, 0x3e, 0x50, 0xa0, 0x0d, 0xa4, 0x25, 0xc7, 0x0e, 0xe6, 0x89, 0xbb, 0x82, 0x18, 0xdd, 0xdb, - 0xdc, 0x60, 0x98, 0x56, 0x65, 0xa8, 0x56, 0x71, 0x5e, 0x9d, 0x18, 0x4a, 0xc7, 0x31, 0x14, 0x1b, 0xd0, 0xad, 0x9a, - 0x1b, 0xdb, 0xfc, 0x66, 0xb8, 0x4f, 0x45, 0x47, 0xf1, 0xcb, 0x53, 0x3a, 0x0f, 0xaa, 0x9c, 0x63, 0xc2, 0xcf, 0x8c, - 0x06, 0x14, 0xd4, 0xa4, 0xe8, 0xd9, 0x3e, 0x15, 0xd3, 0x5f, 0x91, 0x4d, 0xa6, 0x63, 0x62, 0x0e, 0x56, 0xc5, 0xd7, - 0xb7, 0xe8, 0x9a, 0xe6, 0x87, 0x8a, 0xff, 0xf9, 0xb3, 0xe6, 0x83, 0xf9, 0xfd, 0x48, 0x82, 0x0f, 0x3c, 0xeb, 0x25, - 0x80, 0xf9, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0xcc, 0x7f, 0x30, 0xc5, 0x9e, 0x15, 0xb8, - 0xe1, 0x02, 0x50, 0x9a, 0x1b, 0x2e, 0x6a, 0x06, 0x04, 0xd4, 0xbb, 0xae, 0x52, 0x5a, 0x74, 0x55, 0x28, 0xf7, 0xd3, - 0xef, 0x1f, 0xae, 0x68, 0xe2, 0x21, 0x48, 0x72, 0xed, 0xce, 0xd0, 0x15, 0xac, 0xd0, 0x3d, 0xbc, 0x1c, 0x7d, 0x73, - 0xb6, 0x22, 0x99, 0x4b, 0x05, 0x97, 0xc0, 0xe2, 0x01, 0x39, 0xa0, 0x78, 0x3c, 0x69, 0x28, 0x65, 0xf0, 0x66, 0xe4, - 0xce, 0xf7, 0x18, 0x9f, 0x66, 0x28, 0xec, 0x9e, 0x32, 0xd1, 0x46, 0x69, 0xe4, 0x18, 0xd4, 0x44, 0xd6, 0x73, 0x31, - 0xec, 0xe0, 0x28, 0x8c, 0xd4, 0xf1, 0x37, 0xc2, 0x9b, 0xa8, 0x6d, 0x11, 0x20, 0xfb, 0xdf, 0x75, 0x42, 0x82, 0x7f, - 0x8d, 0xbe, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0x55, 0x1f, 0x66, 0x16, 0xf2, 0x31, 0xdf, 0x34, 0x64, 0xc1, 0x43, 0x1e, - 0x95, 0x31, 0x9b, 0x5d, 0x89, 0xd9, 0x84, 0xdf, 0xfb, 0x59, 0xd7, 0xf1, 0x19, 0x5e, 0x68, 0x63, 0xe0, 0x2e, 0xb6, - 0x25, 0x9e, 0xd3, 0x19, 0x22, 0x83, 0x3a, 0x0d, 0x5c, 0xef, 0x13, 0xe7, 0x50, 0xe5, 0x87, 0x43, 0x78, 0x51, 0x41, - 0xd9, 0x35, 0xee, 0x65, 0xdc, 0xca, 0x5b, 0xfc, 0x32, 0x7e, 0xea, 0x7e, 0xe9, 0x67, 0x82, 0x19, 0xc6, 0x87, 0x1c, - 0xb4, 0x39, 0x38, 0xbe, 0x82, 0xfd, 0x01, 0x06, 0xd5, 0x39, 0xfd, 0x4b, 0xef, 0xce, 0xb1, 0x97, 0x1d, 0xc7, 0x02, - 0x36, 0x67, 0xd9, 0xb5, 0xfa, 0x81, 0xd9, 0xb5, 0xfa, 0xf0, 0xf7, 0x11, 0x58, 0x2f, 0xb3, 0x63, 0x1d, 0x7f, 0x74, - 0x3a, 0x81, 0x79, 0x6a, 0xf5, 0xe1, 0xef, 0x92, 0xb6, 0xfa, 0x05, 0x99, 0x1e, 0x60, 0x78, 0xbe, 0x29, 0x61, 0x01, - 0xe9, 0xb7, 0xd0, 0x22, 0x18, 0xa5, 0xeb, 0xad, 0x41, 0x13, 0x01, 0x28, 0x43, 0x35, 0x78, 0x94, 0xc0, 0x70, 0xa8, - 0x41, 0x5a, 0x6e, 0x0c, 0x28, 0xcf, 0x0d, 0x32, 0xc2, 0x22, 0xc5, 0x7c, 0xfb, 0x31, 0x62, 0x6d, 0x9a, 0x03, 0x70, - 0xf3, 0x4c, 0x45, 0x54, 0x75, 0xf1, 0xb7, 0x18, 0x03, 0xeb, 0xf0, 0x90, 0xe1, 0x12, 0x56, 0x2a, 0xb2, 0xe5, 0xe5, - 0xfb, 0x07, 0x8e, 0x7e, 0xa3, 0x44, 0x64, 0x6b, 0xf9, 0xaa, 0x7d, 0x33, 0x75, 0x86, 0xe8, 0xfd, 0xf7, 0xf6, 0x83, - 0x49, 0x4a, 0x69, 0x3f, 0x3c, 0xba, 0xe7, 0xcc, 0x4f, 0xc4, 0xf0, 0x24, 0x14, 0xed, 0x34, 0x47, 0x2e, 0xd7, 0x21, - 0xad, 0xc5, 0x05, 0x50, 0xc9, 0x77, 0x6e, 0x20, 0x99, 0x5e, 0x48, 0x2d, 0x9f, 0x08, 0xcc, 0xff, 0xfc, 0x79, 0x31, - 0x38, 0xb3, 0x32, 0xee, 0x33, 0xa7, 0x07, 0xd7, 0x6e, 0x8f, 0x74, 0x77, 0x5a, 0x01, 0xed, 0x0f, 0x0f, 0x5b, 0xc4, - 0x93, 0xe4, 0x9a, 0x7e, 0xae, 0x63, 0x6c, 0x35, 0x45, 0xaa, 0x69, 0x18, 0x21, 0xb0, 0x6e, 0x85, 0xd5, 0x51, 0xf5, - 0x61, 0xc8, 0x15, 0x66, 0xe1, 0x8e, 0x90, 0xb8, 0x8c, 0x17, 0x53, 0x01, 0x34, 0x3b, 0xe6, 0xb1, 0xc7, 0xa5, 0xf1, - 0x7f, 0x3d, 0x09, 0x74, 0x2f, 0x02, 0x0d, 0x5f, 0xe5, 0xb4, 0x96, 0xdc, 0x4d, 0xc4, 0xbd, 0x4a, 0x2f, 0x54, 0x92, - 0x9e, 0xab, 0x50, 0x04, 0xf9, 0x8e, 0x30, 0xc5, 0x99, 0x30, 0x6f, 0x12, 0xb7, 0x45, 0x51, 0x60, 0xf8, 0x10, 0x13, - 0x5a, 0xe3, 0xae, 0x4e, 0xfa, 0xf3, 0xe7, 0xad, 0x97, 0x10, 0x55, 0x27, 0xcb, 0x99, 0x1e, 0x55, 0x19, 0xbf, 0xa9, - 0x32, 0x8a, 0x11, 0xfd, 0x22, 0xd6, 0xe0, 0x56, 0x59, 0x74, 0xef, 0xe1, 0xcf, 0x29, 0x71, 0x33, 0x8b, 0xe9, 0x41, - 0x34, 0xe9, 0x72, 0x37, 0x1c, 0xd2, 0x05, 0x7b, 0x2c, 0x16, 0x7f, 0x8b, 0x05, 0x9b, 0x7b, 0xb6, 0xfd, 0xb8, 0x66, - 0x7e, 0xc8, 0xd0, 0xc7, 0x67, 0xbb, 0x08, 0x9e, 0xf2, 0x2e, 0x73, 0x69, 0x84, 0x0d, 0xf9, 0xca, 0x8d, 0x32, 0x97, - 0xe7, 0x15, 0x01, 0xba, 0x7c, 0xd8, 0xa8, 0x30, 0x94, 0x7c, 0x95, 0xc7, 0xef, 0xae, 0xbe, 0x53, 0xd8, 0xfe, 0xa7, - 0xfa, 0x2d, 0x64, 0x64, 0x68, 0x14, 0xfc, 0x11, 0x8d, 0x82, 0xaf, 0xb0, 0xb4, 0x12, 0x10, 0x4b, 0x3e, 0x3f, 0xa2, - 0x10, 0x54, 0x15, 0x12, 0x7a, 0x54, 0xeb, 0xb7, 0x5a, 0x07, 0x99, 0x1f, 0xbb, 0x49, 0x76, 0x04, 0x4d, 0x4d, 0x40, - 0x72, 0x6a, 0x9b, 0x07, 0x33, 0x55, 0x1c, 0x72, 0xa1, 0x5a, 0x16, 0x72, 0xcd, 0xe1, 0xdc, 0x0f, 0x84, 0xe2, 0x90, - 0x7f, 0xc0, 0xf5, 0x3c, 0x12, 0x67, 0x23, 0xd5, 0x8d, 0x21, 0x1b, 0x02, 0xc6, 0x37, 0x3e, 0x8a, 0xbc, 0x8c, 0x64, - 0x66, 0x9a, 0x25, 0xc4, 0x5d, 0xa9, 0x22, 0xd6, 0x67, 0xbd, 0xbf, 0x74, 0x3d, 0x5d, 0xf9, 0x99, 0x08, 0x96, 0x47, - 0x27, 0x08, 0x2a, 0x3c, 0x18, 0xe2, 0x78, 0x92, 0x33, 0x10, 0x5e, 0x46, 0x8b, 0xca, 0x8e, 0x2a, 0x28, 0x97, 0x73, - 0x0c, 0xc5, 0xca, 0x22, 0xe0, 0xcf, 0xd0, 0x23, 0xe7, 0x96, 0x79, 0x5d, 0x8b, 0x98, 0x7e, 0xea, 0xf8, 0x8c, 0xb1, - 0xb7, 0x0a, 0x06, 0x0a, 0x50, 0x7b, 0x36, 0x04, 0x9b, 0x6d, 0xf3, 0xc7, 0x3e, 0x62, 0x95, 0xe1, 0x6a, 0xa2, 0x3d, - 0x63, 0xdc, 0x6f, 0x3a, 0x96, 0x2b, 0x20, 0x84, 0x4a, 0x2a, 0xde, 0xa5, 0x33, 0x16, 0x0e, 0x40, 0x38, 0x2a, 0xa4, - 0x95, 0x3e, 0x7f, 0x7e, 0x3d, 0xf9, 0xcf, 0xbf, 0x21, 0x38, 0xf9, 0xd2, 0xe1, 0x5e, 0xd0, 0xd7, 0x72, 0x2d, 0x46, - 0x7d, 0x1a, 0x13, 0x54, 0xef, 0x93, 0x19, 0x0f, 0x0b, 0xc2, 0xb7, 0x56, 0x3e, 0xb9, 0xe1, 0xa1, 0x9e, 0x20, 0x01, - 0x81, 0xce, 0x7d, 0xb5, 0x27, 0xb0, 0xbc, 0x13, 0x1e, 0x22, 0x40, 0xf9, 0x75, 0xf3, 0x7d, 0x1f, 0xb2, 0xf4, 0xd6, - 0xf2, 0x02, 0x48, 0x03, 0xc4, 0x3d, 0x34, 0x3e, 0x73, 0x99, 0xf0, 0x15, 0xc8, 0x8f, 0x74, 0x70, 0x04, 0xd3, 0x5c, - 0x46, 0x2b, 0x62, 0xf9, 0xd1, 0xd1, 0x3d, 0x99, 0x9a, 0x6e, 0xec, 0x53, 0xf9, 0x32, 0xca, 0xdd, 0x14, 0x4a, 0xf9, - 0x09, 0x05, 0x2d, 0xa5, 0xaf, 0xf3, 0x02, 0x94, 0x51, 0x01, 0x28, 0xf8, 0xe9, 0x8e, 0xcb, 0x01, 0xfc, 0x2c, 0x1e, - 0x31, 0xbe, 0x8c, 0xe5, 0xcf, 0x69, 0x1c, 0x3e, 0x1e, 0x72, 0xaf, 0x78, 0x30, 0xa3, 0xf9, 0x5c, 0x0e, 0xba, 0x67, - 0x95, 0xbf, 0x2f, 0xa0, 0x52, 0xec, 0xd9, 0x28, 0xa6, 0x5f, 0xaa, 0x7f, 0x42, 0xfc, 0x84, 0x6c, 0xb9, 0x2c, 0x3e, - 0x23, 0x9c, 0xe7, 0x5a, 0xf0, 0x3e, 0x01, 0x92, 0xa7, 0xb4, 0x12, 0x43, 0x14, 0xd5, 0xc8, 0xd0, 0x2d, 0xa4, 0xc9, - 0x93, 0xd1, 0x88, 0xe2, 0xb1, 0x2a, 0x3a, 0x03, 0x28, 0x35, 0x44, 0xcf, 0x87, 0xc9, 0x66, 0xd0, 0xd0, 0xa4, 0x1e, - 0x5c, 0xd8, 0xa8, 0x3a, 0x9d, 0xfa, 0x18, 0x8f, 0x5c, 0xbe, 0xbf, 0x4a, 0x3b, 0x10, 0x76, 0x16, 0x5b, 0x58, 0x40, - 0xe0, 0xbc, 0x9f, 0x0a, 0x1e, 0x57, 0xbe, 0xa5, 0x28, 0xdb, 0x0c, 0xdc, 0x87, 0x48, 0xd2, 0xac, 0x33, 0x27, 0xfb, - 0x4b, 0x2c, 0xbd, 0xe2, 0xce, 0x6d, 0xb5, 0x93, 0x24, 0x22, 0x90, 0xd7, 0x4f, 0x93, 0x1c, 0x32, 0x7c, 0xdf, 0x61, - 0x92, 0xeb, 0x96, 0x27, 0x83, 0xd8, 0x31, 0x2f, 0x0e, 0x5a, 0xe9, 0x25, 0x9e, 0xfb, 0xfc, 0xec, 0x08, 0xe6, 0x07, - 0x81, 0x01, 0x4a, 0x94, 0x91, 0xaf, 0x43, 0xf4, 0x01, 0x37, 0xa5, 0xd6, 0x01, 0x17, 0x33, 0x4e, 0xd4, 0x21, 0xe7, - 0x28, 0xa2, 0x83, 0x96, 0xaa, 0xd4, 0x89, 0x15, 0xbb, 0x99, 0xca, 0xdb, 0x1f, 0xb1, 0xff, 0xb7, 0x35, 0x86, 0xeb, - 0xcf, 0x87, 0x19, 0xe1, 0x7e, 0xb7, 0x97, 0x59, 0x8b, 0x6b, 0x6e, 0x5b, 0x15, 0x4a, 0xb0, 0xee, 0xa8, 0x50, 0xec, - 0xe3, 0x5d, 0xb5, 0x0a, 0xd2, 0x48, 0x54, 0x8b, 0x5d, 0x4d, 0x7d, 0x8a, 0x3b, 0xbe, 0x56, 0x1b, 0x4b, 0xa1, 0xde, - 0x65, 0x36, 0x82, 0xaa, 0x5c, 0xd8, 0xee, 0xc6, 0x31, 0xad, 0xac, 0x0f, 0xcf, 0x8e, 0x28, 0xdf, 0x39, 0xa6, 0x3b, - 0x6c, 0x7c, 0x06, 0xd6, 0x85, 0x74, 0xd1, 0xdd, 0x38, 0x66, 0x4b, 0x4a, 0x7f, 0xd1, 0x37, 0x47, 0xcb, 0x6c, 0x15, - 0x8c, 0xff, 0x0f, 0x00, 0xa3, 0x9b, 0x76, 0x11, 0x5a, 0x03, 0x00}; + 0xdc, 0xd3, 0x2f, 0xb7, 0x8d, 0x1b, 0xff, 0x7f, 0x9f, 0x82, 0x61, 0xd2, 0x1c, 0x99, 0x90, 0x34, 0x29, 0x59, 0xb6, + 0x23, 0x59, 0xf6, 0xdd, 0x25, 0xb9, 0xa9, 0x3b, 0xbe, 0xcb, 0x4d, 0xe2, 0x66, 0xda, 0xf3, 0x79, 0x2c, 0x4a, 0x82, + 0x24, 0x36, 0x14, 0xa9, 0x21, 0x29, 0x5b, 0x3e, 0x85, 0x7d, 0x96, 0x3e, 0x4b, 0x9f, 0xec, 0x37, 0xbb, 0x0b, 0x80, + 0xe0, 0x87, 0x3e, 0x7c, 0xc9, 0xb5, 0xbf, 0xb9, 0xba, 0x11, 0x41, 0x00, 0x04, 0x16, 0xc0, 0x62, 0xbf, 0xd7, 0x9f, + 0x72, 0xd9, 0x8b, 0x65, 0xb0, 0xfd, 0x3e, 0xf7, 0xf9, 0x33, 0x73, 0x70, 0x4b, 0x02, 0xc1, 0xe7, 0x64, 0xf1, 0x74, + 0x1a, 0x32, 0x43, 0x17, 0xc9, 0x43, 0x74, 0x4b, 0x7e, 0xe6, 0xfc, 0x89, 0x2b, 0x22, 0x76, 0x9a, 0xf9, 0xa6, 0xa3, + 0x25, 0x66, 0xcc, 0x64, 0x48, 0x3b, 0xa2, 0x5c, 0x51, 0x36, 0x7b, 0x87, 0xea, 0x0d, 0xbe, 0x2e, 0xc5, 0xd1, 0xb5, + 0xc7, 0xf1, 0x72, 0x18, 0x32, 0x1b, 0xb7, 0x3b, 0x7c, 0x72, 0x3d, 0x5c, 0x0e, 0x87, 0x90, 0xa5, 0xe5, 0x89, 0x6b, + 0x41, 0xdc, 0x99, 0x38, 0x45, 0x7e, 0x30, 0x37, 0x7b, 0x30, 0x29, 0x27, 0xab, 0x0e, 0x1f, 0x6c, 0x45, 0x40, 0xd4, + 0x43, 0x1f, 0xc8, 0x80, 0xf7, 0x6b, 0x38, 0xb5, 0x7d, 0xfd, 0x03, 0xec, 0xbe, 0x54, 0xef, 0x35, 0x1d, 0xfd, 0xfe, + 0xb5, 0xfe, 0x01, 0x61, 0x8c, 0xd9, 0x8b, 0x5f, 0xd3, 0xee, 0xd5, 0x2d, 0x9d, 0x94, 0xde, 0x4b, 0xcc, 0x63, 0x00, + 0x42, 0xdf, 0x37, 0x81, 0x3f, 0x8d, 0xe2, 0x34, 0x0b, 0x46, 0xfa, 0x4d, 0xef, 0x22, 0x30, 0xae, 0xe7, 0x99, 0x61, + 0xde, 0x58, 0xa3, 0x4c, 0x4d, 0x81, 0x22, 0x10, 0x26, 0x66, 0x40, 0xd9, 0x54, 0x49, 0x3d, 0x41, 0x5b, 0x2b, 0x0a, + 0xd4, 0x8c, 0x95, 0x46, 0x59, 0x1f, 0xea, 0x55, 0xf2, 0xa9, 0x60, 0x62, 0x28, 0x1d, 0x5b, 0x9a, 0x3d, 0xe2, 0x54, + 0x5e, 0x2f, 0xd7, 0x78, 0x95, 0x67, 0xc5, 0x6d, 0x89, 0x31, 0x80, 0x85, 0xe3, 0x0c, 0x3d, 0x3f, 0x51, 0x8d, 0x3e, + 0x4b, 0xf7, 0xee, 0xe0, 0xbb, 0x32, 0x5d, 0x00, 0xf7, 0x37, 0x58, 0x5c, 0x44, 0x71, 0xa6, 0x41, 0x60, 0x1b, 0xf8, + 0xe2, 0xa0, 0x6a, 0x24, 0xc6, 0x7b, 0x35, 0xcc, 0x9c, 0x23, 0x83, 0xef, 0xf1, 0xf2, 0x33, 0x78, 0x78, 0xb3, 0x52, + 0x04, 0x0b, 0x62, 0x16, 0x22, 0x58, 0xc0, 0x2c, 0xbe, 0x8c, 0xef, 0xab, 0x7a, 0x90, 0xd7, 0x83, 0xdd, 0x77, 0xaf, + 0x21, 0xc8, 0x64, 0x91, 0xd5, 0xcf, 0xe0, 0x89, 0x49, 0x05, 0xa1, 0x53, 0x39, 0x53, 0x68, 0xf8, 0x21, 0x68, 0x98, + 0x0c, 0xec, 0xc4, 0xf0, 0x2e, 0x00, 0x94, 0xc4, 0xaf, 0xe9, 0x41, 0x7e, 0x2b, 0x52, 0x27, 0x8b, 0xc4, 0xc5, 0xca, + 0xe5, 0x0c, 0xd8, 0x35, 0x5a, 0x2c, 0x33, 0x0c, 0xb5, 0x0b, 0x03, 0x60, 0xb9, 0xae, 0x61, 0xe8, 0x4e, 0xc0, 0xd2, + 0x05, 0x99, 0x98, 0xeb, 0x5a, 0x30, 0xae, 0x97, 0x71, 0xa2, 0x17, 0x90, 0x17, 0xe2, 0x77, 0x14, 0x54, 0xc1, 0x63, + 0xc2, 0xa7, 0x31, 0xb2, 0x8a, 0x38, 0xf5, 0xc6, 0x08, 0x15, 0x3a, 0x0d, 0x98, 0x61, 0x44, 0xfd, 0xf4, 0x8c, 0xb0, + 0x71, 0xb2, 0x10, 0x7e, 0xb3, 0x34, 0xcd, 0xc1, 0xb3, 0x75, 0x94, 0x9f, 0x3f, 0x5b, 0xa7, 0x79, 0xff, 0xd9, 0xda, + 0x97, 0xb6, 0x02, 0xfa, 0x95, 0x4e, 0x86, 0x02, 0x03, 0x04, 0xc3, 0x20, 0xbf, 0x2d, 0x3c, 0x77, 0x8a, 0xf9, 0xc2, + 0x2e, 0xa3, 0x72, 0x0d, 0x55, 0xf7, 0x7d, 0xae, 0xa0, 0x5f, 0x24, 0xc1, 0xdc, 0x4f, 0x1e, 0x48, 0x9f, 0x6f, 0xa9, + 0x4a, 0x7f, 0x53, 0xd7, 0x08, 0xd1, 0x13, 0x00, 0x08, 0xe7, 0xeb, 0xda, 0xb7, 0xb2, 0x8c, 0xf1, 0xd9, 0x4a, 0xa5, + 0x26, 0x7c, 0xeb, 0x56, 0x7f, 0xc9, 0x9c, 0x31, 0xcb, 0xfc, 0x20, 0xa4, 0x26, 0x3d, 0x91, 0xad, 0xbe, 0x36, 0xbd, + 0xb4, 0x3c, 0xbd, 0xa8, 0xbc, 0x7f, 0x70, 0x32, 0x74, 0x05, 0xd0, 0xb8, 0x71, 0x66, 0x98, 0xc5, 0xaa, 0x79, 0x45, + 0xe9, 0xdd, 0x7f, 0x75, 0x39, 0x18, 0x2c, 0x47, 0x04, 0xcb, 0xc1, 0xa2, 0x51, 0x3c, 0x66, 0x7f, 0x7b, 0x7f, 0x21, + 0xd3, 0x66, 0x81, 0x04, 0x68, 0xc0, 0x37, 0x66, 0x8a, 0xf4, 0x43, 0x82, 0xb4, 0x03, 0x25, 0xb8, 0xd2, 0xe4, 0x16, + 0x4a, 0x72, 0x5d, 0x3b, 0xa7, 0xb1, 0xb3, 0x31, 0x8d, 0xba, 0x1f, 0x63, 0xab, 0x24, 0x3f, 0x3d, 0xa0, 0xda, 0x74, + 0xdb, 0x51, 0x25, 0x00, 0x43, 0x02, 0x33, 0x2c, 0xa0, 0x00, 0x19, 0x3e, 0xfb, 0x5e, 0xc1, 0x50, 0x38, 0x73, 0x94, + 0xb3, 0x7b, 0xe7, 0x65, 0x52, 0x05, 0x5b, 0xe9, 0x67, 0xa7, 0x98, 0xb3, 0x0b, 0xee, 0x6b, 0x88, 0xf2, 0x71, 0x7a, + 0x40, 0x8f, 0x5a, 0xe5, 0x44, 0x14, 0x9d, 0x08, 0xd6, 0xae, 0xcb, 0x3b, 0x78, 0xd4, 0x51, 0x81, 0x14, 0xf1, 0x50, + 0xea, 0xe7, 0xba, 0x36, 0xe7, 0xa4, 0x11, 0x0f, 0x27, 0x04, 0xb1, 0x06, 0x5c, 0x38, 0xbb, 0xba, 0x36, 0xf7, 0x57, + 0x38, 0x73, 0xf1, 0xc6, 0x5f, 0x19, 0x1e, 0x7f, 0x55, 0x9c, 0xb5, 0xb4, 0x7c, 0xd6, 0x46, 0x7c, 0x71, 0xc1, 0x91, + 0x40, 0x72, 0xd6, 0x33, 0x54, 0xd0, 0x36, 0x2c, 0xee, 0x4c, 0x2c, 0xee, 0x78, 0xc3, 0xe2, 0x8e, 0xb7, 0x2c, 0x6e, + 0xc8, 0x17, 0x52, 0x93, 0xa0, 0x4b, 0xd0, 0x39, 0x4c, 0x02, 0x8f, 0x13, 0x1a, 0x5d, 0x7e, 0xce, 0x10, 0x4e, 0x76, + 0x1a, 0x82, 0x71, 0xd4, 0x06, 0x58, 0x35, 0xc1, 0x45, 0x01, 0x44, 0x7d, 0xe2, 0xf2, 0xd4, 0x89, 0x79, 0x43, 0x0e, + 0x4e, 0x23, 0xac, 0xce, 0x17, 0x76, 0x29, 0xe5, 0x17, 0x37, 0x66, 0x1b, 0x66, 0x3a, 0xdb, 0x32, 0xd3, 0x51, 0xe9, + 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x54, 0x27, 0x05, 0x7b, 0x10, 0x0c, 0x46, 0x71, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, + 0xab, 0xec, 0xa8, 0x85, 0x9f, 0xa6, 0xf7, 0x71, 0x02, 0x1a, 0x17, 0xe8, 0xe6, 0x71, 0x5b, 0x6a, 0x1e, 0x44, 0x3c, + 0x98, 0xcb, 0xc6, 0xcd, 0x54, 0xbc, 0x57, 0xb7, 0x54, 0xab, 0xd3, 0xa1, 0x1a, 0x0b, 0x3f, 0xcb, 0x58, 0x82, 0x40, + 0xf7, 0x21, 0xea, 0xf7, 0xff, 0x93, 0x6d, 0xd6, 0x80, 0x43, 0x42, 0x05, 0xab, 0x23, 0x86, 0x5e, 0x00, 0x6d, 0x95, + 0x88, 0x8b, 0x58, 0x09, 0x0c, 0x97, 0x48, 0xc0, 0xff, 0x84, 0xc7, 0xd5, 0x48, 0x14, 0xd7, 0x25, 0xef, 0xc8, 0x74, + 0x16, 0xfe, 0xf8, 0x03, 0x28, 0xf6, 0x8c, 0x96, 0x05, 0x46, 0xba, 0x6a, 0x18, 0xb8, 0x84, 0x88, 0xbd, 0x51, 0x81, + 0x24, 0x11, 0x4b, 0x72, 0x13, 0x28, 0xf0, 0x9e, 0xf4, 0xed, 0xc9, 0xcd, 0xba, 0x95, 0x1f, 0x4c, 0x03, 0xb3, 0x86, + 0x35, 0x01, 0xb5, 0x85, 0xfd, 0x33, 0xc9, 0x73, 0x85, 0x96, 0x77, 0x64, 0x82, 0xe4, 0xf7, 0x1a, 0xf2, 0x99, 0xba, + 0x82, 0xa1, 0x1d, 0x24, 0x70, 0x6b, 0x5d, 0xbb, 0x37, 0xf9, 0xf3, 0x29, 0xfe, 0xf2, 0x6e, 0xf2, 0xe7, 0x43, 0xfc, + 0xd5, 0xba, 0xc1, 0xcc, 0x75, 0x0d, 0x8c, 0xbc, 0x32, 0x67, 0xfd, 0xac, 0xb4, 0x9f, 0xc8, 0xfe, 0xec, 0x11, 0xdb, + 0x86, 0x2f, 0xf0, 0xd3, 0x67, 0xeb, 0x14, 0x3c, 0x2e, 0xd5, 0x39, 0x44, 0x4e, 0x62, 0xe6, 0x8d, 0xe5, 0xd3, 0x0d, + 0xe5, 0x43, 0xf3, 0xbf, 0x7c, 0xf1, 0xe3, 0x2e, 0x89, 0x8b, 0x3b, 0xa5, 0x2c, 0x86, 0xb8, 0x1d, 0x06, 0x91, 0x9f, + 0x3c, 0xdc, 0x12, 0x7b, 0x61, 0x08, 0xda, 0x5d, 0x8a, 0x57, 0x88, 0xbc, 0x2c, 0xab, 0xbb, 0x32, 0x45, 0xc0, 0xfb, + 0xc0, 0x2f, 0xfa, 0xfe, 0xdf, 0x13, 0x85, 0x6c, 0x2b, 0x31, 0xa0, 0x7c, 0x41, 0x4a, 0x1f, 0xba, 0x7d, 0xb6, 0x36, + 0x58, 0xbd, 0x9b, 0xca, 0x6c, 0x2b, 0x74, 0x21, 0x2c, 0x0f, 0x32, 0xb3, 0xf3, 0x71, 0xd0, 0x45, 0x7d, 0xd6, 0x30, + 0x5e, 0xd9, 0xcf, 0xd6, 0xd9, 0xb9, 0x3e, 0xf7, 0x93, 0x4f, 0x6c, 0x6c, 0x8f, 0x82, 0x64, 0x14, 0x32, 0xbd, 0xab, + 0x0f, 0x43, 0x3f, 0xfa, 0xc4, 0x1f, 0xed, 0x78, 0x99, 0xa1, 0x86, 0x7a, 0x27, 0xef, 0x2b, 0x60, 0x42, 0x22, 0x3b, + 0x24, 0x56, 0x1b, 0xa0, 0xa0, 0xbd, 0x96, 0x02, 0xaf, 0x82, 0x50, 0x2c, 0x6a, 0x59, 0x60, 0x60, 0x09, 0x4a, 0x73, + 0xf0, 0x58, 0xb5, 0x74, 0x5c, 0x2f, 0xdd, 0x52, 0xa7, 0x4a, 0xc2, 0x4a, 0x99, 0x72, 0xf1, 0x16, 0x7b, 0xf8, 0xfd, + 0x9f, 0xa3, 0x64, 0xd8, 0xfb, 0x7f, 0x4e, 0xf6, 0xf2, 0x65, 0x33, 0x84, 0x52, 0x9b, 0x3c, 0x25, 0x1e, 0xf1, 0x71, + 0x4e, 0x60, 0x6e, 0xfe, 0xb4, 0xda, 0xd8, 0x4f, 0xd3, 0xe5, 0x9c, 0x8d, 0x49, 0x33, 0x78, 0x5e, 0x0c, 0xaa, 0xcc, + 0x59, 0xa8, 0x03, 0xfb, 0x75, 0xd9, 0x3a, 0x3e, 0x7c, 0x0d, 0x16, 0x0b, 0x40, 0x50, 0xc6, 0x93, 0x89, 0x5e, 0xf0, + 0xf8, 0x3b, 0x9a, 0x79, 0x87, 0xbf, 0x2e, 0x7f, 0x78, 0xeb, 0xfe, 0x20, 0x1b, 0x47, 0x40, 0x18, 0x0b, 0xf5, 0x2b, + 0xa7, 0x8b, 0x95, 0xf1, 0x8a, 0x19, 0x4d, 0xfc, 0x68, 0xf3, 0x74, 0xae, 0x4b, 0x5b, 0x7c, 0xc1, 0xd8, 0x18, 0x08, + 0x6e, 0xab, 0x56, 0x7a, 0x1b, 0xb2, 0x3b, 0x26, 0x55, 0xbb, 0xf5, 0x8f, 0x35, 0xb4, 0xc0, 0xd8, 0x73, 0x5c, 0x65, + 0xcc, 0xa9, 0x3a, 0x65, 0x4a, 0x03, 0x9c, 0x03, 0x9f, 0xb9, 0x7a, 0xc4, 0x2a, 0x47, 0x6a, 0x60, 0xe9, 0xca, 0x00, + 0x36, 0x8e, 0xec, 0x7c, 0x43, 0x79, 0x17, 0x13, 0x4f, 0x37, 0x8f, 0xcd, 0xf2, 0xcc, 0x2e, 0xc4, 0xea, 0xe6, 0x70, + 0x0a, 0xe1, 0xe4, 0x19, 0x85, 0x38, 0x64, 0x13, 0xc4, 0x9a, 0x84, 0x64, 0x3a, 0x49, 0x5f, 0x84, 0xb5, 0x23, 0x9a, + 0xfd, 0x0a, 0x39, 0x54, 0xe3, 0xda, 0x68, 0xe5, 0x99, 0x0f, 0x31, 0xa1, 0x6b, 0xc4, 0xd2, 0x74, 0x23, 0xc0, 0xe4, + 0xa2, 0x5b, 0x7a, 0x51, 0xbb, 0x0c, 0x8f, 0xa2, 0xdc, 0x72, 0x2d, 0x20, 0x09, 0x70, 0x82, 0xd5, 0x6f, 0xe1, 0xf5, + 0x72, 0x3b, 0xe7, 0xf6, 0x2a, 0xc9, 0x74, 0xa8, 0x73, 0x5b, 0x82, 0x4d, 0xef, 0xef, 0x75, 0x3e, 0xa8, 0xd2, 0x35, + 0xdd, 0x38, 0x34, 0xa3, 0x84, 0x7a, 0x6b, 0xe2, 0x22, 0xec, 0x40, 0x8c, 0xa9, 0x82, 0x5f, 0xd9, 0x64, 0xc2, 0x46, + 0x59, 0x6a, 0x0a, 0xe1, 0x91, 0x8c, 0x1e, 0x0b, 0x5e, 0x43, 0x4f, 0xfa, 0xfa, 0x4f, 0xe0, 0x43, 0x2f, 0x82, 0x2c, + 0xf1, 0x01, 0x09, 0x9e, 0xa9, 0x19, 0x4c, 0xd4, 0x63, 0x19, 0x44, 0xfc, 0x2b, 0x90, 0x1c, 0xbc, 0xa1, 0x1c, 0x87, + 0xc6, 0xef, 0x9f, 0x62, 0x5f, 0xc4, 0xd2, 0xaa, 0x65, 0x3b, 0x2a, 0xda, 0x76, 0x7c, 0xd7, 0xde, 0x0f, 0x1d, 0xcf, + 0xcd, 0x75, 0x0b, 0x7c, 0xb7, 0x3e, 0xed, 0x7b, 0xe8, 0xb1, 0x55, 0x1b, 0x5a, 0x2d, 0xa3, 0xc7, 0xb4, 0x6b, 0x79, + 0xaf, 0x3c, 0xdd, 0x22, 0x93, 0x39, 0x05, 0xb7, 0x8d, 0xe2, 0x3b, 0x96, 0x7c, 0xf1, 0x54, 0xca, 0x9d, 0xef, 0x37, + 0x9e, 0x23, 0xcf, 0x05, 0x24, 0x9c, 0xc5, 0x8b, 0x47, 0x4c, 0xa1, 0xad, 0x5b, 0xfa, 0x28, 0x8c, 0x53, 0xa6, 0xce, + 0x81, 0x84, 0x20, 0x5f, 0x38, 0x89, 0x9f, 0xdf, 0xbf, 0xfd, 0xf0, 0x41, 0xb7, 0x30, 0x13, 0x68, 0xaa, 0xf6, 0xce, + 0x37, 0xd4, 0x0e, 0xec, 0xdf, 0xb8, 0xef, 0xe8, 0x86, 0x21, 0xa6, 0xb6, 0xbc, 0xe7, 0xa8, 0xac, 0xb6, 0xe5, 0xf8, + 0xcd, 0xc3, 0xbf, 0x4c, 0x9c, 0xe8, 0x5e, 0xf3, 0x6a, 0xc0, 0x0d, 0xdb, 0xaf, 0xb7, 0x52, 0xc9, 0x3c, 0x88, 0x6e, + 0x1b, 0x4a, 0xfd, 0x55, 0x43, 0x29, 0xb0, 0x72, 0x35, 0x5c, 0xb5, 0x8c, 0xe7, 0x0a, 0x69, 0x00, 0x89, 0x9c, 0x77, + 0x81, 0x4b, 0xe1, 0xa7, 0xbe, 0x60, 0xd0, 0x3c, 0x92, 0x7b, 0x75, 0xd4, 0x0d, 0xc5, 0x9c, 0x09, 0x92, 0xb0, 0x1d, + 0x85, 0x60, 0xf0, 0xc7, 0x54, 0xad, 0x5c, 0x99, 0x6c, 0x94, 0xe6, 0xba, 0x4a, 0x27, 0x44, 0xde, 0xde, 0x66, 0x6c, + 0xbe, 0x60, 0x89, 0x9f, 0x2d, 0x13, 0x76, 0x1b, 0xc6, 0xf7, 0x4f, 0x0a, 0x73, 0xfa, 0x1d, 0x95, 0x67, 0xc1, 0x74, + 0x26, 0x6b, 0x9f, 0x1b, 0xac, 0x2f, 0x17, 0x70, 0xeb, 0x07, 0xf2, 0xff, 0xfc, 0xdb, 0x71, 0xfe, 0xf3, 0xef, 0x9d, + 0x55, 0xa1, 0xfb, 0x7c, 0x60, 0x65, 0xfd, 0x3d, 0xf6, 0x45, 0xf3, 0x97, 0xca, 0x30, 0x6f, 0xae, 0x53, 0x5b, 0x04, + 0x78, 0x5f, 0x5b, 0x82, 0x5a, 0x61, 0x79, 0xdf, 0x3c, 0x6a, 0x60, 0x30, 0xaf, 0x9d, 0x23, 0x83, 0x4a, 0x5f, 0x34, + 0xb4, 0x81, 0xd9, 0xdd, 0x6b, 0x45, 0x7e, 0x3f, 0x84, 0x77, 0xcd, 0xe1, 0x0b, 0x87, 0xcf, 0xe5, 0x92, 0xaf, 0x07, + 0x03, 0x99, 0x5b, 0x4e, 0x6d, 0x0a, 0x26, 0xfe, 0xe7, 0xb5, 0x12, 0x7e, 0x79, 0x76, 0x5d, 0x93, 0x7c, 0xef, 0xfb, + 0xaf, 0x07, 0x68, 0x8c, 0x76, 0x3a, 0x4c, 0x0a, 0x62, 0x65, 0x23, 0x6a, 0x23, 0x63, 0xf2, 0x5a, 0xa7, 0x35, 0xbc, + 0x06, 0xa5, 0x98, 0x70, 0x2c, 0x1f, 0x98, 0xd6, 0xeb, 0x01, 0x17, 0x2c, 0x71, 0xfb, 0xd7, 0x6e, 0x75, 0x6b, 0x73, + 0xb1, 0x6c, 0x09, 0xe8, 0x96, 0x46, 0xfa, 0x1f, 0xac, 0xcc, 0x0a, 0x39, 0x1e, 0x0a, 0xf8, 0x41, 0xa2, 0x30, 0xc8, + 0x31, 0xdf, 0xc9, 0xbb, 0x4d, 0x36, 0x62, 0x3f, 0xef, 0xb6, 0x11, 0xbb, 0xda, 0xcb, 0x46, 0xec, 0xe7, 0xaf, 0x6e, + 0x23, 0xf6, 0x4e, 0xb5, 0x11, 0x83, 0x45, 0x7c, 0xcb, 0xf6, 0x32, 0xdc, 0x12, 0x56, 0x1b, 0xf1, 0x7d, 0xda, 0xf7, + 0x38, 0x49, 0x9b, 0x8e, 0x66, 0x0c, 0x64, 0x04, 0x7c, 0x55, 0xc2, 0x78, 0x0a, 0x46, 0x5c, 0x7f, 0xbc, 0xb9, 0x55, + 0x18, 0x4f, 0x55, 0x63, 0xab, 0x88, 0x47, 0x7c, 0x2d, 0xa2, 0x38, 0x91, 0x81, 0x93, 0x6b, 0x89, 0x98, 0x4f, 0xf6, + 0xa1, 0xa9, 0x64, 0xb5, 0x96, 0xd6, 0x6b, 0x2d, 0x61, 0x02, 0xd5, 0x45, 0xeb, 0x29, 0xd9, 0xb0, 0xf5, 0x52, 0xc4, + 0xb6, 0x50, 0x7b, 0x90, 0x56, 0xc2, 0x14, 0x27, 0x62, 0xad, 0xff, 0xba, 0xf2, 0xbe, 0xbf, 0xf6, 0x7a, 0x6d, 0x0f, + 0x9c, 0xb3, 0x81, 0xc3, 0xc4, 0x02, 0xb7, 0xd7, 0x6e, 0x43, 0xc1, 0xbd, 0x52, 0xd0, 0x82, 0x82, 0x40, 0x29, 0xe8, + 0x40, 0xc1, 0x48, 0x29, 0x38, 0x82, 0x82, 0xb1, 0x52, 0x70, 0x0c, 0x05, 0x77, 0x7a, 0x7e, 0x1d, 0xc9, 0xe1, 0x1e, + 0x9b, 0x37, 0x16, 0x31, 0x15, 0xa2, 0xec, 0xd8, 0xf2, 0xc0, 0x6a, 0xca, 0x9f, 0x76, 0x63, 0x8b, 0xa4, 0x8b, 0xdd, + 0xc4, 0xba, 0x9f, 0x31, 0x0a, 0x14, 0xfd, 0x06, 0xef, 0x1c, 0x27, 0x8b, 0xc1, 0x6e, 0x5a, 0x04, 0x60, 0x10, 0x70, + 0xd0, 0x74, 0x13, 0x04, 0x46, 0x3d, 0xb9, 0x72, 0x22, 0x88, 0x85, 0xb2, 0x96, 0xc5, 0x3b, 0xfa, 0x9c, 0x2d, 0xb7, + 0x40, 0x61, 0x71, 0x62, 0xa8, 0x52, 0xc9, 0xaf, 0x61, 0x77, 0xf0, 0x86, 0x0d, 0x97, 0x53, 0xed, 0x32, 0x9e, 0xee, + 0x34, 0x21, 0x50, 0x5f, 0xc1, 0x28, 0x75, 0x52, 0xbf, 0xd8, 0x62, 0x5b, 0xf2, 0x6f, 0xd1, 0x63, 0x5e, 0xae, 0x9f, + 0xc1, 0xd8, 0xb4, 0x8c, 0x0c, 0x58, 0xe0, 0x3b, 0x00, 0x23, 0x45, 0x87, 0x7f, 0x09, 0x70, 0x56, 0x9e, 0xaf, 0x7c, + 0x65, 0x3c, 0x67, 0x3f, 0xb2, 0x34, 0xf5, 0xa7, 0xa2, 0x7e, 0x7d, 0x9c, 0x60, 0xb4, 0x23, 0xf9, 0x2f, 0x04, 0x20, + 0x48, 0xf2, 0x82, 0x9a, 0x6d, 0x46, 0x12, 0xdf, 0x6b, 0x60, 0xfd, 0x03, 0x1b, 0xaa, 0xb0, 0x53, 0x08, 0x1c, 0x58, + 0xc2, 0xb2, 0x45, 0x01, 0x1c, 0xfe, 0x3b, 0x16, 0x56, 0x0b, 0x33, 0x7f, 0x5a, 0x2d, 0xa2, 0x7d, 0x90, 0xab, 0x63, + 0x93, 0x0a, 0xfd, 0x52, 0xe1, 0x97, 0x68, 0xa8, 0xc3, 0x78, 0xfa, 0x87, 0xaa, 0xa7, 0xb7, 0x98, 0x15, 0x7c, 0x88, + 0xac, 0x20, 0x1b, 0x38, 0x08, 0x63, 0xcd, 0x01, 0x10, 0x76, 0xa3, 0x6c, 0x66, 0xa3, 0x6b, 0x99, 0xd1, 0x8a, 0x4c, + 0xcb, 0xc1, 0xb5, 0x5d, 0x57, 0x1d, 0x6a, 0xbb, 0xc9, 0x74, 0xe8, 0x1b, 0x5e, 0xeb, 0xd8, 0x12, 0x7f, 0x8e, 0xdb, + 0x31, 0x73, 0xec, 0x41, 0x1b, 0x07, 0x77, 0xeb, 0x49, 0x1c, 0x65, 0xf6, 0xc4, 0x9f, 0x07, 0xe1, 0x43, 0x77, 0x1e, + 0x47, 0x71, 0xba, 0xf0, 0x47, 0xac, 0x57, 0x30, 0xd4, 0x3d, 0x0c, 0xd5, 0xc0, 0xbd, 0x05, 0x3d, 0xa7, 0x95, 0xb0, + 0x39, 0xb5, 0x96, 0x91, 0x18, 0x26, 0x21, 0x5b, 0xe5, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, + 0x8a, 0x94, 0x87, 0x79, 0x80, 0xe0, 0x46, 0xbd, 0x85, 0x3f, 0xc6, 0xc8, 0x84, 0x4e, 0xab, 0x93, 0xb0, 0xb9, 0xe6, + 0x74, 0x36, 0x76, 0x9e, 0xc4, 0xf7, 0x67, 0x30, 0x5a, 0x6c, 0x6c, 0xa7, 0x2c, 0x9c, 0xe0, 0x1b, 0x1b, 0x3d, 0x4b, + 0x44, 0x3f, 0x36, 0x32, 0xe2, 0xd0, 0x1b, 0x9b, 0xf7, 0xe0, 0x75, 0xb7, 0xa5, 0xb9, 0xbd, 0x79, 0x10, 0xd9, 0x34, + 0x9d, 0x63, 0x77, 0xa1, 0xf4, 0xa5, 0xc2, 0xcf, 0x5c, 0x63, 0x75, 0x4f, 0x73, 0x7b, 0xc0, 0xac, 0x4d, 0xc2, 0xf8, + 0xbe, 0x3b, 0x0b, 0xc6, 0x63, 0x16, 0xf5, 0x70, 0xcc, 0xb2, 0x90, 0x85, 0x61, 0xb0, 0x48, 0x83, 0xb4, 0x37, 0xf7, + 0x57, 0xbc, 0xd7, 0xc3, 0x4d, 0xbd, 0xb6, 0x79, 0xaf, 0xed, 0xbd, 0x7b, 0x55, 0xba, 0x01, 0x2f, 0x16, 0xea, 0x87, + 0x0f, 0xad, 0xa3, 0xb9, 0x95, 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x61, 0xeb, 0xb9, 0x9f, 0x4c, 0x83, 0xa8, 0xeb, 0xe6, + 0xce, 0xdd, 0x9a, 0x36, 0xc6, 0xd3, 0x93, 0x93, 0x93, 0xdc, 0x19, 0x8b, 0x27, 0x77, 0x3c, 0xce, 0x9d, 0x91, 0x78, + 0x9a, 0x4c, 0x5c, 0x77, 0x32, 0xc9, 0x9d, 0x40, 0x14, 0xb4, 0x5b, 0xa3, 0x71, 0xbb, 0x95, 0x3b, 0xf7, 0x4a, 0x8d, + 0xdc, 0x61, 0xfc, 0x29, 0x61, 0xe3, 0x1e, 0x6e, 0x24, 0x32, 0x2b, 0xed, 0x1e, 0xbb, 0x6e, 0x8e, 0x18, 0xe0, 0xba, + 0x84, 0x9b, 0x50, 0xd6, 0x73, 0xb3, 0xde, 0xbb, 0xa6, 0x56, 0x7c, 0x6e, 0x34, 0x6a, 0xac, 0x37, 0xf6, 0x93, 0x4f, + 0x37, 0x9a, 0x32, 0x0b, 0xdf, 0xa7, 0x6a, 0x6b, 0x01, 0x06, 0x7b, 0xd5, 0x85, 0x90, 0x5d, 0xbd, 0x61, 0x9c, 0xc0, + 0x99, 0x4d, 0xfc, 0x71, 0xb0, 0x4c, 0xbb, 0x5e, 0x6b, 0xb1, 0x12, 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0xba, + 0x69, 0x1c, 0x06, 0x63, 0x51, 0xb4, 0xe9, 0x2c, 0x79, 0x2d, 0xb3, 0x87, 0x0e, 0xeb, 0x01, 0x86, 0x5d, 0xf0, 0xc3, + 0x50, 0x73, 0xda, 0xa9, 0xc6, 0xfc, 0x14, 0xe5, 0xcb, 0x9a, 0x9b, 0x12, 0x5c, 0xd0, 0x39, 0xdd, 0x3b, 0x5c, 0xac, + 0xe4, 0x9e, 0xf7, 0x8e, 0x16, 0xab, 0xfc, 0xdb, 0x39, 0x1b, 0x07, 0xbe, 0x66, 0x14, 0xbb, 0xc9, 0x73, 0x41, 0x06, + 0x6d, 0xae, 0x37, 0x6c, 0x53, 0x71, 0x2c, 0x20, 0xb4, 0xe1, 0x93, 0x60, 0xbe, 0x88, 0x93, 0xcc, 0x8f, 0xb2, 0x3c, + 0x1f, 0xdc, 0xe4, 0x79, 0xef, 0x2a, 0x30, 0xae, 0xff, 0x61, 0xd0, 0x3d, 0x4d, 0x3a, 0x9b, 0xdc, 0xbc, 0xb1, 0xde, + 0x32, 0xd5, 0x66, 0x04, 0xae, 0x31, 0xb4, 0x17, 0x51, 0x2b, 0xd3, 0x2d, 0x59, 0xaf, 0x4c, 0x40, 0x96, 0xd5, 0xc9, + 0x06, 0xa5, 0x5c, 0x05, 0x6f, 0x20, 0xa8, 0xf0, 0x96, 0xf5, 0xaf, 0x14, 0xfb, 0x13, 0x20, 0x56, 0xb0, 0x32, 0xf9, + 0x15, 0x3c, 0xdb, 0x44, 0x33, 0x7e, 0xb7, 0x9b, 0x66, 0xfc, 0x25, 0xdb, 0x87, 0x66, 0xfc, 0xee, 0xab, 0xd3, 0x8c, + 0xcf, 0xea, 0x7e, 0x05, 0x17, 0x71, 0x5f, 0x97, 0x1a, 0x06, 0xb8, 0x9a, 0x12, 0x8a, 0xd8, 0x73, 0xf1, 0xbb, 0xdd, + 0x00, 0x44, 0x6f, 0x94, 0x83, 0x8e, 0x6e, 0x6e, 0x90, 0xc7, 0xbe, 0x8b, 0xfa, 0x7f, 0x4f, 0xd4, 0xe7, 0xc9, 0xa4, + 0xff, 0x26, 0x56, 0x0a, 0xe4, 0x13, 0x37, 0xbe, 0x28, 0x45, 0x57, 0xa0, 0x37, 0xc2, 0x0a, 0x13, 0xf3, 0x4f, 0x80, + 0x73, 0x36, 0x59, 0x1d, 0x8f, 0xa5, 0xf5, 0x59, 0xaf, 0x3c, 0x04, 0x43, 0x9a, 0x7c, 0x0a, 0x17, 0x9c, 0x9a, 0x28, + 0x71, 0xca, 0x32, 0xee, 0x33, 0xfb, 0xfd, 0xc3, 0xc5, 0xd8, 0xb8, 0x88, 0xcd, 0x3c, 0x48, 0xdf, 0x55, 0x1d, 0x60, + 0xb8, 0xee, 0xa7, 0xaf, 0x4e, 0x27, 0xe7, 0x16, 0x64, 0x6a, 0x82, 0x69, 0x78, 0x4d, 0xcd, 0xcf, 0x4b, 0x33, 0xed, + 0xaa, 0x0d, 0x79, 0xa2, 0xab, 0xda, 0x65, 0xcc, 0xbd, 0x0f, 0xd6, 0x9c, 0x02, 0xc4, 0xdc, 0x5d, 0xe8, 0x37, 0x3c, + 0xa6, 0xe6, 0xc1, 0x38, 0xcf, 0xcd, 0x9e, 0x00, 0x84, 0x72, 0xd1, 0xb2, 0x5d, 0x44, 0x5c, 0x7a, 0x2f, 0x6d, 0x1a, + 0xb8, 0x86, 0x90, 0xd4, 0x7f, 0x17, 0xa0, 0x50, 0xe7, 0xca, 0x42, 0x0e, 0x33, 0x5d, 0x23, 0xf0, 0x91, 0xa1, 0x85, + 0x32, 0x21, 0xd0, 0x00, 0x4b, 0xf8, 0x8b, 0x57, 0xa2, 0xa0, 0x6e, 0xc3, 0x49, 0xc0, 0x41, 0x8b, 0x00, 0xf0, 0xf2, + 0x17, 0x72, 0x6d, 0x42, 0x3b, 0xbc, 0x0e, 0x3e, 0xe4, 0xba, 0xa4, 0xfd, 0x70, 0xfb, 0x9d, 0x9d, 0x1e, 0x40, 0x83, + 0xb3, 0x8a, 0xe1, 0xc0, 0x0e, 0x0b, 0x45, 0x20, 0x25, 0xd2, 0x7b, 0xcb, 0x49, 0xef, 0xb5, 0x17, 0x6b, 0x11, 0x21, + 0x23, 0xf3, 0x17, 0x36, 0xb0, 0xf8, 0x88, 0x7b, 0x39, 0xc6, 0x53, 0x82, 0x71, 0xf4, 0x96, 0x29, 0xe0, 0x46, 0x64, + 0x54, 0x11, 0xff, 0xf4, 0x46, 0xcb, 0x24, 0x8d, 0x93, 0xee, 0x22, 0x0e, 0xa2, 0x8c, 0x25, 0x39, 0x82, 0xea, 0x1a, + 0xe1, 0x23, 0xc0, 0x73, 0xb3, 0x8e, 0x17, 0xfe, 0x28, 0xc8, 0x1e, 0xba, 0x2e, 0x27, 0x29, 0xdc, 0x1e, 0xa7, 0x0e, + 0xdc, 0xc6, 0xfa, 0x5d, 0x0e, 0xcd, 0x97, 0x48, 0xf8, 0x25, 0x75, 0x72, 0x46, 0xdd, 0xe6, 0x3d, 0xe5, 0x2d, 0xc5, + 0x08, 0x01, 0xf2, 0xc3, 0x4f, 0xec, 0x29, 0x60, 0x79, 0x58, 0x6a, 0x77, 0xcc, 0xa6, 0x16, 0x62, 0x6d, 0x90, 0xcb, + 0x8b, 0x3f, 0xa7, 0x63, 0x6a, 0x6e, 0x73, 0x31, 0x50, 0x3c, 0xe6, 0x3e, 0x23, 0xeb, 0xfa, 0x90, 0x51, 0xcb, 0xda, + 0xa7, 0xe6, 0x90, 0x4d, 0xe2, 0x84, 0x51, 0x3c, 0x59, 0xef, 0x64, 0xb1, 0xda, 0xbf, 0xfb, 0xed, 0xd3, 0x6f, 0xee, + 0x27, 0x8a, 0x33, 0x43, 0x74, 0x66, 0xee, 0xe8, 0xad, 0x7e, 0x9f, 0x01, 0x69, 0x48, 0x90, 0x1f, 0x51, 0xe8, 0xae, + 0xae, 0xae, 0xf7, 0x1a, 0xc3, 0x76, 0x2d, 0x62, 0x7e, 0xe7, 0x25, 0x2c, 0xf4, 0xb3, 0xe0, 0x4e, 0xd0, 0x8c, 0xed, + 0xa3, 0xc5, 0x4a, 0xac, 0x31, 0x5e, 0x78, 0x8f, 0x58, 0xa4, 0xca, 0x50, 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0x7a, + 0xb5, 0xd9, 0x88, 0x48, 0x16, 0x95, 0x9b, 0xbe, 0xb3, 0x58, 0xa9, 0x57, 0x74, 0xd1, 0x4c, 0xde, 0xd4, 0xd5, 0x10, + 0x64, 0xf3, 0x60, 0x3c, 0x0e, 0x59, 0x5e, 0x5a, 0xe8, 0xf2, 0x5a, 0x2a, 0xc0, 0x91, 0x70, 0xf0, 0x87, 0x69, 0x1c, + 0x2e, 0x33, 0xd6, 0x0c, 0x2e, 0x02, 0x4e, 0xcb, 0x2d, 0x80, 0x83, 0xbf, 0xcb, 0x63, 0xed, 0x00, 0xb9, 0x0d, 0xdb, + 0xc4, 0xed, 0x41, 0xc4, 0x61, 0xbb, 0x5d, 0x1e, 0x3a, 0xbc, 0x92, 0x83, 0xb6, 0x1a, 0x26, 0x62, 0xc1, 0xb5, 0x44, + 0xd8, 0x5b, 0x73, 0x3c, 0x5e, 0x26, 0xa3, 0xae, 0xca, 0xa2, 0xbc, 0x3c, 0x99, 0x3f, 0xe6, 0x8c, 0xbd, 0x6a, 0x3e, + 0x63, 0xaf, 0xc4, 0x19, 0xdb, 0xbe, 0x33, 0x9f, 0x4e, 0x3c, 0xf8, 0xaf, 0x57, 0x4c, 0xa8, 0xeb, 0x6a, 0xed, 0xc5, + 0x4a, 0xf3, 0x16, 0x2b, 0xcd, 0x6e, 0x2d, 0x56, 0x1a, 0x76, 0x8d, 0xf6, 0x20, 0x96, 0xd3, 0x32, 0x2d, 0x57, 0x83, + 0x42, 0xf8, 0x73, 0x4b, 0xaf, 0xbc, 0x43, 0x78, 0x07, 0xad, 0x3a, 0xf5, 0x77, 0xad, 0xed, 0x47, 0x9d, 0xce, 0x92, + 0x40, 0xda, 0xa6, 0x93, 0xf9, 0xc3, 0x21, 0x1b, 0x77, 0x27, 0xf1, 0x68, 0x99, 0xfe, 0x8b, 0x8f, 0x9f, 0x03, 0x71, + 0x2b, 0x22, 0xa8, 0xf4, 0x23, 0x9a, 0x82, 0xa2, 0xe4, 0x8e, 0x89, 0x1e, 0xd6, 0x72, 0x9d, 0xba, 0x14, 0x1e, 0xb9, + 0xe5, 0x1c, 0x36, 0x6c, 0xf2, 0x66, 0x40, 0xff, 0x61, 0xab, 0xb4, 0x19, 0xc5, 0x7c, 0x01, 0x58, 0xb6, 0x82, 0xe3, + 0xf1, 0xd0, 0xe0, 0xab, 0xe9, 0x9e, 0x34, 0x0f, 0xf7, 0x5a, 0x7c, 0xe9, 0x46, 0x5c, 0x2a, 0xfc, 0xde, 0xe2, 0x8e, + 0x29, 0xdb, 0x7b, 0xdd, 0xb4, 0x47, 0x6a, 0xbd, 0x6e, 0xb9, 0x10, 0x8a, 0xba, 0x7b, 0x62, 0xf9, 0xa7, 0xaf, 0x0e, + 0xe1, 0x3f, 0xa2, 0xea, 0x7f, 0xc9, 0x9a, 0x08, 0xf5, 0x8b, 0xb2, 0x25, 0x38, 0x91, 0x4a, 0x48, 0x88, 0xef, 0x5f, + 0x7f, 0x32, 0x79, 0x5c, 0x83, 0xbd, 0x6b, 0x93, 0x29, 0x55, 0xb5, 0xf6, 0xf7, 0x71, 0x0c, 0xa9, 0x3b, 0xeb, 0xd5, + 0x05, 0x78, 0xc8, 0xd8, 0x3d, 0xeb, 0x43, 0x23, 0xc1, 0x47, 0x90, 0x16, 0x5f, 0xc7, 0x36, 0xc4, 0x4a, 0xbc, 0xdd, + 0xc4, 0x4a, 0xbc, 0xd9, 0xcd, 0x4a, 0xfc, 0x75, 0x2f, 0x56, 0xe2, 0xcd, 0x57, 0x67, 0x25, 0xde, 0xd6, 0x59, 0x89, + 0xab, 0x58, 0xd8, 0xcf, 0x5a, 0x17, 0x4b, 0xfe, 0xf3, 0x23, 0x29, 0xe5, 0x2e, 0xe3, 0x7e, 0xc7, 0xa5, 0x90, 0xc7, + 0x57, 0xbf, 0x9b, 0xb1, 0xc0, 0x8d, 0xf8, 0x1e, 0xcd, 0xc9, 0x0a, 0xd6, 0x82, 0x63, 0x76, 0xfc, 0x8e, 0x52, 0x1c, + 0xc6, 0xd1, 0xf4, 0x67, 0x50, 0xca, 0x82, 0x38, 0x30, 0x51, 0x5e, 0x04, 0xe9, 0xcf, 0xf1, 0x62, 0xb9, 0xb8, 0x80, + 0xbe, 0x3e, 0x06, 0x69, 0x30, 0x0c, 0x99, 0xf4, 0x44, 0x26, 0xf3, 0x37, 0x2e, 0x13, 0x07, 0x8b, 0x53, 0xf1, 0xd3, + 0x5f, 0x89, 0x9f, 0x68, 0x93, 0xca, 0x7f, 0x93, 0x5d, 0x9d, 0xde, 0xcc, 0x88, 0x08, 0x25, 0xa0, 0x32, 0xe8, 0xc7, + 0x33, 0x23, 0x57, 0xb1, 0xd9, 0x30, 0x4b, 0x61, 0xef, 0xb0, 0xb1, 0x1f, 0x56, 0x63, 0x6a, 0x96, 0xa6, 0x25, 0x43, + 0x70, 0xd5, 0xc5, 0xf0, 0xf3, 0x78, 0x99, 0xb2, 0x71, 0x7c, 0x1f, 0xe9, 0x56, 0x24, 0x9d, 0x0c, 0x40, 0xc3, 0x29, + 0xdb, 0x60, 0xf2, 0xc8, 0x0f, 0x48, 0x28, 0xc7, 0x89, 0xa1, 0x43, 0xee, 0xd2, 0xe5, 0xc2, 0x26, 0x55, 0xb3, 0x8d, + 0x53, 0xd4, 0x65, 0x96, 0xa3, 0x27, 0x86, 0x11, 0xf7, 0x1f, 0xd7, 0x52, 0x98, 0x6a, 0xc4, 0x0e, 0x97, 0x0a, 0xa7, + 0x46, 0x24, 0x84, 0x8b, 0x22, 0x0e, 0x46, 0xc3, 0xc2, 0xf1, 0x37, 0xe4, 0xba, 0x5a, 0xbc, 0x85, 0x28, 0x22, 0xf9, + 0x92, 0xaf, 0x07, 0x8f, 0x0a, 0x41, 0x8f, 0xaf, 0x15, 0x30, 0xbe, 0xbb, 0x63, 0x49, 0xe8, 0x3f, 0x18, 0x66, 0x1e, + 0x47, 0x3f, 0x02, 0x00, 0xde, 0xc4, 0xf7, 0x91, 0x5a, 0x01, 0x93, 0xb5, 0x34, 0xec, 0xa5, 0xc6, 0xf8, 0x25, 0xe0, + 0xb8, 0xa2, 0x8c, 0x00, 0xd2, 0xe4, 0x4e, 0xd9, 0xdf, 0x2d, 0xfa, 0xf7, 0x1f, 0x66, 0x6e, 0x5d, 0xc6, 0xf2, 0x43, + 0x7f, 0x5b, 0xec, 0xf1, 0x99, 0xe7, 0xcf, 0x9f, 0x6c, 0x9e, 0x76, 0x39, 0x3d, 0x7b, 0x43, 0x6b, 0x73, 0xe3, 0x29, + 0x80, 0x51, 0x5c, 0xc5, 0xcb, 0xd1, 0x0c, 0x0d, 0x5d, 0xbf, 0xde, 0x7c, 0x33, 0xe8, 0x13, 0xb3, 0x94, 0xca, 0xa9, + 0x57, 0x8a, 0x0a, 0x28, 0xe0, 0xf7, 0xdf, 0x42, 0x00, 0xce, 0xff, 0x21, 0x18, 0xea, 0xbb, 0x86, 0x73, 0xf1, 0xc1, + 0xe3, 0x36, 0x6f, 0x0f, 0x92, 0x69, 0xf2, 0xd0, 0x16, 0x42, 0xb9, 0xd6, 0x8c, 0x64, 0xf2, 0x2a, 0xd0, 0xd4, 0x30, + 0x72, 0x9b, 0x22, 0xe4, 0x89, 0xaf, 0x30, 0x87, 0xd8, 0x74, 0xee, 0x68, 0x60, 0x31, 0x8e, 0xad, 0x2a, 0x48, 0x86, + 0x9b, 0x3c, 0x30, 0x44, 0x5f, 0xd5, 0x77, 0xf3, 0x20, 0xb2, 0x30, 0x0a, 0x7c, 0xfd, 0x8d, 0xbf, 0x82, 0x38, 0xc8, + 0x80, 0xdc, 0xaa, 0xaf, 0xa0, 0xd0, 0x52, 0xfd, 0xe6, 0x20, 0xd5, 0x93, 0xde, 0x08, 0x09, 0xa1, 0xc5, 0x1b, 0xfc, + 0x49, 0xd3, 0x34, 0x4d, 0xb2, 0x11, 0x9a, 0xe4, 0x23, 0xb0, 0x1c, 0xd9, 0x01, 0xd0, 0x96, 0xe4, 0x8b, 0x15, 0x95, + 0x00, 0x67, 0x80, 0x3a, 0x59, 0x51, 0xc0, 0x43, 0xfd, 0x75, 0x5c, 0x51, 0x20, 0x18, 0x7a, 0x08, 0xd3, 0xe6, 0x27, + 0x10, 0x11, 0xb8, 0xab, 0x21, 0xc3, 0x8e, 0x6f, 0xb9, 0x24, 0x58, 0x73, 0xe9, 0x71, 0xd0, 0x63, 0xcd, 0x31, 0xe1, + 0x22, 0x05, 0x0b, 0x82, 0xd6, 0xa1, 0x12, 0xe2, 0xd9, 0x62, 0x0d, 0xb8, 0x11, 0xf9, 0xa2, 0x55, 0x36, 0x67, 0xd1, + 0x52, 0xc7, 0x9c, 0x50, 0x18, 0xa3, 0x0f, 0xea, 0xbc, 0x21, 0x62, 0x0b, 0xb0, 0x4d, 0x73, 0xcb, 0x19, 0xdd, 0x85, + 0x29, 0x47, 0xa9, 0xbe, 0x35, 0xe2, 0x8a, 0xcd, 0x94, 0xe3, 0xb6, 0xea, 0x0d, 0xc1, 0x97, 0x34, 0xae, 0x3a, 0x72, + 0x91, 0x25, 0x34, 0xf4, 0x41, 0xd1, 0x31, 0xb8, 0xb8, 0x48, 0x80, 0xdd, 0xf0, 0xab, 0x8b, 0x26, 0x35, 0x32, 0x7e, + 0x45, 0x50, 0x94, 0x98, 0xf5, 0x6e, 0xf8, 0x38, 0x21, 0x30, 0xd1, 0xc6, 0x7e, 0x46, 0xb5, 0x7e, 0x36, 0x4c, 0xfa, + 0x13, 0x7b, 0xa0, 0x8b, 0x84, 0x40, 0xf5, 0x89, 0x3d, 0x80, 0xed, 0xdf, 0x5b, 0x90, 0xa6, 0xe8, 0x5b, 0xd0, 0xb5, + 0x05, 0xa1, 0xfe, 0x47, 0x10, 0xac, 0x6a, 0xcb, 0x01, 0x72, 0xf3, 0x2d, 0x58, 0x1c, 0x41, 0x0c, 0x59, 0x9d, 0xc5, + 0x21, 0xe6, 0x26, 0xfe, 0x46, 0x23, 0x8c, 0xed, 0x86, 0xa3, 0x61, 0xbe, 0xf0, 0x5c, 0xf7, 0xa0, 0x56, 0x1f, 0x04, + 0xd9, 0x4d, 0xb5, 0x4d, 0x2b, 0xeb, 0x7b, 0xae, 0x1d, 0xbc, 0x70, 0x5a, 0xbd, 0xda, 0x1d, 0xad, 0xc4, 0x92, 0x1c, + 0xa0, 0xf8, 0xeb, 0xec, 0xd9, 0xda, 0xa8, 0x1d, 0x48, 0xb3, 0x6a, 0x32, 0x8f, 0x63, 0xcb, 0xb9, 0xfc, 0x6b, 0x50, + 0xbf, 0xfa, 0x29, 0x92, 0x25, 0xe5, 0x35, 0x19, 0x40, 0x34, 0x64, 0x03, 0x8e, 0xd1, 0x9f, 0xb5, 0x97, 0x9a, 0x41, + 0xc7, 0xc7, 0x34, 0x07, 0x32, 0x5d, 0xb6, 0xf0, 0x29, 0x53, 0x3b, 0xa8, 0x7c, 0x31, 0xad, 0x62, 0x38, 0x1e, 0x77, + 0x95, 0x15, 0x1a, 0xbd, 0xad, 0xd4, 0x02, 0xf6, 0xbf, 0xe1, 0xfa, 0x74, 0x86, 0x10, 0x97, 0x00, 0x6a, 0x40, 0xec, + 0xf4, 0x9d, 0x1d, 0x2e, 0x17, 0xe5, 0xee, 0xca, 0x97, 0xe4, 0xfe, 0x9d, 0xe1, 0xa5, 0x83, 0x3a, 0x34, 0xd9, 0x5f, + 0xf3, 0x75, 0xf7, 0xc8, 0x2e, 0x59, 0x34, 0x2e, 0x77, 0x58, 0xb9, 0xbf, 0xf6, 0xef, 0xae, 0x84, 0x51, 0x20, 0xa9, + 0x40, 0xdc, 0x80, 0x51, 0xf2, 0x38, 0xc2, 0xcd, 0x4f, 0xc7, 0x2d, 0xd8, 0x8b, 0x8a, 0xc1, 0x06, 0x14, 0x11, 0x4c, + 0x36, 0x53, 0x84, 0xe2, 0x10, 0xb9, 0x1a, 0xdd, 0x82, 0x0d, 0x41, 0x88, 0x6e, 0xdc, 0x89, 0x99, 0xb0, 0x29, 0x2c, + 0xda, 0x04, 0x3c, 0x16, 0xe5, 0xbe, 0x52, 0xeb, 0x60, 0xb7, 0xd4, 0x3a, 0xdb, 0x25, 0xb5, 0x26, 0x77, 0xaa, 0xfb, + 0xc4, 0x5f, 0x28, 0x1e, 0x79, 0x82, 0x38, 0x57, 0x1d, 0xf3, 0x4a, 0xa2, 0x6e, 0xf4, 0xbe, 0x12, 0xad, 0x6a, 0xbd, + 0x91, 0x95, 0x20, 0x8a, 0xbf, 0x15, 0x06, 0x45, 0x28, 0xd4, 0x55, 0xd9, 0xf8, 0x55, 0x21, 0x1b, 0x27, 0xae, 0xa6, + 0x70, 0xa4, 0x11, 0xd4, 0xbf, 0xe2, 0xa4, 0x26, 0xb9, 0x83, 0xc2, 0x59, 0xad, 0x18, 0xa9, 0xe2, 0x7e, 0x55, 0x30, + 0x1a, 0x8a, 0x53, 0x9f, 0xe0, 0x32, 0xca, 0xbe, 0x7d, 0xe5, 0xaa, 0x85, 0xf7, 0x55, 0x51, 0x0e, 0x52, 0x77, 0x1c, + 0xb2, 0x2c, 0x56, 0xb7, 0x4d, 0xd9, 0xfd, 0x46, 0x7d, 0xad, 0x6c, 0x12, 0xe9, 0x27, 0x43, 0x00, 0x16, 0x62, 0xfa, + 0x8a, 0x5e, 0x5b, 0xda, 0x40, 0xe0, 0x20, 0x1b, 0xdc, 0xfa, 0x76, 0x4b, 0xe7, 0x29, 0x5f, 0x42, 0xa1, 0x85, 0x57, + 0x65, 0x10, 0x08, 0xdf, 0x9b, 0x75, 0xc3, 0x2d, 0x8f, 0x97, 0x3c, 0xbf, 0xdf, 0x41, 0xbc, 0xa8, 0xb9, 0xaa, 0x22, + 0x1f, 0x4f, 0xa6, 0x4d, 0xe6, 0xb9, 0x58, 0xb5, 0xde, 0x29, 0x09, 0x71, 0xd6, 0xdc, 0x33, 0xa6, 0x2c, 0xa3, 0xe7, + 0x35, 0xba, 0xe2, 0xbb, 0x7c, 0xeb, 0x24, 0xcb, 0x08, 0x63, 0xdb, 0xdb, 0x59, 0xe2, 0x8f, 0x3e, 0x29, 0x43, 0x16, + 0x72, 0x4e, 0x90, 0x01, 0x97, 0x35, 0x05, 0x3d, 0x1f, 0x43, 0x41, 0xb2, 0xae, 0xd3, 0x4a, 0x15, 0xe9, 0x4b, 0xf7, + 0xa9, 0xdb, 0xf6, 0x5f, 0x4d, 0x0e, 0x2b, 0x42, 0xd1, 0x56, 0xa7, 0x2c, 0x32, 0xdf, 0x30, 0x8e, 0x6c, 0xb6, 0x9c, + 0x0f, 0xd7, 0xaa, 0x6c, 0x55, 0x11, 0xb9, 0xd6, 0xc5, 0xac, 0xea, 0x67, 0x27, 0x93, 0x49, 0x59, 0xd0, 0xe8, 0x6a, + 0x87, 0x28, 0x2c, 0x7c, 0xea, 0xba, 0x6e, 0x75, 0xec, 0xdb, 0xc1, 0x6e, 0xa3, 0xdc, 0xf6, 0xa4, 0x71, 0xc4, 0x08, + 0xdb, 0x5d, 0xf0, 0xab, 0x83, 0x23, 0x77, 0x8a, 0x93, 0x5d, 0x32, 0x8b, 0xe8, 0x91, 0x31, 0x44, 0x90, 0xb1, 0x79, + 0xda, 0x1d, 0x31, 0xd4, 0xc1, 0x38, 0xca, 0x81, 0x46, 0xc3, 0x01, 0x7b, 0x0a, 0xa6, 0x22, 0x9e, 0xd8, 0x15, 0xae, + 0x86, 0xf2, 0xf0, 0x9a, 0xf0, 0x5e, 0x7c, 0x04, 0x0f, 0xca, 0xba, 0x2e, 0xd3, 0xc6, 0x69, 0x75, 0xdc, 0x3f, 0x97, + 0xea, 0x69, 0x70, 0x01, 0xae, 0x85, 0x42, 0x9b, 0xe4, 0xb3, 0xf8, 0xff, 0x52, 0xfe, 0xff, 0x6a, 0xb1, 0x2a, 0xdb, + 0x8f, 0x9c, 0x80, 0x44, 0xbb, 0x38, 0x2d, 0x34, 0xea, 0xa6, 0x3d, 0x20, 0xad, 0x0c, 0x26, 0xaa, 0x02, 0x1d, 0x94, + 0xf4, 0xa5, 0x04, 0x20, 0x0d, 0xe2, 0x77, 0xa4, 0x98, 0x61, 0x89, 0x0b, 0x11, 0x62, 0x91, 0xbe, 0x0e, 0xe6, 0x60, + 0xbd, 0x3c, 0x41, 0xfd, 0x41, 0x69, 0x4f, 0x80, 0x36, 0xbe, 0x36, 0xb7, 0xbd, 0xc4, 0xfd, 0x55, 0xbd, 0x96, 0xe8, + 0x18, 0x40, 0xe6, 0xc1, 0x21, 0x44, 0x43, 0x02, 0xad, 0xb2, 0xb9, 0x69, 0x94, 0xf2, 0xad, 0xaa, 0x67, 0x13, 0x03, + 0xc3, 0xee, 0x9a, 0xab, 0x50, 0xdf, 0x42, 0x5b, 0x00, 0x93, 0xe5, 0xdb, 0x0f, 0x9f, 0x6d, 0x58, 0x62, 0x75, 0x3f, + 0x7a, 0xb8, 0xe4, 0xb8, 0x7f, 0x6d, 0xbc, 0x3b, 0x53, 0x3a, 0xff, 0x28, 0x5f, 0xfc, 0x6b, 0xa3, 0x40, 0xef, 0xaa, + 0x24, 0xa1, 0xe3, 0xd6, 0xe2, 0x2d, 0x73, 0xaf, 0xda, 0xf3, 0x20, 0xda, 0xbf, 0xae, 0xbf, 0xda, 0xbb, 0x2e, 0x5c, + 0x18, 0x7b, 0x57, 0x86, 0x1b, 0x87, 0x2c, 0x17, 0xb2, 0xfe, 0x5f, 0x15, 0x81, 0xa2, 0xea, 0x75, 0xac, 0x63, 0x2b, + 0xa2, 0xf2, 0xaf, 0x96, 0x40, 0x7c, 0xee, 0x95, 0xe0, 0x41, 0x13, 0x39, 0xda, 0xf4, 0x63, 0xed, 0x44, 0x3b, 0x6e, + 0x6b, 0x47, 0xae, 0x4e, 0x5c, 0x58, 0x5f, 0xef, 0xb4, 0x0a, 0x6f, 0xc2, 0x43, 0x57, 0x3f, 0x3b, 0x9d, 0x8a, 0x4b, + 0x62, 0x12, 0x84, 0x21, 0xa1, 0x8a, 0x34, 0x4b, 0xe2, 0x4f, 0xac, 0xac, 0x66, 0xa1, 0x32, 0x6e, 0x04, 0xd2, 0x12, + 0x8f, 0x70, 0x76, 0x46, 0xfe, 0xa2, 0x8b, 0x67, 0x43, 0x2d, 0x04, 0x03, 0x4e, 0x2a, 0xc5, 0x4f, 0xc0, 0x1d, 0x3c, + 0xd4, 0xcf, 0x4e, 0x21, 0x84, 0xa1, 0x36, 0xee, 0xeb, 0x3f, 0xb6, 0x8e, 0x35, 0xaf, 0x73, 0x67, 0xb7, 0x47, 0xae, + 0xed, 0x39, 0x87, 0x9a, 0xeb, 0x1c, 0xd9, 0x2d, 0xe7, 0x58, 0x6b, 0x39, 0x1d, 0xf8, 0x77, 0xe4, 0x39, 0xaf, 0x34, + 0x17, 0x9e, 0x34, 0xcf, 0x69, 0xe3, 0xbf, 0x2d, 0xe7, 0xf8, 0xae, 0x4d, 0x37, 0xbd, 0x2f, 0xdd, 0xaa, 0x2a, 0xa3, + 0x00, 0x27, 0x10, 0xfd, 0xe0, 0xec, 0x74, 0x99, 0x32, 0x6d, 0xd5, 0xd7, 0x5f, 0xe9, 0xda, 0x2c, 0x61, 0x93, 0xbe, + 0xfe, 0xd4, 0x57, 0x4a, 0xbd, 0x93, 0xc6, 0xe2, 0xd6, 0x71, 0x63, 0x71, 0xfb, 0xa8, 0xb1, 0xf8, 0xb0, 0x53, 0x2e, + 0x3e, 0x98, 0xd2, 0x2b, 0x25, 0x83, 0xe0, 0xdc, 0xcf, 0x92, 0x60, 0x65, 0x78, 0x1a, 0xa0, 0x6b, 0x1b, 0xfe, 0x39, + 0x6e, 0x99, 0xb2, 0xd5, 0x10, 0x5a, 0x49, 0x68, 0x1c, 0x9f, 0x68, 0xde, 0xd1, 0x5f, 0x5a, 0x47, 0x23, 0xa8, 0x07, + 0xf9, 0x2e, 0xe1, 0xef, 0xae, 0x7d, 0x32, 0x72, 0x35, 0x68, 0xe8, 0xc1, 0x7f, 0xb3, 0x4e, 0x6b, 0x44, 0x0f, 0x2e, + 0xbc, 0xff, 0xe8, 0x1d, 0xa7, 0xae, 0xed, 0xc1, 0x7f, 0xbf, 0x49, 0x95, 0x3b, 0x28, 0xfc, 0xd5, 0x7e, 0x0f, 0x5d, + 0xad, 0x7d, 0x32, 0x6b, 0x39, 0xaf, 0xee, 0x8e, 0x9d, 0x93, 0x99, 0x77, 0xfc, 0x91, 0x9e, 0x42, 0xbb, 0xe5, 0xbc, + 0x82, 0xbf, 0x8f, 0x6d, 0x77, 0x66, 0x7b, 0xce, 0xc9, 0x5d, 0xdb, 0x69, 0x87, 0xf6, 0x91, 0x73, 0x02, 0x7f, 0xbf, + 0x01, 0x78, 0x01, 0xae, 0x3c, 0x41, 0xa9, 0x06, 0x1b, 0xa3, 0x62, 0xbf, 0xa1, 0x7e, 0xa4, 0x75, 0xa8, 0x75, 0x0e, + 0xff, 0x72, 0x72, 0x67, 0x1f, 0xce, 0xbc, 0xd6, 0x9d, 0xbd, 0xf1, 0xe7, 0x47, 0x80, 0xfc, 0xf6, 0x85, 0x03, 0x30, + 0x62, 0x46, 0x92, 0x3f, 0x0d, 0xac, 0xcb, 0x4d, 0x62, 0xf4, 0xf7, 0xbb, 0xc5, 0xe8, 0x3f, 0x2c, 0xf7, 0x11, 0xa3, + 0xbf, 0xff, 0xea, 0x62, 0xf4, 0xcb, 0xaa, 0x15, 0xf7, 0xfb, 0x6a, 0xe4, 0xf4, 0x5f, 0xd6, 0x55, 0x22, 0x39, 0xf0, + 0x8d, 0xeb, 0xab, 0xe5, 0x0d, 0xc4, 0xfe, 0x79, 0x1f, 0xf7, 0x7f, 0x58, 0x96, 0x4c, 0x94, 0x62, 0xc0, 0x00, 0xef, + 0x63, 0xc2, 0x00, 0xbf, 0x2d, 0xfb, 0x60, 0x17, 0xc1, 0x6f, 0xcd, 0x60, 0x6c, 0xcf, 0xfc, 0x70, 0x22, 0x6f, 0x5c, + 0x28, 0xe9, 0x61, 0x31, 0xd8, 0xcc, 0xc3, 0x65, 0x02, 0xca, 0x9a, 0xe5, 0x3c, 0x4a, 0xbb, 0x47, 0x2e, 0xa0, 0xf9, + 0xd6, 0x24, 0xc9, 0x2b, 0x8d, 0x1d, 0x11, 0x2d, 0xe9, 0x96, 0xdb, 0xf4, 0x6f, 0x7c, 0x8f, 0x26, 0x6b, 0xcd, 0xbd, + 0x7b, 0xf5, 0x7e, 0x35, 0xb0, 0x05, 0x11, 0x26, 0x7d, 0x40, 0x6c, 0x34, 0xbd, 0x2f, 0x1b, 0x8e, 0x55, 0x4c, 0x05, + 0x37, 0x8f, 0x14, 0x46, 0x52, 0x6d, 0xef, 0x95, 0x0d, 0xcf, 0x76, 0x4d, 0xb3, 0xe1, 0xf3, 0xa5, 0xe6, 0x5b, 0xac, + 0xde, 0x64, 0xc7, 0x55, 0x50, 0x55, 0xf2, 0x7e, 0x35, 0x02, 0xa4, 0xa0, 0x3d, 0x0b, 0xd3, 0xb8, 0x82, 0xf0, 0x71, + 0x35, 0xbc, 0x8d, 0x5d, 0xe5, 0x5d, 0xa9, 0x4f, 0xd5, 0x9c, 0xee, 0xc5, 0x1a, 0xe9, 0xc1, 0xe0, 0x37, 0x20, 0x6c, + 0xf8, 0x7d, 0x3c, 0x8c, 0x55, 0x38, 0xaf, 0x95, 0x7e, 0x89, 0xd4, 0xce, 0x67, 0xde, 0xba, 0x4e, 0xda, 0x6c, 0x34, + 0xa4, 0xf5, 0xd8, 0x5c, 0xdc, 0xd1, 0xf8, 0x79, 0x32, 0x5b, 0xcd, 0xc9, 0xb4, 0x18, 0x2d, 0x73, 0xb7, 0x75, 0x26, + 0xea, 0x3d, 0x85, 0x4d, 0x6c, 0xf1, 0x07, 0xd5, 0x6b, 0x7d, 0x3d, 0x81, 0x1c, 0xcd, 0x5d, 0x24, 0x22, 0x14, 0x0a, + 0xaa, 0x85, 0x36, 0xb6, 0xbd, 0x2d, 0xe6, 0x1f, 0x6a, 0xc7, 0xbc, 0x13, 0xb4, 0xd5, 0xdd, 0x66, 0x31, 0x22, 0x5d, + 0x1b, 0xd6, 0x25, 0x05, 0xaa, 0xd7, 0x39, 0xb6, 0xbc, 0x23, 0xcb, 0x39, 0xee, 0x98, 0xb9, 0x38, 0x70, 0x6a, 0x97, + 0x25, 0x80, 0x80, 0xc9, 0xae, 0x1c, 0x66, 0x10, 0x05, 0x59, 0xe0, 0x87, 0x39, 0xa0, 0xfa, 0x32, 0xcd, 0xfb, 0xcf, + 0x65, 0x9a, 0xc1, 0x1c, 0x05, 0x49, 0x86, 0xe6, 0xca, 0xf6, 0x90, 0x65, 0xf7, 0x8c, 0x45, 0x1b, 0x54, 0xb9, 0x55, + 0xeb, 0xe7, 0x3f, 0xce, 0x16, 0x34, 0x27, 0x3b, 0x8b, 0x61, 0x16, 0xf1, 0xfd, 0x21, 0x4c, 0x75, 0xf3, 0x81, 0xf5, + 0xd3, 0x26, 0x84, 0xfb, 0xcf, 0xdd, 0x08, 0x37, 0x63, 0xfb, 0x20, 0xdc, 0x7f, 0x7e, 0x75, 0x84, 0xfb, 0x93, 0x8a, + 0x70, 0x4b, 0x9e, 0x2a, 0x85, 0x4c, 0xf4, 0x03, 0x3e, 0x1b, 0x10, 0x72, 0xf8, 0xa5, 0x7e, 0x40, 0xe4, 0xa5, 0xae, + 0xa4, 0x82, 0xfd, 0x58, 0xca, 0x6d, 0x83, 0x2c, 0x3b, 0x86, 0x48, 0xa5, 0x3c, 0x1a, 0x90, 0x26, 0x55, 0x26, 0xfc, + 0x86, 0x3e, 0x2f, 0xa2, 0x2c, 0x74, 0xde, 0x73, 0xb6, 0x04, 0x54, 0x10, 0x3f, 0xc4, 0xc9, 0xdc, 0xc7, 0xf0, 0x70, + 0x3a, 0xe6, 0xc4, 0x83, 0x07, 0x17, 0xbc, 0xa3, 0x46, 0x71, 0x34, 0x96, 0x72, 0x74, 0xd6, 0xbf, 0x26, 0x7a, 0x50, + 0x7f, 0x60, 0x7e, 0xa2, 0x5b, 0xf4, 0x1a, 0x16, 0xf7, 0x45, 0xdb, 0x7d, 0xd1, 0x3a, 0x7c, 0x71, 0xe4, 0xc2, 0xff, + 0x3c, 0xd6, 0xce, 0x2d, 0x5e, 0x71, 0x1e, 0x47, 0x90, 0x96, 0x43, 0xd4, 0xdc, 0x54, 0xed, 0x9e, 0xb1, 0x4f, 0x45, + 0xad, 0xe3, 0xe6, 0x4a, 0x63, 0xff, 0xa1, 0xa8, 0xd3, 0x58, 0x63, 0x16, 0x2f, 0x95, 0x61, 0x35, 0x8c, 0x26, 0x88, + 0x96, 0x20, 0x19, 0x52, 0x6a, 0xa8, 0xaf, 0xf9, 0x74, 0x8b, 0x79, 0xb1, 0x76, 0x7e, 0x53, 0xe4, 0xfe, 0x11, 0x39, + 0x48, 0x76, 0x42, 0x90, 0x0b, 0xd5, 0x5d, 0x8c, 0x1c, 0x8e, 0xd9, 0x6f, 0x34, 0xc8, 0xbc, 0x57, 0x24, 0x78, 0xc7, + 0x05, 0xca, 0x92, 0x65, 0x34, 0xa2, 0x1c, 0xee, 0xfe, 0x30, 0x35, 0x82, 0x03, 0x88, 0x1d, 0x8a, 0x1f, 0x36, 0x71, + 0xd5, 0xfc, 0x33, 0xb7, 0x48, 0x94, 0x90, 0x8a, 0x55, 0xf1, 0x5f, 0x64, 0x56, 0x42, 0xe9, 0x55, 0x71, 0x69, 0xed, + 0xbe, 0xff, 0x42, 0x36, 0x7c, 0x91, 0x59, 0x90, 0xe2, 0x14, 0x96, 0xfb, 0xf9, 0x73, 0xaa, 0x05, 0x49, 0x07, 0x69, + 0x5a, 0xe7, 0xa3, 0x22, 0xf8, 0x98, 0xe6, 0x4f, 0x63, 0x8a, 0x3f, 0xd6, 0x1d, 0x59, 0xf1, 0xcb, 0x97, 0x67, 0x7d, + 0xcf, 0xe4, 0x29, 0x33, 0x4b, 0xf9, 0x9d, 0x2e, 0xf7, 0x53, 0x8d, 0x9b, 0x8d, 0x4e, 0x5b, 0x8b, 0x20, 0x9a, 0x0a, + 0xcd, 0xb4, 0xc4, 0x5e, 0x90, 0x6f, 0x81, 0x54, 0x60, 0xbe, 0x50, 0x51, 0x8b, 0x3a, 0x77, 0x2c, 0x81, 0x74, 0x9f, + 0x7d, 0xbd, 0xed, 0xb8, 0x8e, 0xab, 0xcb, 0x86, 0x93, 0x60, 0xda, 0x5f, 0xc7, 0x99, 0x0f, 0x99, 0x6b, 0xc2, 0x78, + 0x0a, 0x9e, 0x1f, 0x59, 0x90, 0x85, 0x90, 0x06, 0x05, 0x5c, 0x40, 0xe6, 0xc4, 0x35, 0xe6, 0xdc, 0x1e, 0xd7, 0x4f, + 0x3e, 0x61, 0x2a, 0x3c, 0xe1, 0xf4, 0x85, 0xf1, 0x70, 0x7e, 0x84, 0xcb, 0xd0, 0xd0, 0x0d, 0x48, 0xc4, 0xc8, 0x92, + 0xd4, 0x56, 0xed, 0xdb, 0xbb, 0x1a, 0xb4, 0x81, 0x24, 0xe9, 0xd8, 0xc1, 0x24, 0xf1, 0xe7, 0x10, 0x31, 0x7c, 0x9d, + 0x5b, 0x1c, 0xd3, 0xea, 0x1c, 0xd5, 0x6a, 0xde, 0xab, 0x23, 0x4b, 0x6b, 0x79, 0x96, 0xe6, 0x02, 0xba, 0xd5, 0x73, + 0x6b, 0x9d, 0xdf, 0xf4, 0x76, 0xa9, 0xe8, 0x08, 0xbf, 0x3c, 0xa5, 0x79, 0x90, 0x72, 0x8e, 0x0b, 0x3f, 0x33, 0x0a, + 0x6f, 0x68, 0x28, 0xb1, 0xbc, 0x03, 0x12, 0xd3, 0x5f, 0xb1, 0x55, 0x66, 0x62, 0x9a, 0x10, 0x5e, 0x25, 0x30, 0xd7, + 0xe8, 0x9a, 0x16, 0x44, 0x5a, 0xf0, 0xf9, 0xb3, 0x11, 0x80, 0xf9, 0x7d, 0x5f, 0x81, 0x0f, 0x3c, 0x9b, 0x25, 0x80, + 0x05, 0x85, 0x62, 0x09, 0x81, 0x05, 0xbe, 0x31, 0xf0, 0x6f, 0x51, 0x2c, 0x7e, 0x70, 0xc5, 0x9e, 0x13, 0xfa, 0xd1, + 0x14, 0x50, 0x9a, 0x1f, 0x4d, 0x6b, 0x06, 0x04, 0xe4, 0x5d, 0x57, 0x29, 0x2d, 0xba, 0x2a, 0x94, 0xfb, 0xe9, 0xf7, + 0x0f, 0x57, 0x94, 0x06, 0x09, 0x52, 0x6e, 0xfb, 0x63, 0x74, 0x05, 0x2b, 0x74, 0x0f, 0x2f, 0xfb, 0xdf, 0x9c, 0xce, + 0x59, 0xe6, 0x93, 0xe0, 0x12, 0x58, 0x3c, 0x20, 0x07, 0xb4, 0x91, 0x48, 0x61, 0x4a, 0x0c, 0xde, 0x98, 0xdd, 0x05, + 0x23, 0xce, 0xa7, 0x59, 0x1a, 0xbf, 0xa7, 0x6c, 0xb4, 0x51, 0xea, 0x7b, 0x16, 0x99, 0xc8, 0x8e, 0x7c, 0x0c, 0x82, + 0xd8, 0x8f, 0x62, 0xfd, 0xec, 0x1b, 0xe9, 0x4d, 0xb4, 0x69, 0x11, 0x20, 0x17, 0xe1, 0x75, 0xc2, 0xc2, 0x7f, 0xf5, + 0xbf, 0x81, 0x8b, 0xfb, 0x9b, 0x1b, 0xdd, 0xec, 0x65, 0x0e, 0xf2, 0x31, 0xdf, 0x34, 0xe4, 0xe4, 0x43, 0x1e, 0x95, + 0x33, 0x9b, 0x6d, 0x85, 0xd9, 0x84, 0xdf, 0xbb, 0x59, 0xd7, 0xb3, 0x53, 0xbc, 0xd0, 0xce, 0x80, 0xbb, 0x58, 0x97, + 0x78, 0x4e, 0xaf, 0x87, 0x0c, 0xea, 0x30, 0xf4, 0x47, 0x9f, 0x04, 0x87, 0xaa, 0x3e, 0xec, 0xc3, 0x8b, 0x4a, 0xca, + 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, 0xf1, 0x53, 0xf7, 0xb3, 0x20, 0x93, 0xcc, 0x30, 0x3e, 0xe4, 0xa0, + 0xcd, 0xc1, 0xf1, 0x15, 0xec, 0x0f, 0x30, 0xa8, 0xde, 0xc9, 0x5f, 0x3a, 0x77, 0x9e, 0x3b, 0x6b, 0x79, 0x0e, 0xb0, + 0x39, 0xb3, 0xb6, 0x73, 0x1c, 0xda, 0x6d, 0xe7, 0x18, 0xfe, 0x3e, 0x02, 0xeb, 0x65, 0xb7, 0x9c, 0xc3, 0x8f, 0x5e, + 0x2b, 0xb4, 0x4f, 0x9c, 0x63, 0xf8, 0xbb, 0xa4, 0x56, 0xbf, 0x20, 0xd3, 0x03, 0x0c, 0xcf, 0x37, 0x25, 0x2c, 0xa0, + 0xfc, 0x96, 0x5a, 0x04, 0xab, 0x74, 0xbd, 0x35, 0x68, 0x22, 0x00, 0x65, 0xe8, 0x96, 0x08, 0x51, 0x18, 0xf5, 0x0c, + 0x48, 0x12, 0x8e, 0xe1, 0xed, 0x85, 0x41, 0x46, 0x54, 0x24, 0xbc, 0xdf, 0x7c, 0x8c, 0x78, 0x9b, 0xe6, 0x70, 0xe0, + 0x22, 0x6f, 0x12, 0xa9, 0x2e, 0xfe, 0xb6, 0xc0, 0x10, 0x3b, 0x22, 0x80, 0xb9, 0x82, 0x95, 0x8a, 0xdc, 0x7d, 0xf9, + 0xee, 0x81, 0xa3, 0xdf, 0x28, 0x93, 0xb9, 0x63, 0xbe, 0x6a, 0xdf, 0x5c, 0x9d, 0x21, 0x7b, 0xff, 0xbd, 0xfd, 0x60, + 0xca, 0x54, 0xea, 0x47, 0xc4, 0x1a, 0x1d, 0x07, 0x89, 0x1c, 0x9e, 0x82, 0xa2, 0xbd, 0xe6, 0x38, 0xea, 0x26, 0x24, + 0xd9, 0xb8, 0x00, 0x2a, 0xf9, 0xce, 0x0f, 0x15, 0xd3, 0x0b, 0xa5, 0xe5, 0x13, 0x89, 0xf9, 0x9f, 0x3f, 0x2f, 0x06, + 0x67, 0x57, 0xc6, 0x7d, 0xea, 0x75, 0xe0, 0xda, 0xed, 0xb0, 0xf6, 0x56, 0x2b, 0xa0, 0xdd, 0xc1, 0x6a, 0x8b, 0x60, + 0x96, 0x42, 0xd3, 0x2f, 0x74, 0x8c, 0x1b, 0x4d, 0x91, 0x6a, 0x1a, 0x46, 0x08, 0xf3, 0x5b, 0x61, 0x75, 0x74, 0xb3, + 0x17, 0x09, 0x85, 0x59, 0xb4, 0x25, 0x40, 0x2f, 0xe7, 0xc5, 0x74, 0x00, 0xcd, 0x96, 0x79, 0xec, 0x70, 0x69, 0xfc, + 0x5f, 0x4f, 0x02, 0xdd, 0x8b, 0x40, 0xc3, 0x57, 0x39, 0xad, 0x25, 0x77, 0x13, 0x79, 0xaf, 0xd2, 0x85, 0xca, 0xd2, + 0x73, 0x1d, 0x8a, 0x20, 0xfb, 0x12, 0x26, 0x5c, 0x93, 0xe6, 0x4d, 0xf2, 0xb6, 0x28, 0x0a, 0xac, 0x00, 0x22, 0x54, + 0x1b, 0xc2, 0xd5, 0xc9, 0x7c, 0xfe, 0x7c, 0xe3, 0x25, 0x44, 0xea, 0x64, 0x35, 0xef, 0xa4, 0xae, 0xe2, 0x37, 0x5d, + 0x45, 0x31, 0xb2, 0x5f, 0xc4, 0x1a, 0xc2, 0x2a, 0x8b, 0xf6, 0x1e, 0xfe, 0x1c, 0x32, 0x3f, 0x73, 0xb8, 0x1e, 0xc4, + 0x50, 0x2e, 0x77, 0xcb, 0x63, 0x6d, 0xb0, 0xc7, 0xe2, 0x91, 0xb8, 0x78, 0xa4, 0xbb, 0x67, 0xeb, 0x8f, 0x4b, 0xee, + 0x87, 0x0c, 0x7d, 0x7c, 0x76, 0x8b, 0xe0, 0x29, 0xef, 0x32, 0x9f, 0x22, 0x6c, 0xa8, 0x57, 0x6e, 0x9c, 0xf9, 0x22, + 0xcb, 0x09, 0xd0, 0xe5, 0xbd, 0x46, 0x85, 0xa1, 0xe2, 0xab, 0x7c, 0xf6, 0xee, 0xea, 0x3b, 0x8d, 0xef, 0x7f, 0xd2, + 0x6f, 0x21, 0x23, 0x43, 0x31, 0xf9, 0xfb, 0x14, 0x93, 0x5f, 0xe3, 0x49, 0x2e, 0x20, 0xb2, 0x7d, 0x7e, 0x40, 0x10, + 0xd4, 0x35, 0x16, 0x8d, 0x48, 0xeb, 0x37, 0x5f, 0x86, 0x59, 0xb0, 0xf0, 0x93, 0xec, 0x00, 0x9a, 0xda, 0x80, 0xe4, + 0xf4, 0x4d, 0x1e, 0xcc, 0xa4, 0x38, 0x14, 0x42, 0xb5, 0x2c, 0x12, 0x9a, 0xc3, 0x49, 0x10, 0x4a, 0xc5, 0xa1, 0xf8, + 0x80, 0x3f, 0x1a, 0xb1, 0x45, 0xd6, 0xd7, 0xfd, 0x05, 0xe4, 0x66, 0xc0, 0x68, 0xcb, 0x07, 0xf1, 0x28, 0x63, 0x99, + 0x9d, 0x66, 0x09, 0xf3, 0xe7, 0xba, 0x0c, 0x34, 0x5a, 0xef, 0x2f, 0x5d, 0x0e, 0xe7, 0x41, 0x26, 0x23, 0xf5, 0xd1, + 0x04, 0x41, 0x85, 0x07, 0x43, 0x3c, 0x1b, 0xe4, 0x1c, 0x84, 0x97, 0xf1, 0xb4, 0xb2, 0xa3, 0x0a, 0xca, 0xe5, 0x1c, + 0xe3, 0xc0, 0xf2, 0x78, 0xfc, 0x63, 0xf4, 0xc8, 0xb9, 0xe5, 0x5e, 0xd7, 0x32, 0xa0, 0xa0, 0x7e, 0x76, 0xca, 0xd9, + 0x5b, 0x0d, 0x03, 0x05, 0xe8, 0x1d, 0x17, 0x22, 0xdd, 0x6e, 0xf2, 0xc7, 0x3e, 0xe0, 0x95, 0xe1, 0x6a, 0xa2, 0x9e, + 0x31, 0x0a, 0x39, 0x8d, 0xe5, 0x0a, 0x08, 0xa1, 0x92, 0x8a, 0x77, 0xe6, 0x9d, 0x49, 0x07, 0x20, 0x1c, 0x15, 0xd2, + 0x4a, 0x9f, 0x3f, 0xbf, 0x1e, 0xfc, 0xe7, 0xdf, 0x10, 0x2a, 0x7d, 0xe6, 0x09, 0x2f, 0xe8, 0x6b, 0xb5, 0x16, 0xa7, + 0x3e, 0xad, 0x01, 0xaa, 0xf7, 0xd9, 0x58, 0x84, 0x05, 0x11, 0x5b, 0x2b, 0x1f, 0xdc, 0x88, 0x50, 0x4f, 0x90, 0x0e, + 0xc1, 0x14, 0xbe, 0xda, 0x03, 0x58, 0xde, 0x81, 0x08, 0x11, 0xa0, 0xfd, 0xba, 0xfa, 0xfe, 0x18, 0x42, 0x01, 0xd7, + 0xb2, 0x14, 0x28, 0x03, 0xc4, 0x3d, 0x74, 0x76, 0xea, 0x73, 0xe1, 0x2b, 0x90, 0x1f, 0x69, 0xf7, 0x00, 0xa6, 0x39, + 0x8b, 0xe7, 0xcc, 0x09, 0xe2, 0x83, 0x7b, 0x36, 0xb4, 0xfd, 0x45, 0x40, 0xf2, 0x65, 0x94, 0xbb, 0x69, 0x44, 0xf9, + 0x49, 0x05, 0x2d, 0xd1, 0xd7, 0x79, 0x01, 0xca, 0xb8, 0x00, 0x14, 0xfc, 0xf4, 0xcf, 0xca, 0xd1, 0x03, 0x1d, 0x11, + 0xbf, 0xbe, 0x8c, 0xe5, 0xcf, 0x29, 0x08, 0xa0, 0x88, 0xf7, 0x57, 0x3c, 0xd8, 0xf1, 0x64, 0xa2, 0x46, 0xfc, 0x73, + 0xca, 0xdf, 0x97, 0x50, 0x29, 0xf6, 0x6c, 0xbc, 0xa0, 0x2f, 0xd5, 0x3f, 0x21, 0x7f, 0x42, 0xee, 0x5e, 0x1e, 0x1c, + 0x12, 0xce, 0x73, 0x2d, 0x72, 0xa0, 0x04, 0xc9, 0x53, 0xaa, 0xc4, 0x11, 0x45, 0x35, 0x4e, 0xf5, 0x06, 0xd2, 0xe4, + 0x49, 0xbf, 0x4f, 0x78, 0xac, 0x8a, 0xce, 0x00, 0x4a, 0x0d, 0xb1, 0xfc, 0x61, 0xb2, 0x19, 0x34, 0xb4, 0xc9, 0x83, + 0x0b, 0x1b, 0x55, 0xa7, 0x53, 0x1f, 0xe3, 0x81, 0x2f, 0xf6, 0x57, 0x69, 0x07, 0xc2, 0xce, 0xe2, 0x0b, 0x0b, 0x08, + 0x5c, 0xf4, 0x53, 0xc1, 0xe3, 0xda, 0xb7, 0x84, 0xb2, 0xed, 0xd0, 0x7f, 0x88, 0x15, 0xcd, 0x3a, 0x77, 0xb2, 0xbf, + 0xc4, 0xd2, 0x2b, 0xe1, 0xdc, 0x56, 0x3b, 0x49, 0x32, 0x1e, 0x7a, 0xfd, 0x34, 0xa9, 0x01, 0xcc, 0x77, 0x1d, 0x26, + 0xb5, 0x6e, 0x79, 0x32, 0x88, 0x1d, 0xf3, 0xe2, 0xa0, 0x95, 0x5e, 0xe2, 0xb9, 0xcf, 0x4f, 0x0f, 0x60, 0x7e, 0x10, + 0x18, 0xa0, 0x44, 0x19, 0x05, 0x26, 0x44, 0x1f, 0xf0, 0x53, 0xb2, 0x0e, 0xb8, 0x18, 0x0b, 0xa2, 0x0e, 0x39, 0x47, + 0x19, 0x9a, 0xb4, 0x54, 0xa5, 0x4e, 0xac, 0xb8, 0xcd, 0x54, 0xde, 0xee, 0xfc, 0x01, 0xbf, 0x2d, 0x31, 0x79, 0x40, + 0xde, 0xcb, 0x98, 0xf0, 0xbb, 0xbd, 0xcc, 0x36, 0xb8, 0xe6, 0x6e, 0xaa, 0x42, 0x04, 0xeb, 0x96, 0x0a, 0xc5, 0x3e, + 0xde, 0x56, 0xab, 0x20, 0x8d, 0x64, 0xb5, 0x85, 0x6f, 0xe8, 0x4f, 0x71, 0xc7, 0xd7, 0x6a, 0x63, 0x29, 0xd4, 0xbb, + 0xcc, 0xfa, 0x50, 0x55, 0x08, 0xdb, 0xfd, 0xc5, 0x82, 0x2a, 0x9b, 0xbd, 0xd3, 0x03, 0xe2, 0x3b, 0xcf, 0x68, 0x87, + 0x9d, 0x9d, 0x82, 0x75, 0x21, 0x2d, 0xba, 0xbf, 0x58, 0xf0, 0x25, 0xa5, 0x5f, 0xf4, 0xe6, 0x60, 0x96, 0xcd, 0xc3, + 0xb3, 0xff, 0x03, 0x1c, 0x2a, 0x1a, 0x60, 0x9f, 0x5a, 0x03, 0x00}; } // namespace web_server } // namespace esphome From 618102fe8c6d1fcafa51d2a0e025e08a1a14588d Mon Sep 17 00:00:00 2001 From: Mischa Siekmann <45062894+gnumpi@users.noreply.github.com> Date: Sun, 9 Jun 2024 08:34:21 +0200 Subject: [PATCH 27/30] fix: arduino media player still sets wrong state. (#6875) --- .../i2s_audio/media_player/i2s_audio_media_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp index ef494fac2e..5140a923b4 100644 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ b/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp @@ -28,7 +28,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { } } - if (this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { + if (play_state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { this->is_announcement_ = true; } From 7b45498de67ccdf10271e61577c66b5e216bc6db Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 08:15:29 +1200 Subject: [PATCH 28/30] [http_request] Add esp-idf and rp2040 support (#3256) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implement http_request component for esp-idf * Fix ifdefs * Lint * clang * Set else to fail with error message * Use unique_ptr * Fix * Tidy up casting, explicit HttpResponse lifetime (#3265) Co-authored-by: Daniel Cousens * Remove unique_ptr wrapper * Fix * Use reference * Add duration code into new split files * Add config for tx/rx buffer on idf * Fix * Try reserve response data with rx buffer size * Update http_request.h * Move client cleanup to be earlier * Move capture_response to bool on struct and remove global * Fix returns * Change quotes to brackets * Rework http request * Remove http request from old test yamls * Update component tests * Validate md5 length when hardcoded string * Linting * Add duration_ms to container * More lint * const * Remove default arguments and add helper functions for get and post * Add virtual destructor to HttpContainer * Undo const HEADER_KEYS * 🤦 * Update esphome/components/http_request/ota/ota_http_request.cpp Co-authored-by: Keith Burzinski * Update esphome/components/http_request/ota/ota_http_request.cpp Co-authored-by: Keith Burzinski * lint * Move header keys inline * Add missing WatchdogManagers * CAPS * Fix "follow redirects" string in config dump * IDF 5+ fix --------- Co-authored-by: Daniel Cousens <413395+dcousens@users.noreply.github.com> Co-authored-by: Daniel Cousens Co-authored-by: Keith Burzinski --- esphome/codegen.py | 1 + esphome/components/http_request/__init__.py | 137 +++++++++++---- .../components/http_request/http_request.cpp | 132 +------------- .../components/http_request/http_request.h | 141 +++++++++------ .../http_request/http_request_arduino.cpp | 161 ++++++++++++++++++ .../http_request/http_request_arduino.h | 40 +++++ .../http_request/http_request_idf.cpp | 155 +++++++++++++++++ .../http_request/http_request_idf.h | 34 ++++ .../components/http_request/ota/__init__.py | 109 ++---------- .../http_request/ota/ota_http_request.cpp | 110 +++++------- .../http_request/ota/ota_http_request.h | 24 +-- .../ota/ota_http_request_arduino.cpp | 134 --------------- .../ota/ota_http_request_arduino.h | 42 ----- .../http_request/ota/ota_http_request_idf.cpp | 86 ---------- .../http_request/ota/ota_http_request_idf.h | 24 --- .../http_request/{ota => }/watchdog.cpp | 19 ++- .../http_request/{ota => }/watchdog.h | 5 +- esphome/cpp_types.py | 1 + tests/components/http_request/common.yaml | 75 ++++++++ .../http_request/common_http_request.yaml | 33 ---- tests/components/http_request/common_ota.yaml | 36 ---- .../http_request/test-nossl.esp8266.yaml | 40 +---- .../http_request/test.esp32-c3-idf.yaml | 2 +- .../http_request/test.esp32-c3.yaml | 3 +- .../http_request/test.esp32-idf.yaml | 2 +- tests/components/http_request/test.esp32.yaml | 3 +- .../components/http_request/test.esp8266.yaml | 3 +- .../components/http_request/test.rp2040.yaml | 2 +- tests/test1.yaml | 29 ---- tests/test3.1.yaml | 24 --- tests/test7.yaml | 23 +-- 31 files changed, 748 insertions(+), 882 deletions(-) create mode 100644 esphome/components/http_request/http_request_arduino.cpp create mode 100644 esphome/components/http_request/http_request_arduino.h create mode 100644 esphome/components/http_request/http_request_idf.cpp create mode 100644 esphome/components/http_request/http_request_idf.h delete mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.cpp delete mode 100644 esphome/components/http_request/ota/ota_http_request_arduino.h delete mode 100644 esphome/components/http_request/ota/ota_http_request_idf.cpp delete mode 100644 esphome/components/http_request/ota/ota_http_request_idf.h rename esphome/components/http_request/{ota => }/watchdog.cpp (79%) rename esphome/components/http_request/{ota => }/watchdog.h (84%) create mode 100644 tests/components/http_request/common.yaml delete mode 100644 tests/components/http_request/common_http_request.yaml delete mode 100644 tests/components/http_request/common_ota.yaml diff --git a/esphome/codegen.py b/esphome/codegen.py index dc17f28a03..b552490129 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -58,6 +58,7 @@ from esphome.cpp_types import ( # noqa bool_, int_, std_ns, + std_shared_ptr, std_string, std_vector, uint8, diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 0c3e249512..37487ec9a7 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -1,9 +1,8 @@ -import urllib.parse as urlparse - import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.const import ( + __version__, CONF_ID, CONF_TIMEOUT, CONF_METHOD, @@ -12,67 +11,91 @@ from esphome.const import ( CONF_ESP8266_DISABLE_SSL_SUPPORT, ) from esphome.core import Lambda, CORE +from esphome.components import esp32 DEPENDENCIES = ["network"] AUTO_LOAD = ["json"] http_request_ns = cg.esphome_ns.namespace("http_request") HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) +HttpRequestArduino = http_request_ns.class_("HttpRequestArduino", HttpRequestComponent) +HttpRequestIDF = http_request_ns.class_("HttpRequestIDF", HttpRequestComponent) + +HttpContainer = http_request_ns.class_("HttpContainer") + HttpRequestSendAction = http_request_ns.class_( "HttpRequestSendAction", automation.Action ) HttpRequestResponseTrigger = http_request_ns.class_( - "HttpRequestResponseTrigger", automation.Trigger + "HttpRequestResponseTrigger", + automation.Trigger.template( + cg.std_shared_ptr.template(HttpContainer), cg.std_string + ), ) -CONF_HEADERS = "headers" +CONF_HTTP_REQUEST_ID = "http_request_id" + CONF_USERAGENT = "useragent" -CONF_BODY = "body" -CONF_JSON = "json" CONF_VERIFY_SSL = "verify_ssl" -CONF_ON_RESPONSE = "on_response" CONF_FOLLOW_REDIRECTS = "follow_redirects" CONF_REDIRECT_LIMIT = "redirect_limit" +CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" + +CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size" +CONF_ON_RESPONSE = "on_response" +CONF_HEADERS = "headers" +CONF_BODY = "body" +CONF_JSON = "json" +CONF_CAPTURE_RESPONSE = "capture_response" def validate_url(value): - value = cv.string(value) - try: - parsed = list(urlparse.urlparse(value)) - except Exception as err: - raise cv.Invalid("Invalid URL") from err - - if not parsed[0] or not parsed[1]: - raise cv.Invalid("URL must have a URL scheme and host") - - if parsed[0] not in ["http", "https"]: - raise cv.Invalid("Scheme must be http or https") - - if not parsed[2]: - parsed[2] = "/" - - return urlparse.urlunparse(parsed) + value = cv.url(value) + if value.startswith("http://") or value.startswith("https://"): + return value + raise cv.Invalid("URL must start with 'http://' or 'https://'") -def validate_secure_url(config): - url_ = config[CONF_URL] +def validate_ssl_verification(config): + error_message = "" + + if CORE.is_esp32: + if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: + error_message = "ESPHome supports certificate verification only via ESP-IDF" + + if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: + error_message = "ESPHome does not support certificate verification on RP2040" + if ( - config.get(CONF_VERIFY_SSL) - and not isinstance(url_, Lambda) - and url_.lower().startswith("https:") + CORE.is_esp8266 + and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] + and config[CONF_VERIFY_SSL] ): + error_message = "ESPHome does not support certificate verification on ESP8266" + + if len(error_message) > 0: raise cv.Invalid( - "Currently ESPHome doesn't support SSL verification. " - "Set 'verify_ssl: false' to make insecure HTTPS requests." + f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." ) + return config +def _declare_request_class(value): + if CORE.using_esp_idf: + return cv.declare_id(HttpRequestIDF)(value) + if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: + return cv.declare_id(HttpRequestArduino)(value) + return NotImplementedError + + CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.GenerateID(): cv.declare_id(HttpRequestComponent), - cv.Optional(CONF_USERAGENT, "ESPHome"): cv.string, + cv.GenerateID(): _declare_request_class, + cv.Optional( + CONF_USERAGENT, f"ESPHome/{__version__} (https://esphome.io)" + ): cv.string, cv.Optional(CONF_FOLLOW_REDIRECTS, True): cv.boolean, cv.Optional(CONF_REDIRECT_LIMIT, 3): cv.int_, cv.Optional( @@ -81,12 +104,21 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( cv.only_on_esp8266, cv.boolean ), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( + cv.Any(cv.only_on_esp32, cv.only_on_rp2040), + cv.positive_not_null_time_period, + cv.positive_time_period_milliseconds, + ), } ).extend(cv.COMPONENT_SCHEMA), cv.require_framework_version( esp8266_arduino=cv.Version(2, 5, 1), esp32_arduino=cv.Version(0, 0, 0), + esp_idf=cv.Version(0, 0, 0), + rp2040_arduino=cv.Version(0, 0, 0), ), + validate_ssl_verification, ) @@ -100,11 +132,30 @@ async def to_code(config): if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") + if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): + cg.add(var.set_watchdog_timeout(timeout_ms)) + if CORE.is_esp32: - cg.add_library("WiFiClientSecure", None) - cg.add_library("HTTPClient", None) + if CORE.using_esp_idf: + esp32.add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", + config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_INSECURE", + not config.get(CONF_VERIFY_SSL), + ) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", + not config.get(CONF_VERIFY_SSL), + ) + else: + cg.add_library("WiFiClientSecure", None) + cg.add_library("HTTPClient", None) if CORE.is_esp8266: cg.add_library("ESP8266HTTPClient", None) + if CORE.is_rp2040 and CORE.using_arduino: + cg.add_library("HTTPClient", None) await cg.register_component(var, config) @@ -116,12 +167,16 @@ HTTP_REQUEST_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_HEADERS): cv.All( cv.Schema({cv.string: cv.templatable(cv.string)}) ), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + cv.Optional(CONF_VERIFY_SSL): cv.invalid( + f"{CONF_VERIFY_SSL} has moved to the base component configuration." + ), + cv.Optional(CONF_CAPTURE_RESPONSE, default=False): cv.boolean, cv.Optional(CONF_ON_RESPONSE): automation.validate_automation( {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(HttpRequestResponseTrigger)} ), + cv.Optional(CONF_MAX_RESPONSE_BUFFER_SIZE, default="1kB"): cv.validate_bytes, } -).add_extra(validate_secure_url) +) HTTP_REQUEST_GET_ACTION_SCHEMA = automation.maybe_conf( CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend( @@ -173,6 +228,9 @@ async def http_request_action_to_code(config, action_id, template_arg, args): template_ = await cg.templatable(config[CONF_URL], args, cg.std_string) cg.add(var.set_url(template_)) cg.add(var.set_method(config[CONF_METHOD])) + cg.add(var.set_capture_response(config[CONF_CAPTURE_RESPONSE])) + cg.add(var.set_max_response_buffer_size(config[CONF_MAX_RESPONSE_BUFFER_SIZE])) + if CONF_BODY in config: template_ = await cg.templatable(config[CONF_BODY], args, cg.std_string) cg.add(var.set_body(template_)) @@ -196,7 +254,12 @@ async def http_request_action_to_code(config, action_id, template_arg, args): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) cg.add(var.register_response_trigger(trigger)) await automation.build_automation( - trigger, [(int, "status_code"), (cg.uint32, "duration_ms")], conf + trigger, + [ + (cg.std_shared_ptr.template(HttpContainer), "response"), + (cg.std_string, "body"), + ], + conf, ) return var diff --git a/esphome/components/http_request/http_request.cpp b/esphome/components/http_request/http_request.cpp index 46894a9afd..be8bef006e 100644 --- a/esphome/components/http_request/http_request.cpp +++ b/esphome/components/http_request/http_request.cpp @@ -1,9 +1,8 @@ -#ifdef USE_ARDUINO - #include "http_request.h" -#include "esphome/core/defines.h" + #include "esphome/core/log.h" -#include "esphome/components/network/util.h" + +#include namespace esphome { namespace http_request { @@ -14,131 +13,12 @@ void HttpRequestComponent::dump_config() { ESP_LOGCONFIG(TAG, "HTTP Request:"); ESP_LOGCONFIG(TAG, " Timeout: %ums", this->timeout_); ESP_LOGCONFIG(TAG, " User-Agent: %s", this->useragent_); - ESP_LOGCONFIG(TAG, " Follow Redirects: %d", this->follow_redirects_); + ESP_LOGCONFIG(TAG, " Follow redirects: %s", YESNO(this->follow_redirects_)); ESP_LOGCONFIG(TAG, " Redirect limit: %d", this->redirect_limit_); -} - -void HttpRequestComponent::set_url(std::string url) { - this->url_ = std::move(url); - this->secure_ = this->url_.compare(0, 6, "https:") == 0; - - if (!this->last_url_.empty() && this->url_ != this->last_url_) { - // Close connection if url has been changed - this->client_.setReuse(false); - this->client_.end(); + if (this->watchdog_timeout_ > 0) { + ESP_LOGCONFIG(TAG, " Watchdog Timeout: %" PRIu32 "ms", this->watchdog_timeout_); } - this->client_.setReuse(true); -} - -void HttpRequestComponent::send(const std::vector &response_triggers) { - if (!network::is_connected()) { - this->client_.end(); - this->status_set_warning(); - ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); - return; - } - - bool begin_status = false; - const String url = this->url_.c_str(); -#if defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)) -#if defined(USE_ESP32) || USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0) - if (this->follow_redirects_) { - this->client_.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); - } else { - this->client_.setFollowRedirects(HTTPC_DISABLE_FOLLOW_REDIRECTS); - } -#else - this->client_.setFollowRedirects(this->follow_redirects_); -#endif - this->client_.setRedirectLimit(this->redirect_limit_); -#endif -#if defined(USE_ESP32) - begin_status = this->client_.begin(url); -#elif defined(USE_ESP8266) - begin_status = this->client_.begin(*this->get_wifi_client_(), url); -#endif - - if (!begin_status) { - this->client_.end(); - this->status_set_warning(); - ESP_LOGW(TAG, "HTTP Request failed at the begin phase. Please check the configuration"); - return; - } - - this->client_.setTimeout(this->timeout_); -#if defined(USE_ESP32) - this->client_.setConnectTimeout(this->timeout_); -#endif - if (this->useragent_ != nullptr) { - this->client_.setUserAgent(this->useragent_); - } - for (const auto &header : this->headers_) { - this->client_.addHeader(header.name, header.value, false, true); - } - - uint32_t start_time = millis(); - int http_code = this->client_.sendRequest(this->method_, this->body_.c_str()); - uint32_t duration = millis() - start_time; - for (auto *trigger : response_triggers) - trigger->process(http_code, duration); - - if (http_code < 0) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s; Duration: %u ms", this->url_.c_str(), - HTTPClient::errorToString(http_code).c_str(), duration); - this->status_set_warning(); - return; - } - - if (http_code < 200 || http_code >= 300) { - ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Code: %d; Duration: %u ms", this->url_.c_str(), http_code, duration); - this->status_set_warning(); - return; - } - - this->status_clear_warning(); - ESP_LOGD(TAG, "HTTP Request completed; URL: %s; Code: %d; Duration: %u ms", this->url_.c_str(), http_code, duration); -} - -#ifdef USE_ESP8266 -std::shared_ptr HttpRequestComponent::get_wifi_client_() { -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_) { - if (this->wifi_client_secure_ == nullptr) { - this->wifi_client_secure_ = std::make_shared(); - this->wifi_client_secure_->setInsecure(); - this->wifi_client_secure_->setBufferSizes(512, 512); - } - return this->wifi_client_secure_; - } -#endif - - if (this->wifi_client_ == nullptr) { - this->wifi_client_ = std::make_shared(); - } - return this->wifi_client_; -} -#endif - -void HttpRequestComponent::close() { - this->last_url_ = this->url_; - this->client_.end(); -} - -const char *HttpRequestComponent::get_string() { -#if defined(ESP32) - // The static variable is here because HTTPClient::getString() returns a String on ESP32, - // and we need something to keep a buffer alive. - static String str; -#else - // However on ESP8266, HTTPClient::getString() returns a String& to a member variable. - // Leaving this the default so that any new platform either doesn't copy, or encounters a compilation error. - auto & -#endif - str = this->client_.getString(); - return str.c_str(); } } // namespace http_request } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index b885de18e6..df6bc7dea7 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -1,27 +1,18 @@ #pragma once -#ifdef USE_ARDUINO - -#include "esphome/components/json/json_util.h" -#include "esphome/core/automation.h" -#include "esphome/core/component.h" -#include "esphome/core/defines.h" - #include #include #include #include #include -#ifdef USE_ESP32 -#include -#endif -#ifdef USE_ESP8266 -#include -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS -#include -#endif -#endif +#include "esphome/components/json/json_util.h" +#include "esphome/core/application.h" +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" namespace esphome { namespace http_request { @@ -31,9 +22,32 @@ struct Header { const char *value; }; -class HttpRequestResponseTrigger : public Trigger { +class HttpRequestComponent; + +class HttpContainer : public Parented { public: - void process(int32_t status_code, uint32_t duration_ms) { this->trigger(status_code, duration_ms); } + virtual ~HttpContainer() = default; + size_t content_length; + int status_code; + uint32_t duration_ms; + + virtual int read(uint8_t *buf, size_t max_len) = 0; + virtual void end() = 0; + + void set_secure(bool secure) { this->secure_ = secure; } + + size_t get_bytes_read() const { return this->bytes_read_; } + + protected: + size_t bytes_read_{0}; + bool secure_{false}; +}; + +class HttpRequestResponseTrigger : public Trigger, std::string> { + public: + void process(std::shared_ptr container, std::string response_body) { + this->trigger(std::move(container), std::move(response_body)); + } }; class HttpRequestComponent : public Component { @@ -41,37 +55,33 @@ class HttpRequestComponent : public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void set_url(std::string url); - void set_method(const char *method) { this->method_ = method; } void set_useragent(const char *useragent) { this->useragent_ = useragent; } void set_timeout(uint16_t timeout) { this->timeout_ = timeout; } + void set_watchdog_timeout(uint32_t watchdog_timeout) { this->watchdog_timeout_ = watchdog_timeout; } + uint32_t get_watchdog_timeout() const { return this->watchdog_timeout_; } void set_follow_redirects(bool follow_redirects) { this->follow_redirects_ = follow_redirects; } void set_redirect_limit(uint16_t limit) { this->redirect_limit_ = limit; } - void set_body(const std::string &body) { this->body_ = body; } - void set_headers(std::list
headers) { this->headers_ = std::move(headers); } - void send(const std::vector &response_triggers); - void close(); - const char *get_string(); + + std::shared_ptr get(std::string url) { return this->start(std::move(url), "GET", "", {}); } + std::shared_ptr get(std::string url, std::list
headers) { + return this->start(std::move(url), "GET", "", std::move(headers)); + } + std::shared_ptr post(std::string url, std::string body) { + return this->start(std::move(url), "POST", std::move(body), {}); + } + std::shared_ptr post(std::string url, std::string body, std::list
headers) { + return this->start(std::move(url), "POST", std::move(body), std::move(headers)); + } + + virtual std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) = 0; protected: - HTTPClient client_{}; - std::string url_; - std::string last_url_; - const char *method_; const char *useragent_{nullptr}; - bool secure_; bool follow_redirects_; uint16_t redirect_limit_; uint16_t timeout_{5000}; - std::string body_; - std::list
headers_; -#ifdef USE_ESP8266 - std::shared_ptr wifi_client_; -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - std::shared_ptr wifi_client_secure_; -#endif - std::shared_ptr get_wifi_client_(); -#endif + uint32_t watchdog_timeout_{0}; }; template class HttpRequestSendAction : public Action { @@ -80,6 +90,7 @@ template class HttpRequestSendAction : public Action { TEMPLATABLE_VALUE(std::string, url) TEMPLATABLE_VALUE(const char *, method) TEMPLATABLE_VALUE(std::string, body) + TEMPLATABLE_VALUE(bool, capture_response) void add_header(const char *key, TemplatableValue value) { this->headers_.insert({key, value}); } @@ -89,19 +100,22 @@ template class HttpRequestSendAction : public Action { void register_response_trigger(HttpRequestResponseTrigger *trigger) { this->response_triggers_.push_back(trigger); } + void set_max_response_buffer_size(size_t max_response_buffer_size) { + this->max_response_buffer_size_ = max_response_buffer_size; + } + void play(Ts... x) override { - this->parent_->set_url(this->url_.value(x...)); - this->parent_->set_method(this->method_.value(x...)); + std::string body; if (this->body_.has_value()) { - this->parent_->set_body(this->body_.value(x...)); + body = this->body_.value(x...); } if (!this->json_.empty()) { auto f = std::bind(&HttpRequestSendAction::encode_json_, this, x..., std::placeholders::_1); - this->parent_->set_body(json::build_json(f)); + body = json::build_json(f); } if (this->json_func_ != nullptr) { auto f = std::bind(&HttpRequestSendAction::encode_json_func_, this, x..., std::placeholders::_1); - this->parent_->set_body(json::build_json(f)); + body = json::build_json(f); } std::list
headers; for (const auto &item : this->headers_) { @@ -111,10 +125,37 @@ template class HttpRequestSendAction : public Action { header.value = val.value(x...); headers.push_back(header); } - this->parent_->set_headers(headers); - this->parent_->send(this->response_triggers_); - this->parent_->close(); - this->parent_->set_body(""); + + auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, headers); + + if (container == nullptr) { + return; + } + + size_t content_length = container->content_length; + size_t max_length = std::min(content_length, this->max_response_buffer_size_); + + std::string response_body; + if (this->capture_response_.value(x...)) { + ExternalRAMAllocator allocator(ExternalRAMAllocator::ALLOW_FAILURE); + uint8_t *buf = allocator.allocate(max_length); + if (buf != nullptr) { + size_t read_index = 0; + while (container->get_bytes_read() < max_length) { + int read = container->read(buf + read_index, std::min(max_length - read_index, 512)); + App.feed_wdt(); + yield(); + read_index += read; + } + response_body.reserve(read_index); + response_body.assign((char *) buf, read_index); + } + } + + for (auto *trigger : this->response_triggers_) { + trigger->process(container, response_body); + } + container->end(); } protected: @@ -130,9 +171,9 @@ template class HttpRequestSendAction : public Action { std::map> json_{}; std::function json_func_{nullptr}; std::vector response_triggers_; + + size_t max_response_buffer_size_{SIZE_MAX}; }; } // namespace http_request } // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp new file mode 100644 index 0000000000..248a85a439 --- /dev/null +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -0,0 +1,161 @@ +#include "http_request_arduino.h" + +#ifdef USE_ARDUINO + +#include "esphome/components/network/util.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#include "watchdog.h" + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.arduino"; + +std::shared_ptr HttpRequestArduino::start(std::string url, std::string method, std::string body, + std::list
headers) { + if (!network::is_connected()) { + this->status_momentary_error("failed", 1000); + ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); + return nullptr; + } + + std::shared_ptr container = std::make_shared(); + container->set_parent(this); + + const uint32_t start = millis(); + + bool secure = url.find("https:") != std::string::npos; + container->set_secure(secure); + + watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + +#if defined(USE_ESP8266) + std::unique_ptr stream_ptr; +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS + if (secure) { + ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); + stream_ptr = std::make_unique(); + WiFiClientSecure *secure_client = static_cast(stream_ptr.get()); + secure_client->setBufferSizes(512, 512); + secure_client->setInsecure(); + } else { + stream_ptr = std::make_unique(); + } +#else + ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); + if (secure) { + ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); + return nullptr; + } + stream_ptr = std::make_unique(); +#endif // USE_HTTP_REQUEST_ESP8266_HTTPS + +#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) + if (!secure) { + ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " + "in your YAML, or use HTTPS"); + } +#endif // USE_ARDUINO_VERSION_CODE + + container->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + bool status = container->client_.begin(*stream_ptr, url.c_str()); + +#elif defined(USE_RP2040) + if (secure) { + container->client_.setInsecure(); + } + bool status = container->client_.begin(url.c_str()); +#elif defined(USE_ESP32) + bool status = container->client_.begin(url.c_str()); +#endif + + App.feed_wdt(); + + if (!status) { + ESP_LOGW(TAG, "HTTP Request failed; URL: %s", url.c_str()); + container->end(); + this->status_momentary_error("failed", 1000); + return nullptr; + } + + container->client_.setReuse(true); + container->client_.setTimeout(this->timeout_); +#if defined(USE_ESP32) + container->client_.setConnectTimeout(this->timeout_); +#endif + + if (this->useragent_ != nullptr) { + container->client_.setUserAgent(this->useragent_); + } + for (const auto &header : headers) { + container->client_.addHeader(header.name, header.value, false, true); + } + + // returned needed headers must be collected before the requests + static const char *header_keys[] = {"Content-Length", "Content-Type"}; + static const size_t HEADER_COUNT = sizeof(header_keys) / sizeof(header_keys[0]); + container->client_.collectHeaders(header_keys, HEADER_COUNT); + + container->status_code = container->client_.sendRequest(method.c_str(), body.c_str()); + if (container->status_code < 0) { + ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s", url.c_str(), + HTTPClient::errorToString(container->status_code).c_str()); + this->status_momentary_error("failed", 1000); + container->end(); + return nullptr; + } + + if (container->status_code < 200 || container->status_code >= 300) { + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); + this->status_momentary_error("failed", 1000); + container->end(); + return nullptr; + } + + int content_length = container->client_.getSize(); + ESP_LOGD(TAG, "Content-Length: %d", content_length); + container->content_length = (size_t) content_length; + container->duration_ms = millis() - start; + + return container; +} + +int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + WiFiClient *stream_ptr = this->client_.getStreamPtr(); + if (stream_ptr == nullptr) { + ESP_LOGE(TAG, "Stream pointer vanished!"); + return -1; + } + + int available_data = stream_ptr->available(); + int bufsize = std::min(max_len, std::min(this->content_length - this->bytes_read_, (size_t) available_data)); + + if (bufsize == 0) { + this->duration_ms += (millis() - start); + return 0; + } + + App.feed_wdt(); + int read_len = stream_ptr->readBytes(buf, bufsize); + this->bytes_read_ += read_len; + + this->duration_ms += (millis() - start); + + return read_len; +} + +void HttpContainerArduino::end() { + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + this->client_.end(); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h new file mode 100644 index 0000000000..dfdf4a35e2 --- /dev/null +++ b/esphome/components/http_request/http_request_arduino.h @@ -0,0 +1,40 @@ +#pragma once + +#include "http_request.h" + +#ifdef USE_ARDUINO + +#if defined(USE_ESP32) || defined(USE_RP2040) +#include +#endif +#ifdef USE_ESP8266 +#include +#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS +#include +#endif +#endif + +namespace esphome { +namespace http_request { + +class HttpRequestArduino; +class HttpContainerArduino : public HttpContainer { + public: + int read(uint8_t *buf, size_t max_len) override; + void end() override; + + protected: + friend class HttpRequestArduino; + HTTPClient client_{}; +}; + +class HttpRequestArduino : public HttpRequestComponent { + public: + std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) override; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ARDUINO diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp new file mode 100644 index 0000000000..138e0438f4 --- /dev/null +++ b/esphome/components/http_request/http_request_idf.cpp @@ -0,0 +1,155 @@ +#include "http_request_idf.h" + +#ifdef USE_ESP_IDF + +#include "esphome/components/network/util.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" + +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#include "watchdog.h" + +namespace esphome { +namespace http_request { + +static const char *const TAG = "http_request.idf"; + +std::shared_ptr HttpRequestIDF::start(std::string url, std::string method, std::string body, + std::list
headers) { + if (!network::is_connected()) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed; Not connected to network"); + return nullptr; + } + + esp_http_client_method_t method_idf; + if (method == "GET") { + method_idf = HTTP_METHOD_GET; + } else if (method == "POST") { + method_idf = HTTP_METHOD_POST; + } else if (method == "PUT") { + method_idf = HTTP_METHOD_PUT; + } else if (method == "DELETE") { + method_idf = HTTP_METHOD_DELETE; + } else if (method == "PATCH") { + method_idf = HTTP_METHOD_PATCH; + } else { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed; Unsupported method"); + return nullptr; + } + + bool secure = url.find("https:") != std::string::npos; + + esp_http_client_config_t config = {}; + + config.url = url.c_str(); + config.method = method_idf; + config.timeout_ms = this->timeout_; + config.disable_auto_redirect = !this->follow_redirects_; + config.max_redirection_count = this->redirect_limit_; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + if (secure) { + config.crt_bundle_attach = esp_crt_bundle_attach; + } +#endif + + if (this->useragent_ != nullptr) { + config.user_agent = this->useragent_; + } + + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); + + esp_http_client_handle_t client = esp_http_client_init(&config); + + std::shared_ptr container = std::make_shared(client); + container->set_parent(this); + + container->set_secure(secure); + + for (const auto &header : headers) { + esp_http_client_set_header(client, header.name, header.value); + } + + int body_len = body.length(); + + esp_err_t err = esp_http_client_open(client, body_len); + if (err != ESP_OK) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); + return nullptr; + } + + if (body_len > 0) { + int write_left = body_len; + int write_index = 0; + const char *buf = body.c_str(); + while (body_len > 0) { + int written = esp_http_client_write(client, buf + write_index, write_left); + if (written < 0) { + err = ESP_FAIL; + break; + } + write_left -= written; + write_index += written; + } + } + + if (err != ESP_OK) { + this->status_momentary_error("failed", 1000); + ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); + esp_http_client_cleanup(client); + return nullptr; + } + + container->content_length = esp_http_client_fetch_headers(client); + const auto status_code = esp_http_client_get_status_code(client); + container->status_code = status_code; + + if (status_code < 200 || status_code >= 300) { + ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), status_code); + this->status_momentary_error("failed", 1000); + esp_http_client_cleanup(client); + return nullptr; + } + container->duration_ms = millis() - start; + return container; +} + +int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { + const uint32_t start = millis(); + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + int bufsize = std::min(max_len, this->content_length - this->bytes_read_); + + if (bufsize == 0) { + this->duration_ms += (millis() - start); + return 0; + } + + App.feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); + this->bytes_read_ += read_len; + + this->duration_ms += (millis() - start); + + return read_len; +} + +void HttpContainerIDF::end() { + watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); + + esp_http_client_close(this->client_); + esp_http_client_cleanup(this->client_); +} + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h new file mode 100644 index 0000000000..79f850a636 --- /dev/null +++ b/esphome/components/http_request/http_request_idf.h @@ -0,0 +1,34 @@ +#pragma once + +#include "http_request.h" + +#ifdef USE_ESP_IDF + +#include +#include +#include +#include + +namespace esphome { +namespace http_request { + +class HttpContainerIDF : public HttpContainer { + public: + HttpContainerIDF(esp_http_client_handle_t client) : client_(client) {} + int read(uint8_t *buf, size_t max_len) override; + void end() override; + + protected: + esp_http_client_handle_t client_; +}; + +class HttpRequestIDF : public HttpRequestComponent { + public: + std::shared_ptr start(std::string url, std::string method, std::string body, + std::list
headers) override; +}; + +} // namespace http_request +} // namespace esphome + +#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/__init__.py b/esphome/components/http_request/ota/__init__.py index 6a56fac83a..0ef1fc2348 100644 --- a/esphome/components/http_request/ota/__init__.py +++ b/esphome/components/http_request/ota/__init__.py @@ -2,92 +2,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.const import ( - CONF_ESP8266_DISABLE_SSL_SUPPORT, CONF_ID, CONF_PASSWORD, - CONF_TIMEOUT, CONF_URL, CONF_USERNAME, ) -from esphome.components import esp32 from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent -from esphome.core import CORE, coroutine_with_priority -from .. import http_request_ns +from esphome.core import coroutine_with_priority +from .. import CONF_HTTP_REQUEST_ID, http_request_ns, HttpRequestComponent CODEOWNERS = ["@oarcher"] AUTO_LOAD = ["md5"] -DEPENDENCIES = ["network"] +DEPENDENCIES = ["network", "http_request"] CONF_MD5 = "md5" CONF_MD5_URL = "md5_url" -CONF_VERIFY_SSL = "verify_ssl" -CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" OtaHttpRequestComponent = http_request_ns.class_( "OtaHttpRequestComponent", OTAComponent ) -OtaHttpRequestComponentArduino = http_request_ns.class_( - "OtaHttpRequestComponentArduino", OtaHttpRequestComponent -) -OtaHttpRequestComponentIDF = http_request_ns.class_( - "OtaHttpRequestComponentIDF", OtaHttpRequestComponent -) OtaHttpRequestComponentFlashAction = http_request_ns.class_( "OtaHttpRequestComponentFlashAction", automation.Action ) - -def validate_ssl_verification(config): - error_message = "" - - if CORE.is_esp32: - if not CORE.using_esp_idf and config[CONF_VERIFY_SSL]: - error_message = "ESPHome supports certificate verification only via ESP-IDF" - - if CORE.is_rp2040 and config[CONF_VERIFY_SSL]: - error_message = "ESPHome does not support certificate verification in Arduino" - - if ( - CORE.is_esp8266 - and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT] - and config[CONF_VERIFY_SSL] - ): - error_message = "ESPHome does not support certificate verification in Arduino" - - if len(error_message) > 0: - raise cv.Invalid( - f"{error_message}. Set '{CONF_VERIFY_SSL}: false' to skip certificate validation and allow less secure HTTPS connections." - ) - - return config - - -def _declare_request_class(value): - if CORE.using_esp_idf: - return cv.declare_id(OtaHttpRequestComponentIDF)(value) - - if CORE.is_esp8266 or CORE.is_esp32 or CORE.is_rp2040: - return cv.declare_id(OtaHttpRequestComponentArduino)(value) - return NotImplementedError - - CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.GenerateID(): _declare_request_class, - cv.SplitDefault(CONF_ESP8266_DISABLE_SSL_SUPPORT, esp8266=False): cv.All( - cv.only_on_esp8266, cv.boolean - ), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, - cv.Optional( - CONF_TIMEOUT, default="5min" - ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_WATCHDOG_TIMEOUT): cv.All( - cv.Any(cv.only_on_esp32, cv.only_on_rp2040), - cv.positive_not_null_time_period, - cv.positive_time_period_milliseconds, - ), + cv.GenerateID(): cv.declare_id(OtaHttpRequestComponent), + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), } ) .extend(BASE_OTA_SCHEMA) @@ -98,7 +41,6 @@ CONFIG_SCHEMA = cv.All( esp_idf=cv.Version(0, 0, 0), rp2040_arduino=cv.Version(0, 0, 0), ), - validate_ssl_verification, ) @@ -106,41 +48,8 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ota_to_code(var, config) - - cg.add(var.set_timeout(config[CONF_TIMEOUT])) - - if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): - cg.add_define( - "USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT", - timeout_ms, - ) - - if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]: - cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS") - - if CORE.is_esp32: - if CORE.using_esp_idf: - esp32.add_idf_sdkconfig_option( - "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", - config.get(CONF_VERIFY_SSL), - ) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_INSECURE", - not config.get(CONF_VERIFY_SSL), - ) - esp32.add_idf_sdkconfig_option( - "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", - not config.get(CONF_VERIFY_SSL), - ) - else: - cg.add_library("WiFiClientSecure", None) - cg.add_library("HTTPClient", None) - if CORE.is_esp8266: - cg.add_library("ESP8266HTTPClient", None) - if CORE.is_rp2040 and CORE.using_arduino: - cg.add_library("HTTPClient", None) - await cg.register_component(var, config) + await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID]) OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( @@ -148,7 +57,9 @@ OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( { cv.GenerateID(): cv.use_id(OtaHttpRequestComponent), cv.Optional(CONF_MD5_URL): cv.templatable(cv.url), - cv.Optional(CONF_MD5): cv.templatable(cv.string), + cv.Optional(CONF_MD5): cv.templatable( + cv.All(cv.string, cv.Length(min=32, max=32)) + ), cv.Optional(CONF_PASSWORD): cv.templatable(cv.string), cv.Optional(CONF_USERNAME): cv.templatable(cv.string), cv.Required(CONF_URL): cv.templatable(cv.url), @@ -159,7 +70,7 @@ OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( @automation.register_action( - "ota_http_request.flash", + "ota.http_request.flash", OtaHttpRequestComponentFlashAction, OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA, ) diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index cf0816c858..a41f552baf 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -1,16 +1,16 @@ #include "ota_http_request.h" -#include "watchdog.h" +#include "../watchdog.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" #include "esphome/components/md5/md5.h" +#include "esphome/components/ota/ota_backend.h" #include "esphome/components/ota/ota_backend_arduino_esp32.h" #include "esphome/components/ota/ota_backend_arduino_esp8266.h" #include "esphome/components/ota/ota_backend_arduino_rp2040.h" #include "esphome/components/ota/ota_backend_esp_idf.h" -#include "esphome/components/ota/ota_backend.h" namespace esphome { namespace http_request { @@ -21,25 +21,7 @@ void OtaHttpRequestComponent::setup() { #endif } -void OtaHttpRequestComponent::dump_config() { - ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request:"); - ESP_LOGCONFIG(TAG, " Timeout: %llus", this->timeout_ / 1000); -#ifdef USE_ESP8266 -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - ESP_LOGCONFIG(TAG, " ESP8266 SSL support: No"); -#else - ESP_LOGCONFIG(TAG, " ESP8266 SSL support: Yes"); -#endif -#endif -#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - ESP_LOGCONFIG(TAG, " TLS server verification: Yes"); -#else - ESP_LOGCONFIG(TAG, " TLS server verification: No"); -#endif -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT - ESP_LOGCONFIG(TAG, " Watchdog timeout: %ds", USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT / 1000); -#endif -}; +void OtaHttpRequestComponent::dump_config() { ESP_LOGCONFIG(TAG, "Over-The-Air updates via HTTP request"); }; void OtaHttpRequestComponent::set_md5_url(const std::string &url) { if (!this->validate_url_(url)) { @@ -58,20 +40,6 @@ void OtaHttpRequestComponent::set_url(const std::string &url) { this->url_ = url; } -bool OtaHttpRequestComponent::check_status() { - // status can be -1, or HTTP status code - if (this->status_ < 100) { - ESP_LOGE(TAG, "HTTP server did not respond (error %d)", this->status_); - return false; - } - if (this->status_ >= 310) { - ESP_LOGE(TAG, "HTTP error %d", this->status_); - return false; - } - ESP_LOGV(TAG, "HTTP status %d", this->status_); - return true; -} - void OtaHttpRequestComponent::flash() { if (this->url_.empty()) { ESP_LOGE(TAG, "URL not set; cannot start update"); @@ -104,17 +72,18 @@ void OtaHttpRequestComponent::flash() { } } -void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend) { +void OtaHttpRequestComponent::cleanup_(std::unique_ptr backend, + const std::shared_ptr &container) { if (this->update_started_) { ESP_LOGV(TAG, "Aborting OTA backend"); backend->abort(); } ESP_LOGV(TAG, "Aborting HTTP connection"); - this->http_end(); + container->end(); }; uint8_t OtaHttpRequestComponent::do_ota_() { - uint8_t buf[this->http_recv_buffer_ + 1]; + uint8_t buf[OtaHttpRequestComponent::HTTP_RECV_BUFFER + 1]; uint32_t last_progress = 0; uint32_t update_start_time = millis(); md5::MD5Digest md5_receive; @@ -132,9 +101,10 @@ uint8_t OtaHttpRequestComponent::do_ota_() { } ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); ESP_LOGI(TAG, "Connecting to: %s", this->url_.c_str()); - this->http_init(url_with_auth); - if (!this->check_status()) { - this->http_end(); + + auto container = this->parent_->get(url_with_auth); + + if (container == nullptr) { return OTA_CONNECTION_ERROR; } @@ -144,18 +114,18 @@ uint8_t OtaHttpRequestComponent::do_ota_() { ESP_LOGV(TAG, "OTA backend begin"); auto backend = ota::make_ota_backend(); - auto error_code = backend->begin(this->body_length_); + auto error_code = backend->begin(container->content_length); if (error_code != ota::OTA_RESPONSE_OK) { ESP_LOGW(TAG, "backend->begin error: %d", error_code); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return error_code; } - this->bytes_read_ = 0; - while (this->bytes_read_ < this->body_length_) { + while (container->get_bytes_read() < container->content_length) { // read a maximum of chunk_size bytes into buf. (real read size returned) - int bufsize = this->http_read(buf, this->http_recv_buffer_); - ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", this->bytes_read_, this->body_length_, bufsize); + int bufsize = container->read(buf, OtaHttpRequestComponent::HTTP_RECV_BUFFER); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize = %i", container->get_bytes_read(), + container->content_length, bufsize); // feed watchdog and give other tasks a chance to run App.feed_wdt(); @@ -163,9 +133,9 @@ uint8_t OtaHttpRequestComponent::do_ota_() { if (bufsize < 0) { ESP_LOGE(TAG, "Stream closed"); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return OTA_CONNECTION_ERROR; - } else if (bufsize > 0 && bufsize <= this->http_recv_buffer_) { + } else if (bufsize > 0 && bufsize <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { // add read bytes to MD5 md5_receive.add(buf, bufsize); @@ -176,16 +146,16 @@ uint8_t OtaHttpRequestComponent::do_ota_() { // error code explanation available at // https://github.com/esphome/esphome/blob/dev/esphome/components/ota/ota_backend.h ESP_LOGE(TAG, "Error code (%02X) writing binary data to flash at offset %d and size %d", error_code, - this->bytes_read_ - bufsize, this->body_length_); - this->cleanup_(std::move(backend)); + container->get_bytes_read() - bufsize, container->content_length); + this->cleanup_(std::move(backend), container); return error_code; } } uint32_t now = millis(); - if ((now - last_progress > 1000) or (this->bytes_read_ == this->body_length_)) { + if ((now - last_progress > 1000) or (container->get_bytes_read() == container->content_length)) { last_progress = now; - float percentage = this->bytes_read_ * 100.0f / this->body_length_; + float percentage = container->get_bytes_read() * 100.0f / container->content_length; ESP_LOGD(TAG, "Progress: %0.1f%%", percentage); #ifdef USE_OTA_STATE_CALLBACK this->state_callback_.call(ota::OTA_IN_PROGRESS, percentage, 0); @@ -201,13 +171,13 @@ uint8_t OtaHttpRequestComponent::do_ota_() { this->md5_computed_ = md5_receive_str.get(); if (strncmp(this->md5_computed_.c_str(), this->md5_expected_.c_str(), MD5_SIZE) != 0) { ESP_LOGE(TAG, "MD5 computed: %s - Aborting due to MD5 mismatch", this->md5_computed_.c_str()); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; } else { backend->set_update_md5(md5_receive_str.get()); } - this->http_end(); + container->end(); // feed watchdog and give other tasks a chance to run App.feed_wdt(); @@ -217,7 +187,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { error_code = backend->end(); if (error_code != ota::OTA_RESPONSE_OK) { ESP_LOGW(TAG, "Error ending update! error_code: %d", error_code); - this->cleanup_(std::move(backend)); + this->cleanup_(std::move(backend), container); return error_code; } @@ -256,28 +226,32 @@ bool OtaHttpRequestComponent::http_get_md5_() { ESP_LOGVV(TAG, "url_with_auth: %s", url_with_auth.c_str()); ESP_LOGI(TAG, "Connecting to: %s", this->md5_url_.c_str()); - this->http_init(url_with_auth); - if (!this->check_status()) { - this->http_end(); + auto container = this->parent_->get(url_with_auth); + if (container == nullptr) { + ESP_LOGE(TAG, "Failed to connect to MD5 URL"); return false; } - int length = this->body_length_; - if (length < 0) { - this->http_end(); + size_t length = container->content_length; + if (length == 0) { + container->end(); return false; } if (length < MD5_SIZE) { - ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, - this->body_length_); - this->http_end(); + ESP_LOGE(TAG, "MD5 file must be %u bytes; %u bytes reported by HTTP server. Aborting", MD5_SIZE, length); + container->end(); return false; } - this->bytes_read_ = 0; this->md5_expected_.resize(MD5_SIZE); - auto read_len = this->http_read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); - this->http_end(); + int read_len = 0; + while (container->get_bytes_read() < MD5_SIZE) { + read_len = container->read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); + App.feed_wdt(); + yield(); + } + container->end(); + ESP_LOGV(TAG, "Read len: %u, MD5 expected: %u", read_len, MD5_SIZE); return read_len == MD5_SIZE; } diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 9fbdf2ec25..91c7085517 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -1,13 +1,16 @@ #pragma once +#include "esphome/components/ota/ota_backend.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" -#include "esphome/components/ota/ota_backend.h" +#include "esphome/core/helpers.h" #include #include #include +#include "../http_request.h" + namespace esphome { namespace http_request { @@ -20,7 +23,7 @@ enum OtaHttpRequestError : uint8_t { OTA_CONNECTION_ERROR = 0x12, }; -class OtaHttpRequestComponent : public ota::OTAComponent { +class OtaHttpRequestComponent : public ota::OTAComponent, public Parented { public: void setup() override; void dump_config() override; @@ -29,27 +32,19 @@ class OtaHttpRequestComponent : public ota::OTAComponent { void set_md5_url(const std::string &md5_url); void set_md5(const std::string &md5) { this->md5_expected_ = md5; } void set_password(const std::string &password) { this->password_ = password; } - void set_timeout(const uint64_t timeout) { this->timeout_ = timeout; } void set_url(const std::string &url); void set_username(const std::string &username) { this->username_ = username; } std::string md5_computed() { return this->md5_computed_; } std::string md5_expected() { return this->md5_expected_; } - bool check_status(); - void flash(); - virtual void http_init(const std::string &url){}; - virtual int http_read(uint8_t *buf, size_t len) { return 0; }; - virtual void http_end(){}; - protected: - void cleanup_(std::unique_ptr backend); + void cleanup_(std::unique_ptr backend, const std::shared_ptr &container); uint8_t do_ota_(); std::string get_url_with_auth_(const std::string &url); bool http_get_md5_(); - bool secure_() { return this->url_.find("https:") != std::string::npos; }; bool validate_url_(const std::string &url); std::string md5_computed_{}; @@ -58,14 +53,9 @@ class OtaHttpRequestComponent : public ota::OTAComponent { std::string password_{}; std::string username_{}; std::string url_{}; - size_t body_length_ = 0; - size_t bytes_read_ = 0; int status_ = -1; - uint64_t timeout_ = 0; bool update_started_ = false; - const uint16_t http_recv_buffer_ = 256; // the firmware GET chunk size - const uint16_t max_http_recv_buffer_ = 512; // internal max http buffer size must be > HTTP_RECV_BUFFER_ (TLS - // overhead) and must be a power of two from 512 to 4096 + static const uint16_t HTTP_RECV_BUFFER = 256; // the firmware GET chunk size }; } // namespace http_request diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.cpp b/esphome/components/http_request/ota/ota_http_request_arduino.cpp deleted file mode 100644 index d1dc638d5e..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_arduino.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "ota_http_request.h" -#include "watchdog.h" - -#ifdef USE_ARDUINO -#include "ota_http_request_arduino.h" -#include "esphome/core/defines.h" -#include "esphome/core/log.h" -#include "esphome/core/application.h" -#include "esphome/components/network/util.h" -#include "esphome/components/md5/md5.h" - -namespace esphome { -namespace http_request { - -struct Header { - const char *name; - const char *value; -}; - -void OtaHttpRequestComponentArduino::http_init(const std::string &url) { - const char *header_keys[] = {"Content-Length", "Content-Type"}; - const size_t header_count = sizeof(header_keys) / sizeof(header_keys[0]); - watchdog::WatchdogManager wdts; - -#ifdef USE_ESP8266 - if (this->stream_ptr_ == nullptr && this->set_stream_ptr_()) { - ESP_LOGE(TAG, "Unable to set client"); - return; - } -#endif // USE_ESP8266 - -#ifdef USE_RP2040 - this->client_.setInsecure(); -#endif - - App.feed_wdt(); - -#if defined(USE_ESP32) || defined(USE_RP2040) - this->status_ = this->client_.begin(url.c_str()); -#endif -#ifdef USE_ESP8266 - this->client_.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - this->status_ = this->client_.begin(*this->stream_ptr_, url.c_str()); -#endif - - if (!this->status_) { - this->client_.end(); - return; - } - - this->client_.setReuse(true); - - // returned needed headers must be collected before the requests - this->client_.collectHeaders(header_keys, header_count); - - // HTTP GET - this->status_ = this->client_.GET(); - - this->body_length_ = (size_t) this->client_.getSize(); - -#if defined(USE_ESP32) || defined(USE_RP2040) - if (this->stream_ptr_ == nullptr) { - this->set_stream_ptr_(); - } -#endif -} - -int OtaHttpRequestComponentArduino::http_read(uint8_t *buf, const size_t max_len) { -#ifdef USE_ESP8266 -#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 1, 0) // && USE_ARDUINO_VERSION_CODE < VERSION_CODE(?, ?, ?) - if (!this->secure_()) { - ESP_LOGW(TAG, "Using HTTP on Arduino version >= 3.1 is **very** slow. Consider setting framework version to 3.0.2 " - "in your YAML, or use HTTPS"); - } -#endif // USE_ARDUINO_VERSION_CODE -#endif // USE_ESP8266 - - watchdog::WatchdogManager wdts; - - // Since arduino8266 >= 3.1 using this->stream_ptr_ is broken (https://github.com/esp8266/Arduino/issues/9035) - WiFiClient *stream_ptr = this->client_.getStreamPtr(); - if (stream_ptr == nullptr) { - ESP_LOGE(TAG, "Stream pointer vanished!"); - return -1; - } - - int available_data = stream_ptr->available(); - int bufsize = std::min((int) max_len, available_data); - if (bufsize > 0) { - stream_ptr->readBytes(buf, bufsize); - this->bytes_read_ += bufsize; - buf[bufsize] = '\0'; // not fed to ota - } - - return bufsize; -} - -void OtaHttpRequestComponentArduino::http_end() { - watchdog::WatchdogManager wdts; - this->client_.end(); -} - -int OtaHttpRequestComponentArduino::set_stream_ptr_() { -#ifdef USE_ESP8266 -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS - if (this->secure_()) { - ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); - this->stream_ptr_ = std::make_unique(); - WiFiClientSecure *secure_client = static_cast(this->stream_ptr_.get()); - secure_client->setBufferSizes(this->max_http_recv_buffer_, 512); - secure_client->setInsecure(); - } else { - this->stream_ptr_ = std::make_unique(); - } -#else - ESP_LOGV(TAG, "ESP8266 HTTP connection with WiFiClient"); - if (this->secure_()) { - ESP_LOGE(TAG, "Can't use HTTPS connection with esp8266_disable_ssl_support"); - return -1; - } - this->stream_ptr_ = std::make_unique(); -#endif // USE_HTTP_REQUEST_ESP8266_HTTPS -#endif // USE_ESP8266 - -#if defined(USE_ESP32) || defined(USE_RP2040) - this->stream_ptr_ = std::unique_ptr(this->client_.getStreamPtr()); -#endif - return 0; -} - -} // namespace http_request -} // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_arduino.h b/esphome/components/http_request/ota/ota_http_request_arduino.h deleted file mode 100644 index 02bc046520..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_arduino.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "ota_http_request.h" - -#ifdef USE_ARDUINO -#include "esphome/core/automation.h" -#include "esphome/core/component.h" -#include "esphome/core/defines.h" - -#include -#include -#include - -#if defined(USE_ESP32) || defined(USE_RP2040) -#include -#endif -#ifdef USE_ESP8266 -#include -#ifdef USE_HTTP_REQUEST_ESP8266_HTTPS -#include -#endif -#endif - -namespace esphome { -namespace http_request { - -class OtaHttpRequestComponentArduino : public OtaHttpRequestComponent { - public: - void http_init(const std::string &url) override; - int http_read(uint8_t *buf, size_t len) override; - void http_end() override; - - protected: - int set_stream_ptr_(); - HTTPClient client_{}; - std::unique_ptr stream_ptr_; -}; - -} // namespace http_request -} // namespace esphome - -#endif // USE_ARDUINO diff --git a/esphome/components/http_request/ota/ota_http_request_idf.cpp b/esphome/components/http_request/ota/ota_http_request_idf.cpp deleted file mode 100644 index 9fa565d9bb..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_idf.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "ota_http_request_idf.h" -#include "watchdog.h" - -#ifdef USE_ESP_IDF -#include "esphome/core/application.h" -#include "esphome/core/defines.h" -#include "esphome/core/log.h" -#include "esphome/components/md5/md5.h" -#include "esphome/components/network/util.h" - -#include "esp_event.h" -#include "esp_http_client.h" -#include "esp_idf_version.h" -#include "esp_log.h" -#include "esp_netif.h" -#include "esp_system.h" -#include "esp_task_wdt.h" -#include "esp_tls.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs_flash.h" - -#include -#include -#include -#include -#include -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE -#include "esp_crt_bundle.h" -#endif - -namespace esphome { -namespace http_request { - -void OtaHttpRequestComponentIDF::http_init(const std::string &url) { - App.feed_wdt(); -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" - esp_http_client_config_t config = {nullptr}; - config.url = url.c_str(); - config.method = HTTP_METHOD_GET; - config.timeout_ms = (int) this->timeout_; - config.buffer_size = this->max_http_recv_buffer_; - config.auth_type = HTTP_AUTH_TYPE_BASIC; - config.max_authorization_retries = -1; -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - if (this->secure_()) { - config.crt_bundle_attach = esp_crt_bundle_attach; - } -#endif -#pragma GCC diagnostic pop - - watchdog::WatchdogManager wdts; - this->client_ = esp_http_client_init(&config); - if ((this->status_ = esp_http_client_open(this->client_, 0)) == ESP_OK) { - this->body_length_ = esp_http_client_fetch_headers(this->client_); - this->status_ = esp_http_client_get_status_code(this->client_); - } -} - -int OtaHttpRequestComponentIDF::http_read(uint8_t *buf, const size_t max_len) { - watchdog::WatchdogManager wdts; - int bufsize = std::min(max_len, this->body_length_ - this->bytes_read_); - - App.feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); - if (read_len > 0) { - this->bytes_read_ += bufsize; - buf[bufsize] = '\0'; // not fed to ota - } - - return read_len; -} - -void OtaHttpRequestComponentIDF::http_end() { - watchdog::WatchdogManager wdts; - - esp_http_client_close(this->client_); - esp_http_client_cleanup(this->client_); -} - -} // namespace http_request -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/ota_http_request_idf.h b/esphome/components/http_request/ota/ota_http_request_idf.h deleted file mode 100644 index 9783b2a3e1..0000000000 --- a/esphome/components/http_request/ota/ota_http_request_idf.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "ota_http_request.h" - -#ifdef USE_ESP_IDF -#include "esp_http_client.h" - -namespace esphome { -namespace http_request { - -class OtaHttpRequestComponentIDF : public OtaHttpRequestComponent { - public: - void http_init(const std::string &url) override; - int http_read(uint8_t *buf, size_t len) override; - void http_end() override; - - protected: - esp_http_client_handle_t client_{}; -}; - -} // namespace http_request -} // namespace esphome - -#endif // USE_ESP_IDF diff --git a/esphome/components/http_request/ota/watchdog.cpp b/esphome/components/http_request/watchdog.cpp similarity index 79% rename from esphome/components/http_request/ota/watchdog.cpp rename to esphome/components/http_request/watchdog.cpp index 663c9afaac..e609feb4dd 100644 --- a/esphome/components/http_request/ota/watchdog.cpp +++ b/esphome/components/http_request/watchdog.cpp @@ -1,7 +1,5 @@ #include "watchdog.h" -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT - #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -20,14 +18,22 @@ namespace esphome { namespace http_request { namespace watchdog { -static const char *const TAG = "watchdog.http_request.ota"; +static const char *const TAG = "http_request.watchdog"; -WatchdogManager::WatchdogManager() { +WatchdogManager::WatchdogManager(uint32_t timeout_ms) : timeout_ms_(timeout_ms) { + if (timeout_ms == 0) { + return; + } this->saved_timeout_ms_ = this->get_timeout_(); - this->set_timeout_(USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT); + this->set_timeout_(timeout_ms); } -WatchdogManager::~WatchdogManager() { this->set_timeout_(this->saved_timeout_ms_); } +WatchdogManager::~WatchdogManager() { + if (this->timeout_ms_ == 0) { + return; + } + this->set_timeout_(this->saved_timeout_ms_); +} void WatchdogManager::set_timeout_(uint32_t timeout_ms) { ESP_LOGV(TAG, "Adjusting WDT to %" PRIu32 "ms", timeout_ms); @@ -68,4 +74,3 @@ uint32_t WatchdogManager::get_timeout_() { } // namespace watchdog } // namespace http_request } // namespace esphome -#endif diff --git a/esphome/components/http_request/ota/watchdog.h b/esphome/components/http_request/watchdog.h similarity index 84% rename from esphome/components/http_request/ota/watchdog.h rename to esphome/components/http_request/watchdog.h index 0a09dcd6fa..9b54ae6c82 100644 --- a/esphome/components/http_request/ota/watchdog.h +++ b/esphome/components/http_request/watchdog.h @@ -9,9 +9,8 @@ namespace http_request { namespace watchdog { class WatchdogManager { -#ifdef USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT public: - WatchdogManager(); + WatchdogManager(uint32_t timeout_ms); ~WatchdogManager(); private: @@ -19,7 +18,7 @@ class WatchdogManager { void set_timeout_(uint32_t timeout_ms); uint32_t saved_timeout_ms_{0}; -#endif + uint32_t timeout_ms_{0}; }; } // namespace watchdog diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 0f1b7f236b..bd79d3b2f9 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -8,6 +8,7 @@ double = global_ns.namespace("double") bool_ = global_ns.namespace("bool") int_ = global_ns.namespace("int") std_ns = global_ns.namespace("std") +std_shared_ptr = std_ns.class_("shared_ptr") std_string = std_ns.class_("string") std_vector = std_ns.class_("vector") uint8 = global_ns.namespace("uint8_t") diff --git a/tests/components/http_request/common.yaml b/tests/components/http_request/common.yaml new file mode 100644 index 0000000000..2b6996c0b9 --- /dev/null +++ b/tests/components/http_request/common.yaml @@ -0,0 +1,75 @@ +substitutions: + verify_ssl: "true" + +wifi: + ssid: MySSID + password: password1 + +esphome: + on_boot: + then: + - http_request.get: + url: https://esphome.io + headers: + Content-Type: application/json + on_response: + then: + - logger.log: + format: "Response status: %d, Duration: %u ms" + args: + - response->status_code + - response->duration_ms + - http_request.post: + url: https://esphome.io + headers: + Content-Type: application/json + json: + key: value + - http_request.send: + method: PUT + url: https://esphome.io + headers: + Content-Type: application/json + body: "Some data" + +http_request: + useragent: esphome/tagreader + timeout: 10s + verify_ssl: ${verify_ssl} + +ota: + - platform: http_request + on_begin: + then: + - logger.log: "OTA start" + on_progress: + then: + - logger.log: + format: "OTA progress %0.1f%%" + args: ["x"] + on_end: + then: + - logger.log: "OTA end" + on_error: + then: + - logger.log: + format: "OTA update error %d" + args: ["x"] + on_state_change: + then: + lambda: 'ESP_LOGD("ota", "State %d", state);' + +button: + - platform: template + name: Firmware update + on_press: + then: + - ota.http_request.flash: + md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 + url: http://my.ha.net:8123/local/esphome/firmware.bin + + - ota.http_request.flash: + md5: 0123456789abcdef0123456789abcdef + url: http://my.ha.net:8123/local/esphome/firmware.bin + + - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/common_http_request.yaml b/tests/components/http_request/common_http_request.yaml deleted file mode 100644 index b00768c736..0000000000 --- a/tests/components/http_request/common_http_request.yaml +++ /dev/null @@ -1,33 +0,0 @@ -esphome: - on_boot: - then: - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - on_response: - then: - - logger.log: - format: 'Response status: %d, Duration: %u ms' - args: - - status_code - - duration_ms - - http_request.post: - url: https://esphome.io - headers: - Content-Type: application/json - json: - key: value - verify_ssl: false - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: "Some data" - verify_ssl: false - -http_request: - useragent: esphome/tagreader - timeout: 10s diff --git a/tests/components/http_request/common_ota.yaml b/tests/components/http_request/common_ota.yaml deleted file mode 100644 index 10e7d54c3f..0000000000 --- a/tests/components/http_request/common_ota.yaml +++ /dev/null @@ -1,36 +0,0 @@ -wifi: - ssid: MySSID - password: password1 - -ota: - - platform: http_request - verify_ssl: ${verify_ssl} - on_begin: - then: - - logger.log: "OTA start" - on_progress: - then: - - logger.log: - format: "OTA progress %0.1f%%" - args: ["x"] - on_end: - then: - - logger.log: "OTA end" - on_error: - then: - - logger.log: - format: "OTA update error %d" - args: ["x"] - on_state_change: - then: - lambda: 'ESP_LOGD("ota", "State %d", state);' - -button: - - platform: template - name: Firmware update - on_press: - then: - - ota_http_request.flash: - md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 - url: http://my.ha.net:8123/local/esphome/firmware.bin - - logger.log: "This message should be not displayed (reboot)" diff --git a/tests/components/http_request/test-nossl.esp8266.yaml b/tests/components/http_request/test-nossl.esp8266.yaml index 65116d5550..9fc4706c89 100644 --- a/tests/components/http_request/test-nossl.esp8266.yaml +++ b/tests/components/http_request/test-nossl.esp8266.yaml @@ -1,38 +1,4 @@ -<<: !include common_http_request.yaml +<<: !include common.yaml -wifi: - ssid: MySSID - password: password1 - -ota: - - platform: http_request - esp8266_disable_ssl_support: true - on_begin: - then: - - logger.log: "OTA start" - on_progress: - then: - - logger.log: - format: "OTA progress %0.1f%%" - args: ["x"] - on_end: - then: - - logger.log: "OTA end" - on_error: - then: - - logger.log: - format: "OTA update error %d" - args: ["x"] - on_state_change: - then: - lambda: 'ESP_LOGD("ota", "State %d", state);' - -button: - - platform: template - name: Firmware update - on_press: - then: - - ota_http_request.flash: - md5_url: http://my.ha.net:8123/local/esphome/firmware.md5 - url: http://my.ha.net:8123/local/esphome/firmware.bin - - logger.log: "This message should be not displayed (reboot)" +http_request: + esp8266_disable_ssl_support: true diff --git a/tests/components/http_request/test.esp32-c3-idf.yaml b/tests/components/http_request/test.esp32-c3-idf.yaml index da629e83a9..ee2f5aa59b 100644 --- a/tests/components/http_request/test.esp32-c3-idf.yaml +++ b/tests/components/http_request/test.esp32-c3-idf.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "true" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32-c3.yaml b/tests/components/http_request/test.esp32-c3.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp32-c3.yaml +++ b/tests/components/http_request/test.esp32-c3.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32-idf.yaml b/tests/components/http_request/test.esp32-idf.yaml index da629e83a9..ee2f5aa59b 100644 --- a/tests/components/http_request/test.esp32-idf.yaml +++ b/tests/components/http_request/test.esp32-idf.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "true" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp32.yaml b/tests/components/http_request/test.esp32.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp32.yaml +++ b/tests/components/http_request/test.esp32.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.esp8266.yaml b/tests/components/http_request/test.esp8266.yaml index 1f597bb500..c1937b5a10 100644 --- a/tests/components/http_request/test.esp8266.yaml +++ b/tests/components/http_request/test.esp8266.yaml @@ -1,5 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_http_request.yaml -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/components/http_request/test.rp2040.yaml b/tests/components/http_request/test.rp2040.yaml index 077e4d82da..c1937b5a10 100644 --- a/tests/components/http_request/test.rp2040.yaml +++ b/tests/components/http_request/test.rp2040.yaml @@ -1,4 +1,4 @@ substitutions: verify_ssl: "false" -<<: !include common_ota.yaml +<<: !include common.yaml diff --git a/tests/test1.yaml b/tests/test1.yaml index c49ff307e5..2dacfda536 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -25,31 +25,6 @@ esphome: then: - lambda: >- ESP_LOGV("main", "ON LOOP!"); - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - - http_request.post: - url: https://esphome.io - verify_ssl: false - json: - key: !lambda |- - return id(${textname}_text).state; - greeting: Hello World - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - on_response: - then: - - logger.log: - format: "Response status: %d" - args: - - status_code build_path: build/test1 packages: @@ -84,10 +59,6 @@ network: mdns: disabled: false -http_request: - useragent: esphome/device - timeout: 10s - mqtt: broker: "192.168.178.84" port: 1883 diff --git a/tests/test3.1.yaml b/tests/test3.1.yaml index 018a4d94f3..c3b078fe67 100644 --- a/tests/test3.1.yaml +++ b/tests/test3.1.yaml @@ -447,26 +447,6 @@ switch: switches: - id: custom_switch name: Custom Switch - on_turn_on: - - http_request.get: - url: https://esphome.io - headers: - Content-Type: application/json - verify_ssl: false - - http_request.post: - url: https://esphome.io - verify_ssl: false - json: - key: !lambda |- - return id(custom_text_sensor).state; - greeting: Hello World - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - platform: template name: open_vent id: open_vent @@ -722,10 +702,6 @@ display: lambda: |- it.printdigit("hello"); -http_request: - useragent: esphome/device - timeout: 10s - button: - platform: output id: output_button diff --git a/tests/test7.yaml b/tests/test7.yaml index b22fbfbcb4..ac193eae4e 100644 --- a/tests/test7.yaml +++ b/tests/test7.yaml @@ -1,7 +1,7 @@ # Tests for ESP32-C3 boards which use toolchain-riscv32-esp --- wifi: - ssid: 'ssid' + ssid: "ssid" network: enable_ipv6: true @@ -12,31 +12,12 @@ esp32: type: arduino esphome: - name: 'on-response-test' - on_boot: - then: - - http_request.send: - method: PUT - url: https://esphome.io - headers: - Content-Type: application/json - body: Some data - verify_ssl: false - on_response: - then: - - logger.log: - format: "Response status: %d" - args: - - status_code + name: test7 logger: debug: -http_request: - useragent: esphome/tagreader - timeout: 10s - sensor: - platform: adc id: adc_sensor_p4 From 6de79d6cfbdf42b5fdc9b1f880b86210900dab5a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:22:41 +1200 Subject: [PATCH 29/30] [i2s_speaker] A few fixes (#6872) --- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 40 +++++++++++++++---- .../i2s_audio/speaker/i2s_audio_speaker.h | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index 546c2c98f7..6b07ecb1b6 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -38,15 +38,22 @@ void I2SAudioSpeaker::start() { ESP_LOGE(TAG, "Cannot start audio, speaker failed to setup"); return; } + if (this->task_created_) { + ESP_LOGW(TAG, "Called start while task has been already created."); + return; + } this->state_ = speaker::STATE_STARTING; } void I2SAudioSpeaker::start_() { + if (this->task_created_) { + return; + } if (!this->parent_->try_lock()) { return; // Waiting for another i2s component to return lock } - this->state_ = speaker::STATE_RUNNING; xTaskCreate(I2SAudioSpeaker::player_task, "speaker_task", 8192, (void *) this, 1, &this->player_task_handle_); + this->task_created_ = true; } void I2SAudioSpeaker::player_task(void *params) { @@ -131,7 +138,16 @@ void I2SAudioSpeaker::player_task(void *params) { (10 / portTICK_PERIOD_MS)); if (err != ESP_OK) { event = {.type = TaskEventType::WARNING, .err = err}; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send WARNING event"); + } + continue; + } + if (bytes_written != sizeof(sample)) { + event = {.type = TaskEventType::WARNING, .err = ESP_FAIL}; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send WARNING event"); + } continue; } remaining--; @@ -139,18 +155,25 @@ void I2SAudioSpeaker::player_task(void *params) { } event.type = TaskEventType::PLAYING; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + event.err = current; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send PLAYING event"); + } + } + + event.type = TaskEventType::STOPPING; + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send STOPPING event"); } i2s_zero_dma_buffer(this_speaker->parent_->get_port()); - event.type = TaskEventType::STOPPING; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); - i2s_driver_uninstall(this_speaker->parent_->get_port()); event.type = TaskEventType::STOPPED; - xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY); + if (xQueueSend(this_speaker->event_queue_, &event, 10 / portTICK_PERIOD_MS) != pdTRUE) { + ESP_LOGW(TAG, "Failed to send STOPPED event"); + } while (true) { delay(10); @@ -181,6 +204,7 @@ void I2SAudioSpeaker::watch_() { break; case TaskEventType::STARTED: ESP_LOGD(TAG, "Started I2S Audio Speaker"); + this->state_ = speaker::STATE_RUNNING; break; case TaskEventType::STOPPING: ESP_LOGD(TAG, "Stopping I2S Audio Speaker"); @@ -191,6 +215,7 @@ void I2SAudioSpeaker::watch_() { case TaskEventType::STOPPED: this->state_ = speaker::STATE_STOPPED; vTaskDelete(this->player_task_handle_); + this->task_created_ = false; this->player_task_handle_ = nullptr; this->parent_->unlock(); xQueueReset(this->buffer_queue_); @@ -208,7 +233,6 @@ void I2SAudioSpeaker::loop() { switch (this->state_) { case speaker::STATE_STARTING: this->start_(); - break; case speaker::STATE_RUNNING: case speaker::STATE_STOPPING: this->watch_(); diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 20c36a69d3..1800feaeec 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -60,7 +60,6 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud protected: void start_(); - // void stop_(); void watch_(); static void player_task(void *params); @@ -70,6 +69,7 @@ class I2SAudioSpeaker : public Component, public speaker::Speaker, public I2SAud QueueHandle_t event_queue_; uint8_t dout_pin_{0}; + bool task_created_{false}; #if SOC_I2S_SUPPORTS_DAC i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; From dceab6ce29493e67caaa8cdadf8cf7f4df063635 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:22:55 +1200 Subject: [PATCH 30/30] [voice_assistant] Write less data to speaker each loop (#6877) --- esphome/components/voice_assistant/voice_assistant.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e4fd2f2e9d..1fa8236cf4 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -428,14 +428,15 @@ void VoiceAssistant::loop() { #ifdef USE_SPEAKER void VoiceAssistant::write_speaker_() { if (this->speaker_buffer_size_ > 0) { - size_t written = this->speaker_->play(this->speaker_buffer_, this->speaker_buffer_size_); + size_t write_chunk = std::min(this->speaker_buffer_size_, 4 * 1024); + size_t written = this->speaker_->play(this->speaker_buffer_, write_chunk); if (written > 0) { memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); this->speaker_buffer_size_ -= written; this->speaker_buffer_index_ -= written; this->set_timeout("speaker-timeout", 5000, [this]() { this->speaker_->stop(); }); } else { - ESP_LOGD(TAG, "Speaker buffer full, trying again next loop"); + ESP_LOGV(TAG, "Speaker buffer full, trying again next loop"); } } } @@ -798,7 +799,7 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { this->speaker_buffer_index_ += msg.data.length(); this->speaker_buffer_size_ += msg.data.length(); this->speaker_bytes_received_ += msg.data.length(); - ESP_LOGD(TAG, "Received audio: %d bytes from API", msg.data.length()); + ESP_LOGV(TAG, "Received audio: %" PRId32 " bytes from API", msg.data.length()); } else { ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); }